1、对图片进行压缩和优化
image-webpack-loader可以帮助我们对图片进行压缩和优化
cnpm install image-webpack- --save-dev复制代码
{ test: /\.(png|svg|jpg|gif|jpeg|ico)$/, use: [ 'file-loader', { loader: 'image-webpack-loader', options: { mozjpeg: { progressive: true, quality: 65 }, optipng: { enabled: false, }, pngquant: { quality: '65-90', speed: 4 }, gifsicle: { interlaced: false, }, webp: { quality: 75 } } }, ] }复制代码
2、区分环境变量
- 日常的前端开发工作中,一般都会有两套构建环境
- 一套开发时使用,构建结果用于本地开发调试,不进行代码压缩,打印 debug 信息,包含 sourcemap 文件
- 一套构建后的结果是直接应用于线上的,即代码都是压缩后,运行时不打印 debug 信息,静态文件不包括 sourcemap
- webpack 4.x 版本引入了 mode 的概念
- 指定使用 production mode 时,默认会启用各种性能优化的功能,包括构建结果优化以及 webpack 运行性能优化
- 指定使用 development mode 的话,则会开启 debug 工具,运行时打印详细的错误信息,以及更加快速的增量编译构建
2.2、获取mode参数
optimize-css-assets-webpack-plugin 用于优化或者压缩CSS资源
cnpm install image-webpack- --save-dev复制代码
const UglifyJSPlugin = require('webpack/lib/optimize/UglifyJsPlugin');const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');module.exports=(env,argv) => ({ optimization: { minimizer: argv.mode == 'production'?[ new UglifyJSplugin({ cache: true,//启用缓存 parallel: true,// 使用多进程运行改进编译速度 sourceMap:true//生成sourceMap映射文件 }), new OptimizeCssAssetsWebpackPlugin({}) ]:[] }})复制代码
3、拆分webpack配置
可以把 webpack 的配置按照不同的环境拆分成多个文件,运行时直接根据环境变量加载对应的配置即可
- webpack.base.js:基础部分,即多个文件中共享的配置
- webpack.development.js:开发环境使用的配置
- webpack.production.js:生产环境使用的配置
- webpack.test.js:测试环境使用的配置
- 使用webpack-merge 合并环境配置
const { smart } = require('webpack-merge')const webpack = require('webpack')const base = require('./webpack.base.js')module.exports = smart(base, { module: { rules: [], }})复制代码
4、设置忽略打包模块
IgnorePlugin用于忽略某些特定的模块,让 webpack 不把这些指定的模块打包进去
import 'vue-scroll from 'vue-scroll';new webpack.IgnorePlugin(/^\.\/locale/,/vue-scroll/)复制代码
5、设置无需解析文件
noParse 字段,可以用于配置哪些模块文件的内容不需要进行解析, 不需要解析依赖(即无依赖) 的第三方大型类库等,可以通过这个字段来配置,以提高整体的构建速度
module.exports = {// ...module: { noParse: /jquery|lodash/, // 正则表达式 // 或者使用函数 noParse(content) { return /jquery|lodash/.test(content) },}}...复制代码
6、resolve解析
6.1extensions
指定extension之后可以不用在require或是import的时候加文件扩展名,会依次尝试添加扩展名进行匹配
resolve: { extensions: [".js",".vue",".json",".css"]},复制代码
6.2 alias
配置别名可以加快webpack查找模块的速度
每当引入lodash 模块的时候,它会直接引入lodash,而不需要从node_modules文件夹中按模块的查找规则查找
resolve: { alias:{ "lodash":path.resolve(__dirname,'node_modules/lodash'); }},复制代码
6.2 modules
- 对于直接声明依赖名的模块(如 vue ),webpack 会类似 Node.js 一样进行路径搜索,搜索node_modules目录
- 这个目录就是使用resolve.modules字段进行配置的 默认配置
resolve: { modules: ['node_modules'],}复制代码
6.2 mainFiles
当目录下没有 package.json 文件时,我们说会默认使用目录下的 index.js 这个文件,其实这个也是可以配置的
resolve: { mainFiles: ['index'], // 你可以添加其他默认使用的文件名}复制代码
7、打包第三方类库
平时使用工具函数时,会直接引用过来例如:
import _ from 'lodash';console.log(_.join([1, 2, 3],','));复制代码
利用webpack.ProvidePlugin lodash 函数会自动添加到当前模块的上下文,无需显示声明
new webpack.ProvidePlugin({ _:'lodash' })复制代码
8、DLL
dll为后缀的文件称为动态链接库,在一个动态链接库中可以包含给其他模块调用的函数和数据
- 把基础模块独立出来打包到单独的动态连接库里
- 当需要导入的模块在动态连接库里的时候,模块不能再次被打包,而是去动态连接库里获取
- DllPlugin插件: 用于打包出一个个动态连接库
- DllReferencePlugin: 在配置文件中引入DllPlugin插件打包好的动态连接库
const path=require('path');const DllPlugin=require('webpack/lib/DllPlugin');module.exports={ entry: { vue:['vue','vue-router'] },// 把 vue, vue-router 相关模块的放到一个单独的动态链接库 output: { path: path.resolve(__dirname,'dist/dll'),// 输出的文件都放到 dist/dll 目录下 filename: '[name].dll.js',//输出的动态链接库的文件名称,[name] 代表当前动态链接库的名称 library: '_dll_[name]',//存放动态链接库的全局变量名称,例如对应 vue 来说就是 _dll_vue }, plugins: [ new DllPlugin({ context: __dirname, // 动态链接库的全局变量名称,需要和 output.library 中保持一致 // 该字段的值也就是输出的 manifest.json 文件 中 name 字段的值 // 例如 vue.manifest.json 中就有 "name": "_dll_vue" name: '_dll_[name]', // 描述动态链接库的 manifest.json 文件输出时的文件名称 path: path.join(__dirname, 'dist/dll', '[name].manifest.json') }) ]}复制代码
9、HappyPack
- Node.js 之上的 Webpack 是单线程模型
- 构建需要解析和处理文件,文件读写和计算密集型的操作太多后速度会很慢
- happypack 就能让Webpack把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。
npm i happypack --save-dev复制代码
const HappyPack = require('happypack'); rules: [ { test: /\.js$/, // 把对 .js 文件的处理转交给 id 为 babel 的 HappyPack 实例 use: ['happypack/loader?id=babel'], exclude: path.resolve(__dirname, 'node_modules'), }, { test: /\.css$/, // 把对 .css 文件的处理转交给 id 为 css 的 HappyPack 实例 use: ['happypack/loader?id=css'] }]new Happypack({ //ID是标识符的意思,ID用来代理当前的happypack是用来处理一类特定的文件的 id: 'js', use: [{ loader: 'babel-loader', //options=query都是向插件传递参数的 options: { presets: [["@babel/preset-env", { modules: false }], "@babel/preset-react"], plugins: [ ["@babel/plugin-proposal-decorators", { "legacy": true }], ["@babel/plugin-proposal-class-properties", { "loose": true }], ] } }] }), new Happypack({ //ID是标识符的意思,ID用来代理当前的happypack是用来处理一类特定的文件的 id: 'css', use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'], threads: 4,//你要开启多少个子进程去处理这一类型的文件 verbose: true//是否要输出详细的日志 verbose })复制代码
10、打包模块输出分析
通过使用webpack-bundle-analyzer可以看到项目各模块的大小,可以按需优化
安装
cnpm i webpack-bundle-analyzer --save-dev复制代码
配置webpack
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;plugins: [ new BundleAnalyzerPlugin( { analyzerMode: 'server', analyzerHost: '127.0.0.1', analyzerPort: 8889, reportFilename: 'report.html', defaultSizes: 'parsed', openAnalyzer: true, generateStatsFile: false, statsFilename: 'stats.json', statsOptions: null, logLevel: 'info' } ),]复制代码
配置package.json
"analyz": "NODE_ENV=production npm_config_report=true npm run build"复制代码
分析结果
webpack --profile --json > stats.json复制代码