module: {
rules: [{
test: /\.js$/,
use: {
loader: 'babel-loader',
},
// 規避了對龐大的 node_modules 文件夾或者 bower_components 文件夾的處理
exclude: /(node_modules|bower_components)/,
include: resolve('source')
}]
}
複製代碼
module: {
rules: [{
test: /\.js$/,
use: {
// 開啓緩存
loader: 'babel-loader?cacheDirectory=true'
},
exclude: /(node_modules|bower_components)/,
include: resolve('source')
}]
}
複製代碼
處理第三方庫有多種方式,externals、CommonsChunkPlugin、splitChunks、DllPlugin/DLLReferencePlugin 。咱們先說說各類的優劣勢html
防止將某些 import 的包(package)打包到 bundle 中,而是在運行時(runtime)再去從外部獲取這些擴展依賴(external dependencies)。vue
<script src="https://unpkg.com/element-ui@2.0.8/lib/index.js"></script>
module.exports= {
externals: {
ElementUi: 'ELEMENT' // 主要element-ui保留出來的全局變量是ELEMENT
}
}
import ElementUi from 'ElementUi';
複製代碼
經過將公共模塊拆出來,最終合成的文件可以在最開始的時候加載一次,便存到緩存中供後續使用。這個帶來速度上的提高,由於瀏覽器會迅速將公共的代碼從緩存中取出來, 而不是每次訪問一個新頁面時,再去加載一個更大的文件。(可是新的webpack中已經被移除,使用的是SplitChunksPlugin)node
new webpack.optimize.CommonsChunlPlugin({
name: string, // or
names: string[],
// 這是 common chunk 的名稱。已經存在的 chunk 能夠經過傳入一個已存在的 chunk 名稱而被選擇。
// 若是一個字符串數組被傳入,這至關於插件針對每一個 chunk 名被屢次調用
// 若是該選項被忽略,同時 `options.async` 或者 `options.children` 被設置,全部的 chunk 都會被使用,
// 不然 `options.filename` 會用於做爲 chunk 名。
// When using `options.async` to create common chunks from other async chunks you must specify an entry-point
// chunk name here instead of omitting the `option.name`.
filename: string,
// common chunk 的文件名模板。能夠包含與 `output.filename` 相同的佔位符。
// 若是被忽略,本來的文件名不會被修改(一般是 `output.filename` 或者 `output.chunkFilename`)。
// This option is not permitted if you're using `options.async` as well, see below for more details. minChunks: number|Infinity|function(module, count) -> boolean, // 在傳入 公共chunk(commons chunk) 以前所須要包含的最少數量的 chunks 。 // 數量必須大於等於2,或者少於等於 chunks的數量 // 傳入 `Infinity` 會立刻生成 公共chunk,但裏面沒有模塊。 // 你能夠傳入一個 `function` ,以添加定製的邏輯(默認是 chunk 的數量) chunks: string[], // 經過 chunk name 去選擇 chunks 的來源。chunk 必須是 公共chunk 的子模塊。 // 若是被忽略,全部的,全部的 入口chunk (entry chunk) 都會被選擇。 children: boolean, // 若是設置爲 `true`,全部公共 chunk 的子模塊都會被選擇 deepChildren: boolean, // 若是設置爲 `true`,全部公共 chunk 的後代模塊都會被選擇 async: boolean|string, // 若是設置爲 `true`,一個異步的 公共chunk 會做爲 `options.name` 的子模塊,和 `options.chunks` 的兄弟模塊被建立。 // 它會與 `options.chunks` 並行被加載。 // Instead of using `option.filename`, it is possible to change the name of the output file by providing // the desired string here instead of `true`. minSize: number, // 在 公共chunk 被建立立以前,全部 公共模塊 (common module) 的最少大小。 }); 複製代碼
webpack4中支持了零配置的特性,同時對塊打包也作了優化,CommonsChunkPlugin已經被移除了,如今是使用optimization.splitChunks代替。webpack
// webpack.config.js
splitChunks: {
chunks: "async",
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
複製代碼
DllPlugin:是基於 Windows 動態連接庫(dll)的思想被創做出來的。這個插件會把第三方庫單獨打包到一個文件中,這個文件就是一個單純的依賴庫。這個依賴庫不會跟着你的業務代碼一塊兒被 從新打包,只有當依賴自身發生版本變化時纔會從新打包。ios
DLLReferencePlugin:是基於 Windows 動態連接庫(dll)的思想被創做出來的。這個插件會把第三方庫單獨打包到一個文件中,這個文件就是一個單純的依賴庫。這個依賴庫不會跟着你的業務代碼。web
一塊兒被從新打包,只有當依賴自身發生版本變化時纔會從新打包。配置步驟以下:vue-router
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: {
// 依賴的庫數組
vendor: [
'vue/dist/vue.esm.js',
'axios',
// 'element-ui',
'vue-router',
'vuex',
'v-viewer',
'vue-photo-preview',
'mockjs'
]
},
output: {
path: path.join(__dirname, 'htdocs/dist'),
filename: '[name].js',
library: '[name]_[hash]',
},
plugins: [
new CleanWebpackPlugin(['htdocs/dist/vendor-manifest.json', 'htdocs/dist/vendor.js']),
new webpack.DllPlugin({
// DllPlugin的name屬性須要和libary保持一致
name: '[name]_[hash]',
path: path.join(__dirname, 'htdocs/dist', '[name]-manifest.json'),
// context須要和webpack.config.js保持一致
context: __dirname,
}),
],
}
複製代碼
/ package.json
"scripts": {
"dll": "webpack -p --progress --config ./webpack.dll.config.js"
},
複製代碼
module.exports = {
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
// manifest就是咱們第一步中打包出來的json文件
manifest: require('./htdocs/dist/vendor-manifest.json'),
})
]
}
複製代碼
第一種:直接在index.html。,這種方式簡單粗暴,針對沒有vendor.js沒有hash值的,徹底ok,可是若是你打包的vendor.js有hash,每次從新 npm run dll以後若是生成了新的hash,就要手動改這個路徑了。vuex
第二種:add-asset-html-webpack-plugin,該插件會將給定的JS或CSS文件添加到Webpack知道的文件中,並將其放入html-webpack-plugin注入到生成的html 的資產列表中。將插件添加 到您的配置中。(可是須要注意的是此插件須要html-webpack-plugin@^2.10.0。在webpack 4+以後,須要先註冊AddAssetHtmlPlugin後才 使用內部使用的鉤子,而先前版本的webpack對此 並不關心。HtmlWebpackPluginhtml-webpack-plugin-before-html-generation。)npm
可是我在操做的時候遇到一個很奇葩的坑,element-ui被dllPlugins以後,el-table不生效,是的不生效,頁面也麼有報錯,樣式都還存在,可是就是頁面展現不出來table。編程
我看到element-ui的issues上也有人遇到這樣的狀況,可是如今尚未一個解決方案,很難受。
若是不能dll elemenet-ui,打包出來的index文件,仍是很大的,怎麼辦。 因此我想到了一個辦法就是,利用externals來處理element-ui(操做步驟如上),index有80%的大小是element-ui打包以後佔據的。可是externals來處理卻發現了另一個問題。index.js打包的文件是小了不少 可是,有一個相應的js文件的大小反而變的很大,這樣操做得不償失。網上有不少解決辦法,可是都沒有根治我這個問題,最後的解決方案是,單獨的使用table,項目重寫table。這樣的方法也有一個弊端,就是當前只是發現了table不能正常使用,可是若是還有其餘 組件不行,也須要重寫,這樣的成本就很好了。因此,最後項目選擇是不打包element-ui(無奈之舉)。期待這個問題被解決。
webpack 是單線程的,就算此刻存在多個任務,你也只能排隊一個接一個地等待處理。這是 webpack 的缺點,好在咱們的 CPU 是多核的,Happypack 會充分釋放 CPU 在多核併發方面的優點, 幫咱們把任務分解給多個子進程去併發執行,大大提高打包效率。
HappyPack 的使用方法也很是簡單,只須要咱們把對 loader 的配置轉移到 HappyPack 中去就好,咱們能夠手動告訴 HappyPack 咱們須要多少個併發的進程:
const HappyPack = require("happypack");
// 手動建立進程池
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
module.exports = {
plugins: [
new HappyPack({
// 這個HappyPack的「名字」就叫作happyBabel,和樓上的查詢參數遙相呼應
id: 'happyBabel',
// 指定進程池
threadPool: happyThreadPool,
// 輸出日誌
verbose: true,
loaders: ['babel-loader?cacheDirectory']
}),
]
};
複製代碼
這個插件能夠幫助具備許多入口點的項目加速構建。隨Webpack提供的uglifyjs插件在每一個輸出文件上按順序運行。這個插件與每一個可用CPU的一個線程並行運行uglify。這可能會致使顯著減小構 建時間,由於最小化是CPU密集型的。簡單點來講就是順序運行改成並行,因此大大提高了構建速度。
// const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
module.exports = {
plugins: [
new ParallelUglifyPlugin({
cacheDir: 'cache_dir',//用做緩存的可選絕對路徑。若是未提供,則不使用緩存。
sourceMap: config.build.productionSourceMap, //可選布爾值。是否爲壓縮後的代碼生成對應的Source Map(瀏覽器能夠在調試代碼時定位到源碼位置了),這會減慢編譯速度。默認爲false
uglifyJS: {
output: {
comments: false,//是否保留代碼中的註釋,默認爲保留
},
warnings: true,//是否在UglifyJS刪除沒有用到的代碼時輸出警告信息,默認爲false
compress: {
drop_console: true,//是否刪除代碼中全部的console語句,默認爲false
collapse_vars: true,//是否內嵌雖然已經定義了,可是隻用到一次的變量, 默認值false
reduce_vars: true,//是否提取出現了屢次可是沒有定義成變量去引用的靜態值,默認爲false
}
},
})
]
};
複製代碼
做者優化這個項目以前,開發人員也是分組打包,可是是一個路由打包一個js文件,致使最後的結果就是,生產了60+的js文件,在進行批量發佈時,哪速度叫一個感人,做者進行了一個簡單的操做優化, 就是根據名稱分組打包,最後打包下來只有10+的js,而且我發現,60+文件打包的大小比10+文件的整體大小要大一些。哈哈哈,無心間發現的。
這個優化其實就是一個平常須要注意的問題,可是能間接的提高webpack的打包效率、打包大小的優化。
因此咱們在平常的操做中多使用函數式編程,來提高webpack的打包效率和打包大小。
element-ui被dllPlugins以後,el-table不生效。求大神解決。項目依賴版本以下: