webpack打包

172 阅读3分钟

详情请点击

基本配置

entry、output、loader、plugins配置

chunk输出与引用路径总结

chunk【entry js,非entry js、css】输出路径:output.path+chunkName

chunk引用路径:output.publicPath【默认情况】+chunkName或者module.rule.options.publicPath【优先级高于前者】——publicPath最好不用相对路径

 - entry js chunkName:output.filename
 - not entry js chunkName:output.chunkFilename,其中output.chunkFilename:"[name]",[name]=require.ensure()第三个参数
 - css文件chunkName:miniCsExtractPlugin.filename
 - html文件chunkName:htmlWebpackPlugin.filename
 - image chunkName:module.rule.options.outputPath+module.rule.options.name

性能优化

webpack打包优化——webpack构建速度

- DllPlugin减少基础模块编译次数:
    原理:1、添加webpack_dll.config.js,打包第三方抽离出来的单独包,在webpack_dll.config.js中使用new DllPlugin()生成模块对应关系manifest.json文件。2、在主webpack打包文件中,使用new DllReferencePlugin()添加DllPlugin生成manifest.json文件,DllReferencePlugin去 manifest.json 文件读取 name 字段的值,把值的内容作为在从全局变量中获取动态链接库中内容时的全局变量名,因此:在 webpack_dll.config.js 文件中,DllPlugin 中的 name 参数必须和 output.library 中保持一致。3、由于主webpack打包文件不会打包第三方抽离出来的代码,所以使用add-asset-html-webpack-plugin插件,将webpack_dll.config.js中生成的js插入在html中。
    
    > 注意:使用DllPlugin,不能指定resolve.modules、resolve.mainFields等寻找node_modules中文件路径,这样会使webpack_dll.config.js生成的[name].mainfest.json文件node_modules文件的对应关系失效。
    
    // webpack_dll.config.js文件
        const path = require('path');
        const DllPlugin = require('webpack/lib/DllPlugin');
        module.exports = {
            context:__dirname,
            entry: {
                vue: ['vue/dist/vue.esm.js', 'vue', 'vue-router']
            },
            output: {
                filename: '[name].dll.js',
                path: path.resolve(__dirname, 'dll'),
                library: '_dll_[name]',  //dll的全局变量名
            },
            plugins: [
                new DllPlugin({
                    context:__dirname,
                    name: '_dll_[name]',  //[name].manifest.json的name值,与library名字一致
                    path: path.join(__dirname, 'dll', '[name].manifest.json')//描述生成的manifest文件
                })
            ]
        };
    // 主webpack文件
        const DllReferencePlugin = require('webpack/lib/DllReferencePlugin');
        const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
        const manifest = require("./dll/vue.manifest.json"); // 加载webpack_dll.config.js生成的[name].mainfest.json文件
        plugins:[
                new HtmlWebpackPlugin(),
                new DllReferencePlugin({
                    context: __dirname,
                    manifest
                }),
                new AddAssetHtmlPlugin({
                    filepath: path.resolve(__dirname, './dll/*.dll.js'),
                    outputPath: "static/commonJs",// 引用.dll.js文件输出地址
                    publicPath: "/static/commonJs",// 访问.dll.js文件的基础路径
                    includeSourcemap: false
                }),
        ]
    
     - 依赖模块路径解析优化:
        resolve:resolve.extensions、resolve.alias、resolve.modules、resolve.mainField
        modulemodule.noParse、module.rule.include、module.rule.exclude
    
     - 多进程转换:happypack
        const HappyPack = require('happypack'); //开启多进程Loader转换
        const happythreadPool=HappyPack.ThreadPool({size:5}); // 公用进程池
        module:{
            rules: [{
                    test: /\.es6?$/,
                    use: 'happypack/loader?id=babelES6'
                }
            ]
        }
        plugins:[
            new HappyPack({
                id:"babelES6",
                loaders:["babel-loader"],
                threadPool:happythreadPool
            })
        ]
    
 - 多进程压缩js代码:webpack-parallel-uglify-plugin
    plugins:[
        new ParallelUglifyPlugin({
            uglifyJS: {
                warnings: false, // 在UglifyJs删除没有用到的代码时不输出警告
                output: {
                    beautify: false, //不需要格式化
                    comments: true //不保留注释
                },
                compress: {
                    drop_console: true, // 删除所有的 `console` 语句,可以兼容ie浏览器
                    collapse_vars: true, // 内嵌定义了但是只用到一次的变量
                    reduce_vars: true // 提取出出现多次但是没有定义成变量去引用的静态值
                }
            }
        })
    ]
    

压缩输出文件

css文件:optimize-css-assets-webpack-plugin、purifycss-webpack(删除没有用的css代码)。
js文件:使用uglify-webpack-plugin或webpack-parallel-uglify-plugin(开启多进程使用Uglify压缩js代码)压缩js文件。

使用webpack-parallel-uglify-plugin:
new ParallelUglifyPlugin({
    uglifyJS: {
        warnings: false, // 在UglifyJs删除没有用到的代码时不输出警告
        output: {
            beautify: false, //不需要格式化
            comments: true //不保留注释
        },
        compress: {
            drop_console: true, // 删除所有的 `console` 语句,可以兼容ie浏览器
            collapse_vars: true, // 内嵌定义了但是只用到一次的变量
            reduce_vars: true // 提取出出现多次但是没有定义成变量去引用的静态值
        }
    }})

拆分公共模块

(首屏加载所需的node_modules为一个chunk,子页面单独用的node_modules为一个chunk)

不同类型静态资源配置不同CDN

module.rule.options.publicPath设置不同类型静态文件引用路径

webpack-dev-server读写文件原理

将文件写入内存,写入内存中文件为Buffer格式。。读取通过memory-fs暴露方法读取文件。读取内存文件和往内存中写入文件都在webpack-dev-middleware插件中暴露出方法,一般读取文件、写入文件方法在context.fs对象中,context对象操作内存文件方法,由另一个文件中setFs扩充。