webpack 4迁移指南

栏目: JavaScript · 发布时间: 5年前

内容简介:webpack 4 出来也已经一年了,公司的老项目用的还是webpack3,也是时候该升级一波了。说实话webpack4还是有几点挺吸引我的,估计也是感受到了parcel的压力,4这个版本内置了很多默认配置。如上,实现了对vue,jsx, js, 和资源文件对处理和转译如上,配置了开发环境的配置,注意webpack4多了一个mode,mode有三个选项可以选择:development, production, 和none,

webpack 4 出来也已经一年了,公司的老项目用的还是webpack3,也是时候该升级一波了。说实话webpack4还是有几点挺吸引我的,估计也是感受到了parcel的压力,4这个版本内置了很多默认配置。

迁移的坑

  1. CommonsChunkPlugin 废除, webpack 4内置了optimization.splitChunks 和 runtimeChunk 进行代码拆分
  2. ExtractTextPlugin 不支持webpack4,官方推荐了一个MiniCssExtractPlugin来拆分chunk中的css代码
  3. vue-loader 的升级,vue-loader 版本由14 升级到了15, 之前的配置也改变了具体参考 从 v14 迁移

基础配置

const package = require('../package.json');
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const utils = require('./utils');

function resolve (dir) {
    return path.join(__dirname, dir);
}

module.exports = {
    entry: {
        main: '@/main',
        'vender-exten': '@/vendors/vendors.exten.js'
    },
    output: {
        path: path.resolve(__dirname, '../dist/' + package.version) // 输出文件的绝对路径
    },
    module: {
        rules: [
            {
                test: /\.(js|vue)$/,
                loader: 'eslint-loader',
                enforce: 'pre',
                exclude: /node_modules/,
                options: {
                    emitError: true,
                    emitWarning: false,
                    failOnError: true
                }
            },
            {
                test: /\.vue$/,
                exclude: /node_modules/,
                loader: 'vue-loader'
            },
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            },
            {
                test: /\.js[x]?$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader'
                }
            },
            {
                test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 10000,
                        name: utils.assetsPath('img/[name].[hash:7].[ext]')
                    }
                }
            },
            {
                test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 10000,
                        name: utils.assetsPath('media/[name].[hash:7].[ext]')
                    }
                }
            },
            {
                test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
                use: {
                    loader: 'url-loader',
                    options: {
                        limit: 10000,
                        name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
                    }
                }
            }
        ]
    },
    plugins: [
        new VueLoaderPlugin(),
    ],
    resolve: {
        extensions: ['.js', '.vue'],
        alias: {
            '@': resolve('../src')
        }
    },
    externals: {
        AMap: 'AMap',
        vue: 'Vue',
        iview: 'iview',
        'vue-router': 'VueRouter',
        vuex: 'Vuex'
    }
};

如上,实现了对vue,jsx, js, 和资源文件对处理和转译

开发环境配置

const HtmlWebpackPlugin = require("html-webpack-plugin");
const merge = require("webpack-merge");
const webpackBaseConfig = require("./webpack.base.config.js");
const config = require("./config");
const webpack = require("webpack");


module.exports = merge(webpackBaseConfig, {
    mode: 'development',
    devtool: '#source-map',
    output: {
        publicPath: '/dist/',
        filename: '[name].js',
        chunkFilename: '[name].chunk.js'
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: 'admin management',
            filename: '../index.html',
            inject: false
        }),
    ],

    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['vue-style-loader', 'css-loader', 'postcss-loader']
            },
            {
                test: /\.less$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    'postcss-loader',
                    'less-loader'
                ]
            }
        ]
    },

    //设置跨域代理
    devServer: {
        public: 'local.xxxx.net:9000',
        port: 9000,
        proxy: {
            '/login': {
                target: config.devApi.passport, 
                pathRewrite: { '^/login': '/login' },
                changeOrigin: true
            },
            '/v3': {
                target: config.devApi.sass,
                pathRewrite: { '^/v3': '/v3' },
                changeOrigin: true
            }
        }
    }
});

如上,配置了开发环境的配置,注意webpack4多了一个mode,mode有三个选项可以选择:development, production, 和none,

webpack 4迁移指南

可以看官方的这个图,webpack会根据mode自动开启内置插件

生产环境配置

