為提高前端工程webpack打包速度,對工程進行改造
第一部分:vue-cli2工程
可以采用js分包+壓縮混淆升級+CDN加速+gzip壓縮等手段進行加速
(1)分包,在webpack的配置中添加
module.exports = { externals: { vue: 'Vue', moment: 'moment', rxjs: 'Rx', ramda: 'R', 'vue-router': 'VueRouter', jquery: 'jQuery', 'element-ui': 'ELEMENT', axios: 'axios', qs: 'Qs', vuex: 'Vuex', 'echarts': 'echarts', lodash: { //如果我們的庫運行在Node.js環境中,import _ from 'lodash'等價於const _ = require('lodash') commonjs: "lodash", commonjs2: "lodash", //同上 amd: "lodash", //如果我們的庫使用require.js等加載,等價於 define(["lodash"], factory); root: "_", //如果我們的庫在瀏覽器中使用,需要提供一個全局的變量‘_’,等價於 var _ = (window._) or (_); } }, }
(2)分包后,這些被排除的包將不會被打包進入vendor中去,那么我們就必須使用CDN來提供這些包的功能
在入口文件index.html中添加對應的js文件
使用CDN的優點:
1.可以充分利用客戶端緩存,大大減少每次webpack打包的vendor的體積,提高打包速度
2.每次工程迭代時,這些包將不需要更新,也不需要客戶端重新加載3
3.用戶在第一次加載之后,后面的版本迭代大部分文件將直接讀緩存,不需要再次加載外部依賴文件
缺點:工程部署必須能夠連接外網,內網部署的工程將不能夠使用CDN,可以通過在內網維護一個自己的簡單的CDN庫來解決
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <link crossorigin="anonymous" href="https://lib.baomitu.com/element-ui/2.3.9/theme-chalk/index.css" rel="stylesheet"> </head> <body> <div id="app"></div> <!-- built files will be auto injected --> <script src="https://lib.baomitu.com/jquery/3.2.1/jquery.min.js"></script> <script src="https://lib.baomitu.com/vue/2.5.2/vue.js"></script> <script src="https://lib.baomitu.com/vue-router/2.7.0/vue-router.min.js"></script> <script src="https://lib.baomitu.com/moment.js/2.18.1/moment.min.js"></script> <script src="https://lib.baomitu.com/moment.js/2.18.1/locale/zh-cn.js"></script> <script src="https://lib.baomitu.com/rxjs/5.4.3/Rx.min.js"></script> <script src="https://lib.baomitu.com/ramda/0.24.1/ramda.min.js"></script> <script crossorigin="anonymous" src="https://lib.baomitu.com/lodash.js/4.17.0/lodash.min.js"></script> <script crossorigin="anonymous" src="https://lib.baomitu.com/element-ui/2.3.9/index.js"></script> <script crossorigin="anonymous" src="https://lib.baomitu.com/axios/0.16.2/axios.min.js"></script> <script crossorigin="anonymous" src="https://lib.baomitu.com/vuex/3.0.1/vuex.min.js"></script> <script crossorigin="anonymous" src="https://lib.baomitu.com/qs/6.5.1/qs.min.js"></script> <script crossorigin="anonymous" src="https://lib.baomitu.com/xlsx/0.14.2/xlsx.min.js"></script> </body> </html>
(3)使用uglifyjs-webpack-plugin,新版的uglifyjs-webpack-plugin能夠支持es6語法
在webpack.prod.config.js中添加
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
module.exports= {
// 其他配置...,
plugins:[
new UglifyJsPlugin({
cache: true,
uglifyOptions: {
compress: {
drop_debugger: true,
drop_console: true,
},
ecma: 6,
output: {
comments: false,
beautify: false,
},
warnings: false,
},
sourceMap: false,
parallel: true,
}),
]
}
(4)使用開發環境資源緩存,提高第二次及以后的啟動速度
在webpack.dev.conf.js中,添加配置
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
module.exports = {
// ...其他配置
plugins: [
// 緩存加速二次構建速度
new HardSourceWebpackPlugin({
// Either an absolute path or relative to webpack's options.context.
// 設置緩存在磁盤中存放的路徑
cacheDirectory: './../disk/.cache/hard-source/[confighash]',
// Either a string of object hash function given a webpack config.
recordsPath: './../disk/.cache/hard-source/[confighash]/records.json',
configHash: function (webpackConfig) {
// node-object-hash on npm can be used to build this.
return require('node-object-hash')({ sort: false }).hash(webpackConfig);
},
// An object.
info: {
// 'none' or 'test'.
mode: 'none',
// 'debug', 'log', 'info', 'warn', or 'error'.
level: 'debug',
},
// Clean up large, old caches automatically.
cachePrune: {
// Caches younger than `maxAge` are not considered for deletion. They must
// be at least this (default: 2 days) old in milliseconds.
maxAge: 2 * 24 * 60 * 60 * 1000,
// All caches together must be larger than `sizeThreshold` before any
// caches will be deleted. Together they must be at least this
// (default: 50 MB) big in bytes.
sizeThreshold: 100 * 1024 * 1024
},
}),
]
}
第二部分:vue/cli3+版本
vue/cli3+版本里面的webpack配置作者進行了內置
我們需要在vue.config.js中進行配置
(1)
const path = require('path')
const webpack = require('webpack')
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin')
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')
// 拼接路徑
function resolve (dir) {
return path.join(__dirname, dir)
}
const baseUrlObject = {
development: '',
beta: '//fezz.wormpex.com/ripei-fe-web',
prod: '//fezz.blibee.com/ripei-fe-web',
production: '//fezz.blibee.com/ripei-fe-web'
}
const env = process.env.NODE_ENV || 'production'
// 基礎路徑 注意發布到生產環境之前要先修改這里
const baseUrl = baseUrlObject[env] || process.env.VUE_APP_BASE_URL
const IS_DEV = process.env.VUE_APP_NODE_ENV === 'development'
console.log(process.env.NODE_ENV)
console.log(process.env.VUE_APP_BASE_URL)
console.log(baseUrl)
// 用於開發環境下,緩存第一次編譯的文件,提高二次構建速度
const devPlugins = [
// 緩存加速二次構建速度
new HardSourceWebpackPlugin({
// Either an absolute path or relative to webpack's options.context.
// 設置緩存在磁盤中存放的路徑
cacheDirectory: './../disk/.cache/hard-source/[confighash]',
// Either a string of object hash function given a webpack config.
recordsPath: './../disk/.cache/hard-source/[confighash]/records.json',
configHash: function (webpackConfig) {
// node-object-hash on npm can be used to build this.
return require('node-object-hash')({ sort: false }).hash(webpackConfig);
},
// An object.
info: {
// 'none' or 'test'.
mode: 'none',
// 'debug', 'log', 'info', 'warn', or 'error'.
level: 'debug',
},
// Clean up large, old caches automatically.
cachePrune: {
// Caches younger than `maxAge` are not considered for deletion. They must
// be at least this (default: 2 days) old in milliseconds.
maxAge: 4 * 24 * 60 * 60 * 1000,
// All caches together must be larger than `sizeThreshold` before any
// caches will be deleted. Together they must be at least this
// (default: 50 MB) big in bytes.
sizeThreshold: 100 * 1024 * 1024
},
}),
new HardSourceWebpackPlugin.ExcludeModulePlugin([
{
test: /mini-css-extract-plugin[\\/]dist[\\/]loader/
}
])
]
const configPlugins = [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'windows.jQuery': 'jquery'
}),
new webpack.DllReferencePlugin({
context: process.cwd(),
manifest: require('./public/vendor/vendor-manifest.json')
}),
// 將 dll 注入到 生成的 html 模板中
new AddAssetHtmlPlugin({
// dll文件位置
filepath: path.resolve(__dirname, './public/vendor/*.js'),
// dll 引用路徑
publicPath: `${baseUrl}/vendor`,
// dll最終輸出的目錄
outputPath: './vendor'
})
]
module.exports = {
publicPath: baseUrl, // 根據你的實際情況更改這里
lintOnSave: true,
configureWebpack: { // 引入jquery
// externals: { // 引入百度地圖
// 'BMap': 'BMap'
// },
plugins: IS_DEV ? configPlugins.concat(devPlugins) : configPlugins
},
devServer: {
https: false,
publicPath: baseUrl, // 和 baseUrl 保持一致
// 代理設置
proxy: {
}
},
// webpack 設置
chainWebpack: config => {
// 修復HMR
config.resolve.symlinks(true)
// svg
const svgRule = config.module.rule('svg')
svgRule.uses.clear()
svgRule
.include
.add(resolve('src/assets/svg-icons/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'd2-[name]'
})
.end()
// image exclude
const imagesRule = config.module.rule('images')
imagesRule
.test(/\.(png|jpe?g|gif|webp|svg)(\?.*)?$/)
.exclude
.add(resolve('src/assets/svg-icons/icons'))
.end()
// 重新設置 alias
config.resolve.alias
.set('@', resolve('src'))
// babel-polyfill 加入 entry
const entry = config.entry('app')
entry
.add('babel-polyfill')
.end()
}
}
(2)使用DllPlugin進行包的拆分
在根目錄下創建webpack.dll.conf.js
/** * 配置vue-cli4工程的DllPlugins,用以減少熱更新和打包時的文件數量,提高熱更新和打包的速度 * 參考文獻:https://blog.csdn.net/DongFuPanda/article/details/104866788 * 步驟 */ const path = require('path') const webpack = require('webpack') const { CleanWebpackPlugin } = require('clean-webpack-plugin') // dll文件存放的目錄 const dllPath = 'public/vendor' module.exports = { entry: { // 需要提取的庫文件 vendor: ['vue', 'vue-router', 'vuex', 'axios', 'jquery', 'moment', 'ramda', 'element-ui', 'core-js', 'lodash'] }, output: { path: path.join(__dirname, dllPath), filename: '[name].[hash].dll.js', // vendor.dll.js中暴露出的全局變量名 // 保持與 webpack.DllPlugin 中名稱一致 library: '[name]_[hash]' }, plugins: [ // 清除之前的dll文件 new CleanWebpackPlugin(), // 設置環境變量 new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify('production') } }), // manifest.json 描述動態鏈接庫包含了哪些內容 new webpack.DllPlugin({ path: path.join(__dirname, dllPath, '[name]-manifest.json'), // 保持與 output.library 中名稱一致 name: '[name]_[hash]', context: process.cwd() }) ] }
在package.json中添加
"scripts": { "start": "vue-cli-service serve --open --mode development", "serve": "vue-cli-service serve --open --mode development", "build": "vue-cli-service build", "beta": "vue-cli-service build --mode beta", "lint": "vue-cli-service lint", "dll": "webpack -p --progress --config ./webpack.dll.conf.js" },
使用webpack-bundle-analyzer 進行代碼打包體積分析
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
module.exports = {
// ...其他配置
plugins:[
// new BundleAnalyzerPlugin()
]
}
