- 提升热更新速度:
- 提升热更新速度,上百页 2000ms内搞定,10几页面区别不大
//在.env.development环境变量配置
VUE_CLI_BABEL_TRANSPILE_MODULES:true
- 原理:利用插件,在开发环境中将异步组件变为同步引入,也就是import()转化为require())
- 通常页面到达几十上百,热更新慢的状况下须要用到。
- webpack5 即将发布,大幅提升了打包和编译速度
- 分析打包时长:
- webpack-bundle-analyzer 分析打包后的模块文件大小
npm run build -- --report
npm install --save-dev speed-measure-webpack-plugin
//vue.config.js
//导入速度分析插件
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
//实例化插件
const smp = new SpeedMeasurePlugin();
module.exports = {
configureWebpack: smp.wrap({
plugins: [
// 这里是本身项目里须要使用到的其余插件
new yourOtherPlugin()
]
})
}
- 较耗时:代码的编译或压缩(转化 AST树 -> 遍历AST树 -> 转回JS代码)
- 编译 JS、CSS 的 Loader
- 压缩 JS、CSS 的 Plugin
- 缓存:让二次构建时,不须要再去作重复的工做[没有变化的直接使用缓存,速度更快]
- 开启Loader、压缩插件的cache配置【如babel-loader的cacheDirectory:true】,uglifyjs-webpack-plugin【如cache: true】,构建完将缓存存放在node_modules/.cache/..。
- cache-loader:将 loader 的编译结果写入硬盘缓存,再次构建若是文件没有发生变化则会直接拉取缓存,添加在时间长的 loader 的最前面。
module: {
rules: [
{
test: /\.ext$/,
use: ['cache-loader', ...loaders],
include: path.resolve('src'),
},
],
},
- 多核:充分利用了硬件自己的优点
- happypack:开启系统CPU最大线程,经过插件将loader包装,暴露id,直接module.rules引用该id。
//安装:npm install happypack -D
//引入:const Happypack = require('happypack');
exports.plugins = [
new Happypack({
id: 'jsx',
threads: 4,
loaders: [ 'babel-loader' ]
}),
new Happypack({
id: 'styles',
threads: 2,
loaders: [ 'style-loader', 'css-loader', 'less-loader' ]
})
];
exports.module.rules = [
{
test: /\.js$/,
use: 'Happypack/loader?id=jsx'
},
{
test: /\.less$/,
use: 'Happypack/loader?id=styles'
},
]
- thread-loader:添加在此loader后面的放入单独的 worker 池里运行,配置简单
//安装:npm install thread-loader -D
module.exports = {
module: {
//个人项目中,babel-loader耗时比较长,因此我给它配置 thread-loader
rules: [
{
test: /\.jsx?$/,
use: ['thread-loader', 'cache-loader', 'babel-loader']
}
]
}
}
- 默认的TerserWebpackPlugin:开启了多进程和缓存,缓存文件 node_modules/.cache/terser-webpack-plugin
- 其余并行压缩插件:
- webpack-parallel-uglify-plugin:子进程并发执行把结果送回主进程,多核并行压缩来提高压缩速度
- uglifyjs-webpack-plugin自带的parallel:【如parallel: true】配置项开启多核编译
- 抽离:Vue全家桶、echarts、element-ui、工具库lodash不常变动的依赖 【几十秒】
- 内置webpack的 DllPlugin 和 DllReferencePlugin 引入dll, 经过DllPlugin来对那些咱们引用可是绝对不会修改的npm包来进行预编译,再经过DllReferencePlugin将预编译的模块加载进来,避免反复编译浪费时间。新建一个webpack.dll.config.js 的配置文件,通常不变化,若是变了,新的dll文件名便会加上新的hash
// webpack.config.dll.js
const webpack = require('webpack');
const path = require('path');
module.exports = {
entry: {
react: ['react', 'react-dom']
},
mode: 'production',
output: {
filename: '[name].dll.[hash:6].js',
path: path.resolve(__dirname, 'dist', 'dll'),
library: '[name]_dll' //暴露给外部使用
//libraryTarget 指定如何暴露内容,缺省时就是 var
},
plugins: [
new webpack.DllPlugin({
//name和library一致
name: '[name]_dll',
path: path.resolve(__dirname, 'dist', 'dll', 'manifest.json') //manifest.json的生成路径
})
]
}
// package.json 中新增 dll 命令
{
"scripts": {
"build:dll": "webpack --config webpack.config.dll.js"
},
}
// npm run build:dll 后,会生成
dist
└── dll
├── manifest.json
└── react.dll.9dcd9d.js
// manifest.json 用于让 DLLReferencePlugin 映射到相关依赖上。至此 dll 准备工做完成,接下来在 webpack 中引用便可。
// webpack.config.js
const webpack = require('webpack');
const path = require('path');
module.exports = {
//...
devServer: {
contentBase: path.resolve(__dirname, 'dist')
},
plugins: [
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, 'dist', 'dll', 'manifest.json')
}),
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: ['**/*', '!dll', '!dll/**'] //不删除dll目录
}),
//...
]
}
// 使用 npm run build 构建,能够看到 bundle.js 的体积大大减小。
// 修改 public/index.html 文件,在其中引入 react.dll.js
<script src="/dll/react.dll.9dcd9d.js"></script>
- 配置Externals(推荐):外部引入,将不须要打包的静态资源从构建逻辑中剔除,使用 CDN 的方式去引用。
- 步骤:在externals中配置key[包名]+value[CDN全局变量名],而后在HTML中引入CDN的script 标签。就能实现import引入了。
//webpack.config.js
module.exports = {
//...
externals: {
//jquery经过script引入以后,全局中即有了 jQuery 变量
'jquery': 'jQuery'
}
}
<script src="https://cdn.bootcss.com/react/16.9.0/umd/react.production.min.js"></script>
- 有些 CDN 服务不稳定,尽可能选择成熟的CDN服务。