const HtmlWebpackPlugin = require('html-webpack-plugin')
const TerserJSPlugin = require('terser-webpack-plugin');
const webpack = require('webpack')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const cleanWebpackPlugin = require('clean-webpack-plugin')
const merge = require('webpack-merge')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const webpackBaseConfig = require('./webpack.base.config.js')
const path = require('path')
const package = require('../package.json')

module.exports = merge(webpackBaseConfig, {
    mode: 'production', 
    output: {
        publicPath: '/' + package.version + '/', // 所有引入的文件资源都加上publicPath路径
        filename: '[name].[contenthash].js', // 输出 bundle 的名称, 入口(non-entry)
        chunkFilename: '[name].[contenthash].chunk.js' // 非入口(non-entry) chunk 文件的名称
    },
    optimization: {
        splitChunks: {
            cacheGroups: {
                // 缓存组
                commons: {
                    test: /[\\/]node_modules[\\/]/, // 只抽取引入的node_modules文件
                    name: 'vender-exten', // 要缓存的 分隔出来的 chunk 名称
                    chunks: 'all' // 对所有的chunk都进行缓存
                }
            }
        },
        runtimeChunk: {
            name: 'runtime'
        }, 
        minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})]
    },
    module: {
        rules: [
            {
                test: /\.css?$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader',
                    'less-loader'
                ]
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: '[name].[contenthash].css',
            chunkFilename: '[name].[contenthash].css'
        }),
        new cleanWebpackPlugin(['dist/*'], {
            root: path.resolve(__dirname, '../')
        }),
        new CopyWebpackPlugin([
            {
                from: path.resolve(__dirname, '../static'),
                to: '../static',
                ignore: ['.*']
            }
        ]),
        new HtmlWebpackPlugin({
            title: 'admin',
            favicon: './static/favicon.ico',
            filename: '../index.html',
            template: '!!ejs-loader!./src/template/index.ejs',
            inject: false
        })
    ]
});

生产环境

1.使用MiniCssExtractPlugin,来拆分css,我可以可以options里面有两个值filename和chunkFilename, filename指的是entry中key生成的css名称, chunkFilename是webpack中每个chunk拆分生成css的名称。

2.使用OptimizeCSSAssetsPlugin 对打包之后的css文件进行压缩,

3.使用splitChunks对公共代码进行抽取缓存,我们先来看一下这个插件的默认配置

module.exports = {
    optimization: {
        splitChunks: {
            chunks: 'async',  "initial" | "all"(推荐) | "async" (默认就是async)
            minSize: 30000, 最小尺寸,30000
            maxSize: 0, 最小尺寸
            minChunks: 1, 最小 chunk ,默认1
            maxAsyncRequests: 5, // 最大异步请求数, 默认5
            maxInitialRequests: 3, // 最大初始化请求书,默认3
            automaticNameDelimiter: '~', // 打包分隔符
            name: true,
            cacheGroups: { // 重点,缓存配置
                vendors: {
                    test: /[\\/]node_modules[\\/]/, // 只缓存node_modules里面的模块
                    priority: -10 // // 缓存组优先级,可能有多个
                },
            }
        }
    }
};

看下我的配置

splitChunks: {
    cacheGroups: {
        // 缓存组
        commons: {
            test: /[\\/]node_modules[\\/]/, // 只抽取引入的node_modules文件
            name: 'vender-exten', // 要缓存的 分隔出来的 chunk 名称
            chunks: 'all' // 对所有的chunk都进行缓存
        }
    }
}

通过webpack-bundle-analyzer生成的可视化图标分析查看项目中的多个chunk共同引入的lib包

webpack 4迁移指南

抽离5个依赖的lib包,进行缓存<br/><br/>

4.使用optimization.runtimeChunk,去缓存生成chunk过程中生成的webpack公用代码<br/><br/>

5.使用TerserJSPlugin对js进行压缩


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Orange'S:一个操作系统的实现

Orange'S:一个操作系统的实现

于渊 / 电子工业出版社 / 2009-6 / 69.00元

《Orange S:一个操作系统的实现》从只有二十行的引导扇区代码出发,一步一步地向读者呈现一个操作系统框架的完成过程。书中不仅关注代码本身,同时关注完成这些代码的思路和过程。本书不同于其他的理论型书籍,而是提供给读者一个动手实践的路线图。读者可以根据路线图逐步完成各部分的功能,从而避免了一开始就面对整个操作系统数万行代码时的迷茫和挫败感。书中讲解了大量在开发操作系统中需注意的细节问题,这些细节不......一起来看看 《Orange'S:一个操作系统的实现》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试