项目打包构建优化
优化项目: vue3-elm-master
方法
- 查找并诊断性能瓶颈
- 构建速度分析: 影响构建性能和开发效率. speed-measure-webpack-plugin
- 构建体积分析: 影响页面访问性能 webpack-bundle-analyzer
- 构建性能优化常用方法:
- 通过多进程加快构建速度
thread-loader
- 通过分包减小构建目标容量(某些文件太大,就分成多个目标)
DllPlugin
- 减少构建目标加快构建速度(文件太小,数量有多的, 合并文件)
- 通过多进程加快构建速度
1. speed-measure-webpack-plugin 分析项目构建速度
用来分析各个loader, plugin花费的时间.
// vue-cli的情况
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin({
disable: process.env.MEASURE !== "true", // 是否使用 速度测试
outputFormat: "humanVerbose", // 输出内容格式
});
module.exports = {
// smp.wrap(webpackConfig), 在vue.config.js里包裹configureWebpack, 直接使用webpack的话, 就是包裹webpackConfig.
configureWebpack: smp.wrap({
devtool: "eval-source-map",
})
}
// 直接使用webpack的情况
const webpackConfig = smp.wrap(webpackConfig);
var compiler = webpack(webpackConfig)
2. webpack-bundle-analyzer 检测打包后的文件的体积的插件
配置项 analyzerMode:
1. "serve" 启动后通过服务器开启浏览器页面
2. "static" 将检测结果生成一个html文件, 默认为 dist/report.html
3. "json" 将检测结果生成一个json文件
4. "disabled" 不启动检测.
// 检测构建文件体积的插件
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
// webpack的配置
{
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: process.env.MEASURE === "true" ? "server" : "disabled",
}),
]
}
3. 用thread-loader,启动多进程构建.
thread-loader, 放到所有loader的前面, 可以开启多进程构建.
- 由于启动进程也需要时间, 所以如果构建本身就够快的情况下, 多进程反而会更耗费时间. 需要本身就很耗费时间的情况下, 多进程才有意义.
- worker属性: 进程数量.
- 以当前项目为例, 未开多进程,构建项目5359ms, 开了5个进程, 5037ms(有用但不多).
- vue-cli的parallel配置项, 是否开多进程编译, 尽在生产模式
production
生效.
parallel: true
, build时间: 8553ms,
parallel: false
build时间: 8671ms
{
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: "thread-loader",
options: {
// 进程数量
worker: 5,
}
}
],
}
]
},
}
4. DllPlugin 分包
对于变化几率很小的一些第三方包(比如vue, vux, vue-router), 没必要每次build都打包一次. 可以把这些单独
抽出来打包好(一般不超过300kb).
webpack本身是要体现出模块之间的依赖关系, 当我们将一些包抽离出来后, 维护之前的依赖关系就需要manifest.json
这个文件,将vue, vue-router, vuex等基础包打包成一个文件,也就是使用DllPlugin进行分包,
DllReferencePlugin对manifest.json引用. manifest.json是对分离出来的包的描述
具体步骤
- 分包: 定义webpack.dll.config.js 使用DllPlugin配置分包, 定义script命令,完成分包
- 排除分包: 在vue.config.js中, 使用DllReferencePlugin引用manifest文件排除分包
- 引用dll: 使用add-asset-html-webpack-plugin 引用分包文件
5. 分包
分包原因:
包太大.导致请求缓慢.
分包方案:
对于变化几率很小的一些第三方包(比如vue, vux, vue-router), 没必要每次build都打包一次. 可以把这些单独
抽出来打包成一个文件,作为静态文件(一般不超过300kb).
分包好处:
- 这样不用每次打包的时候重复打包,减少打包时间
- 减少index.js的文件大小.分出300kb, 降低页面的请求时间.
6. 分包方案
- DllPlugin分包
用DllPlugin, 把vue,vuex, vue-router打包成一个js文件包vue.dll.js
. 作为一个静态文件存放到项目中
执行webpack --config build/webpack.dll.config.js
,会生成
dll文件夹
- vue.dll.js 打包好的vue,vuex,vue-router总和的文件.对外输出
vue_xxxxxxx
作为入口. - vue-manifest.json 记录
vue.dll.js
信息的文件, 给webpack用, webpack打包时要知道哪些文件dll打包了,打包的文件怎么引用. - vue.dll.js.LICENSE.txt 分享权限声明文件, 无实际作用.
// webpack.dll.config.js
const path = require("path");
const webpack = require("webpack");
const dllPath = "../dll";
module.exports = {
mode: "production",
entry: {
// 入口文件, vue, vue-router, vuex, 命名为一个vue
vue: ['vue', 'vue-router', 'vuex'],
// 将 better-scroll, 命名为scroll
// scroll: ["better-scroll"],
},
output: {
// 输出文件路径
path: path.join(__dirname, dllPath),
// 输出的文件名, name就是entry里的"vue", "scroll", 最后生成 vue.dll.js, scroll.dll.js
filename: '[name].dll.js',
// library是在全局声明一个变量. 变量的内容就是entry里的内容.
// 具体在这个案例就是声明一个 `vue_xxxxxxxx`的变量.里面有{vue: xxx, vuex: xxx, vue-router: xxxx}
// 通过这种方式来获取entry里的内容.
library: `[name]_[hash]`,
},
plugins: [
new webpack.DllPlugin({
//生成vue-manifest.json文件,记录vue.dll.js里都打包了哪些文件
// 给webpack build打包用, 用来排除vue,vuex,vue-router
path: path.join(__dirname, dllPath, '[name]-manifest.json'),
// 用来记录 相关对象的导出方式(比如获取vue对象方式: vue_xxxxxxxx.vue ) , 和 output.library想同.
name: '[name]_[hash]',
context: process.cwd(),
})
]
}
- 由于vue,vuex, vue-router打成一个包了, 那么webpack build的时候, 就要把vue,vuex, vue-router去掉.
const path = require("path");
const webpack = require("webpack");
{
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
// 获取dll打包的信息文件, 后续webpack打包时就不会打包manifest.json里记录的文件了.
manifest: path.resolve(__dirname, "./dll/vue-manifest.json"),
})
]
}
- 默认生成的index.html是不会引入
vue.dll.js
的, 需要用add-asset-html-webpack-plugin
插件创建一个script标签把vue.dll.js
导入到index.html里
按理说如下所示使用即可, 但是实际操作中,未生效. 网上提示需要 Html-Webpack-Plugin@3.2.0
, 我未使用此种方案
const AddAssetHtmlWebpackPlugin = require("add-asset-html-webpack-plugin");
{
plugins: [
new AddAssetHtmlWebpackPlugin({
filepath: path.resolve(__dirname, './dll/vue.dll.js'),
})
]
}
我的方案:
- htmlWebpackPlugin指定了一个index.html模板, 在index.html模板中直接用script引入
vue.dll.js
文件 - 用
copy-webpack-plugin
把dll/vue.dll.js
直接复制到dist/js/vue.dll.js
.
// index.html直接加入这一行
<script src="js/vue.dll.js"></script>
// vue.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
export default {
configureWebpack: {
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './public/index.html')
}),
new CopyWebpackPlugin({
patterns: [{
from: path.resolve(__dirname, "./dll/vue.dll.js"),
to: path.resolve(__dirname, "./dist/js/vue.dll.js"),
}]
}),
]
}
}
7. cache缓存
webpack的cache缓存属性. 开发环境默认 true, 生产环境禁用.
一般是测试环境build代码时使用. 用jenkins在线打包时, 第一次慢,第二次快用的就是cache.
生成的缓存文件
- 0.pack : 应该是 node_modules里的总和文件
- index.pack : 应该是业务的总和文件.
build时间:
- 不适用缓存 17838ms
- 使用缓存 1548ms
export default {
configureWebpack: {
// 使用缓存, 开发环境默认 true, 生产环境禁用.
cache: {
type: 'filesystem',
cacheDirectory: path.resolve(__dirname, "node_modules/.cache_temp"),
},
}
}
8. image-webpack-loader 图片压缩
插件下载: cnpm i -D image-webpack-plugin
, 用npm下载会报错
9. purgecss-webpack-plugin css 去掉未使用的css
该插件会把css文件里有的, 但是在html中未使用的css类去掉.达到压缩css文件的目的.
未压缩前app.css: 131kb
. 压缩后 6kb
;
插件下载: cnpm i -D purgecss-webpack-plugin
, 用npm下载会报错
const glob = require("glob");
// 去掉未使用的css的插件
const { PurgeCSSPlugin } = require("purgecss-webpack-plugin");
const PATHS = {
src: path.join(__dirname, "src"),
}
export default {
plugins: [
new PurgeCSSPlugin({
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
})
]
}
标签:文件,vue,dll,webpack,构建,js,优化,打包
From: https://www.cnblogs.com/bridge7839/p/18573002