webpack打包极限优化

    技术2022-07-11  104

    一、基础介绍

    1.为什么我们需要构建工具 (a) 转换ES6语法 (b) 转换JSX © CSS前缀补全/预处理器 (d) 压缩混淆 (e) 图片压缩

    2.初级分析-使用Webpack内置的stats (a) stats:构建的统计信息 (b) package.json中使用status

    "scripts": { "build:stats": "webpack ---env production --json > stats.json" ... }

    © Node API中使用

    const webpack = require('webpack'); const config = require('./webpack.config.js')("production"); webpack(config, (err, stats) => { if (err) { return console.error(err); } if (stats.hasErrors()) { return console.error(stats.toString("errors-only")) } console.log(stats); })

    3.速度分析-使用speed-measure-webpack-plugin

    const speedMeasurePlugin = require("speed-measure-webpack-plugin"); const smp = new SpeedMeasurePlugin(); const webpackConfig = smp.wrap({ plugins: { new MyPlugin(), new MyOtherPlugin() } }) // 可以看到每个loader和插件执行耗时

    4.体积分析-使用webpack-bundle-analyzer

    const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = { plugins: { new BundleAnalyzerPlugin() } } // 构建完成后会在8888端口展示各个打包后文件的大小

    二、构建速度优化

    1.速度优化策略 (a) 使用webpack4 (b) 多进程/多实例构建 © 分包 (d) 缓存 (e) 缩小构建目标

    2.使用webpack4-优化原因 (a) V8带来的优化(for of替代forEach、Map和Set替代Object、includes替代indexOf) (b) 默认使用更快的md4 hash算法 © webpacks AST可以直接从loader传递给AST,减少解析时间 (d) 使用字符串方法替代正则表达式

    3.多进程/多实例-使用HappyPack解析资源 原理:每次webpack解析一个模块,HappyPack会将它及它的依赖分配给worker线程中

    exports.plugins = { new HappyPack({ id: 'jsx', threads: 4, // 固定线程数,但是不建议 loaders: ['babel-loader'] }), new HappyPack({ id: 'styles', threads: 2, // 固定线程数,但是不建议 loaders: ['style-loader', 'css-loader', 'less-loader'] }) }

    4.多进程/多实例-并行压缩 方法一:使用parallel-uglify-plugin插件(webpack3使用)

    const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin'); module.exports = { plugins: [ new ParallelUglifyPlugin({ uglifyJS: { output:{ beautity: false, comments: false, }, compress: { warnings: false, drop_console: true, collapse_vars: true, reduce_vars: true } } }) ] }

    方法二:使用uglifyjs-webpack-plugin开启parallel参数(webpack4使用)

    const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); module.exports = { plugins: [ new UglifyJsPlugin({ uglifyOptions: { warnings: false, parse: {}, compress: {}, mangle: true, output: null, toplevel: false, nameCache: null, ie8: false, keep_fnames: false }, parallel: true }) ] }

    注意:uglifyjs-webpack-plugin现已废弃,用terser-webpack-plugin代替,支持ES6:

    const TerserWebpackPlugin = require('terser-webpack-plugin') new TerserWebpackPlugin({ cache: true, parallel: true, sourceMap: build.productionSourceMap, terserOptions: { warnings: false } })

    5.分包-设置Externals 思路:将react、react-dom基础包通过cdn引入,不打入bundle中 方法:使用html-webpack-externals-plugin

    const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin'); plugins: [ new HtmlWebpackExternalsPlugin({ external: [ { module: 'react', entry: '........./react-with-addons.min.js?_bid=313', global: 'React' }, { module: 'react-dom', entry: '........./react-dom.min.js?_bid=313', global: 'ReactDOM' } ] }) ]

    6.进一步分包-预编译资源模块 思路:将react、react-dom、redux、react-redux基础包和业务基础包打包成一个文件。 方法:使用DLLPlugin进行分包,DllReferencePlugin对manifest.json引用

    module.exports = { plugins: [ new webpack.DllPlugin({ name: '[name]', path: './build/library/[name].json' }) ] }

    7.缓存 目的:提升二次构建速度 方法:使用HardSourceWebpackPlugin或者cache-loader 比较推荐使用HardSourceWebpackPlugin,速度更快

    8.缩小构建目标 目的:尽可能的少构建模块 比如babel-loader不解析node_modules

    module.exports = { rules: { test: /\.js$/, loader: 'happypack/loader', exclude: 'node_modules' } }

    三、构建体积优化

    1.体积优化策略 (a) Scope Hoisting (b) Tree-shaking © 公共资源分离 (d) 图片压缩 (e) 动态Polyfill

    2.Scope Hoisting 原理:将所有模块的代码按照引用顺序放在一个函数作用域里,然后适当的重命名一些变量以防止变量名冲突 对比:通过scope hoisting可以减少函数声明代码

    // 代码示例: module.exports = { plugins: [ new webpack.opimize.ModuleConcatenationPlugin() ] } // 要求:必须是ES6的语法,CJS的方式不支持

    3.Tree-shaking 概念:1个模块可能有多个方法,只要其中的某个方法使用到了,则整个文件都会被打到bundle里面去,Tree-shaking 就是只把用到的方法打入bundle,没用到的方法会在uglify阶段被删掉 使用:webpack默认支持,在.babelrc里设置modules:false即可 要求:必须是ES6的语法,CJS的方式不支持

    4.公共资源分离 目的:提取多页面公共JS chunk代码 使用:webpack3使用CommonsChunkPlugin webpack4使用SplitChunksPlugin

    5.图片压缩 要求:基于Node库的imagemin或者tinypng API 使用:配置image-webpack-loader

    Processed: 0.032, SQL: 9