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
复制代码