原有的vue-cli,create-react-app在項目較大時編譯時間過長,擴展性很差。重寫了一套,優化了構建速度和體積。主要從如下優化了webpackcss
開啓多線程壓縮有多種方式,happy-pack/thread-loader/parallel-webpack
等,happy-pack
在webpack3
時很受歡迎,主要是在webpack
compile
後經過happy-pack
建立的線程池分模塊構建,處理後從新傳到主線程,目前官方已經再也不維護,推薦使用的webpack4
的thread-loader
。在webpack
解析一個模塊時, thread-loader
會將它及它的依賴分配到 worker 線程中,添加thread-loader
以下:html
//1. 安裝依賴
npm install --save-dev thread-loader (以後方法省略該步驟)
//2. module中引入
module: {
rules: [
{
test: /\.js$/,
include: path.resolve(__dirname, '../src'),
//多線程編譯 項目不大不建議使用
use: [{
loader: 'thread-loader',
options: {
workers: 3
}
},
'babel-loader?cacheDirectory=true']
}
]
}
複製代碼
一樣多種方式: parallel-uglify-plugin/ugilfyjs-wepack-plugin/terser-webpack-plugin ,而terser-webpack-plugin
支持壓縮ES6語法。使用一樣簡單:vue
//安裝後添加到optimization中
optimization: {
minimizer: [
new TerserPlugin({
//開啓並行壓縮,true爲默認值,可設數值, 一樣項目小不建議使用,可能反而延長時間
parallel: true,
//開啓壓縮緩存
cache: true
})
],
},
複製代碼
使用html-webpack-externals-plugin指定引入包CDNnode
new HtmlWebpackExternalsPlugin({
externals: [
{
module: 'jquery',
entry: '//unpkg.com/jquery@3.2.1/dist/jquery.min.js',
global: 'jQuery',
},
{
module: 'react',
entry: '//unpkg.com/react@16/umd/react.production.min.js',
global: 'React',
},
],
})
複製代碼
此方法需手動引入,同時會致使頁面打入多個<script>
標籤進行引用,對於SplitChunk仍是會對基礎包進行分析。項目不大可使用。推薦使用DLLreact
這是webpack自帶的神器,此插件專門用於單獨的webpack配置中,以建立dll的捆綁包。它建立一個manifest.json文件,DllReferencePlugin使用它來映射依賴項。webpack詳情jquery
能夠先建立webpack.dll.js
文件,將公共包提出來(如下文件都存在config文件夾,__dirname目錄可能補同)webpack
const path = require('path')
const webpack = require('webpack')
module.exports = {
entry: {
//將一下包打成library文件
library:[
'react',
'react-dom',
'redux',
'react-redux',
'axios'
],
},
output:{
filename:'[name]_[hash].js',
//路徑不要存在dist中,不然會被cleanwebpackplugin清理
path: path.join(__dirname,'../build/library'),
library:'[name]'
},
plugins:[
//使用dll
new webpack.DllPlugin({
name:'[name]_[hash]',
path: path.join(__dirname,'../build/library/[name].json'),
})
]
}
複製代碼
在pack.json
中新加一條命令運行:ios
"dll": "webpack --config ./config/webpack.dll.js",
複製代碼
run後會產生build文件夾web
在原webpack production
模式下添加vue-cli
plugins:[
new webpack.DllReferencePlugin({
manifest:require(path.resolve(__dirname,'../build/library/library.json')),
})
]
複製代碼
會發現速度提高,同時打包體積變小。此時需在編譯後的html文件中手動添加library文件夾。可以使用copy-webpack-plugin
和 html-webpack-tags-plugin
實現自動添加:
plugins:[
new HtmlWebpackPlugin(),
new HtmlWebpackTagsPlugin({
//須要引入的文件
tags: [`${require('../build/library/library.json').name}.js`],
//加載末尾
append: false
}),
]
複製代碼
注:html-webpack-tags-plugin
必須配合html-webpack-plugin
,而且在此以後引入。同時,該插件彷佛和speed-measure-webpack-plugin
衝突,如果引用了speed-measure-webpack-plugin
建議在構建時暫時關閉。
在production
配置中添加:
plugins:[
new CopyWebpackPlugin([
//目錄從項目根文件開始,從複製build/lirary文件到當前,須要更多配置可查詢官方
{ from: 'build/library', to: '' },
]),
]
複製代碼
此時運行能夠自動添加文件。
緩存對於二次編譯具備很大的提升。一般有幾種方法:
開啓babel-loaer
緩存(直接在babel-loader
後添加?cacheDirectory=true
方法1中)
開啓terser-webpack-plugin
緩存(方法二中)
使用hard-source-webpack-plugin
提高模塊轉換階段緩存
plugins:[
// ...
new HardSourceWebpackPlugin(),
]
複製代碼
縮小構建目標,減小每次構建文件查找範圍也能提升速度,有如下狀況:
// 1. 排除或縮小目錄
module: {
rules: [
{
test: /\.js$/,
//只在解析src下文件
include: path.resolve(__dirname, '../src'),
//排除 node_module文件夾,一般不須要同時使用。
exclude: 'node_module',
use: [{
loader: 'thread-loader',
options: {
workers: 3
}
},
'babel-loader?cacheDirectory=true']
}
]
}
//2.resolve模塊使用
resolve: {
//合理使用別名,減小搜索層級
alias: {
//import react能夠直接找到
"react": path.resolve(__dirname, "../node_module/react/dist/react.min.js"),
},
modules:[path.resolve(__dirname,"../node_module")]
//後綴名,如import 'index'時會自動按extensions順序查找,可選多個,但查找速度慢,指定爲一下數組中類型時,其餘類必須寫明後綴,不然沒法找到
extensions:[.js],
//packjson指定的入口文件
mainFeilds:['main']
}
複製代碼
基於Node庫的Imagemin
(定製選項,能夠引入第三方優化插件,能夠處理多種圖片格式)
使用:配置image-webpack-loader
快速入口
module:{
rules:[
{
test: /\.(gif|png|jpe?g|svg|blob)$/,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
quality: 65
},
// optipng.enabled: false will disable optipng
optipng: {
enabled: false,
},
pngquant: {
quality: '65-90',
speed: 4
},
gifsicle: {
interlaced: false,
},
// the webp option will enable WEBP
webp: {
quality: 75
}
}
},
],
},
]
}
複製代碼
Mac OS 可能因爲libpng錯誤,官方建議安裝或更新libpng
brew install libpng
複製代碼
若還有錯誤,可能因爲node引發
node rebuild
複製代碼
從新編譯可能時間長
webpack3
中使用purifyCSS
,已經中止維護,4中可以使用purgecss-webpack-plugin
進行treeshaking
,刪除未使用的css;
const PATHS = {
src: path.join(__dirname, '../src')
}
plugins:[
new MiniCssExtractPlugin(),
//必須和mini-css-extract-plugin配合使用
new PurgecssPlugin({
paths: glob.sync(`${PATHS.src}/**/*`, { nodir: true }),
}),
]
複製代碼
Polyfill通常佔用很大,不少時候不是必須的。通常經常使用的方法是使用babel-polyfill
,體積會很大。可使用polyfill-service
按需加載。polyfill-service
主要經過UA來判斷該引用哪些polyfill。因此缺點也明顯,各大瀏覽器會僞造UA來搶佔,這會形成 service判斷困難。
CDN:
除了對項目和速度進行優化,也能夠對webpack
展現優化,提升友好性。
plugins:[
// 提示框
new WebpackBuildNotifyerPlugin({
//提示項目名
title: 'project',
suppressSuccess: true
}),
//進度條
new ProgressBarPlugin(),
//儀表盤,看須要
//new DashboardPlugin(),
//錯誤提示,須要同stats使用
new FriendlyErrorsWebpackPlugin(),
// 體積分析,須要的時候加上,有多種分析插件
// new BundleAnalyzerPlugin(),
]
複製代碼