hello~親愛的看官老爺們你們好~ 最近一直在學習 webpack
的相關知識。曾幾什麼時候我總以爲 webpack
的體系龐大而難以掌握,一直迴避不肯去學。然而偉人魯迅曾說過: 世上太多事會因沒法掌握而使你狂躁不安,最好的解決方法就是硬着頭皮開始作! 於是就從比較簡單的 CommonsChunkPlugin
開始學起吧~ css
雖然本文比較簡單,但仍是須要一點 webpack
知識的,如若徹底沒接觸過 webpack
,建議先移步 官方文檔 與 Webpack 3,從入門到放棄 瞭解一下 webpack
基礎爲佳~html
CommonsChunkPlugin
插件,是一個可選的用於創建一個獨立文件(又稱做 chunk)的功能,這個文件包括多個入口 chunk 的公共模塊。經過將公共模塊拆出來,最終合成的文件可以在最開始的時候加載一次,便存起來到緩存中供後續使用。這個帶來速度上的提高,由於瀏覽器會迅速將公共的代碼從緩存中取出來,而不是每次訪問一個新頁面時,再去加載一個更大的文件。vue
簡單來講,這有點像封裝函數。把不變的與變化的分開,使得不變的能夠高效複用,變化的靈活配置。接下來會根據這個原則優化咱們的項目,如今先看看虛擬的項目長成什麼樣吧~node
新建一個 index.html
模板與入口 index.js
文件,簡單配置以下:jquery
index.html
: webpack
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<p>{{ vue_test }}</p>
</div>
<div class="jq_test"></div>
</body>
</html>複製代碼
index.js
:git
import Vue from 'vue';
import $ from 'jquery';
new Vue({
el: '#app',
data: {
vue_test: 'vue is loaded!'
}
})
$(function() {
$('.jq_test').html('jquery is loaded!')
})複製代碼
爲演示起見,代碼十分簡單,相信不用多加解釋。接下來先簡單配置一下 webpack.config.js
,代碼以下:github
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
entry: {
index: path.join(__dirname, 'index.js')
},
output: {
path: path.join(__dirname, '/dist'),
filename: 'js/[name].[chunkhash].js'
},
resolve: { alias: { 'vue': 'vue/dist/vue.js' } },
plugins: [
new CleanWebpackPlugin(['./dist']),
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
new BundleAnalyzerPlugin(),
]
};複製代碼
CleanWebpackPlugin
主要用於清除 dist
目錄下的文件,這樣每次打包就沒必要手動清除了。HtmlWebpackPlugin
則是爲了在 dist
目錄下新建 html
模板並自動插入依賴的 js
。 BundleAnalyzerPlugin
主要是爲了生成打包後的 js
文件包含的依賴,如此時進行打包,則生成:web
能夠看到生成的 index.js
文件包含了 vue
與 jquery
。vuex
通常而言,咱們項目中的類庫變化較少,業務代碼卻是多變的。須要想辦法把類庫抽離出來,把業務代碼單獨打包。這樣加傷 hash
後瀏覽器就能緩存類庫的 js
文件,優化用戶體驗。此時咱們的主角 CommonsChunkPlugin
就正式登場了。咱們在 webpack.config.js
文件的 plugins
中添加 CommonsChunkPlugin
,配置以下:
plugins: [
//...此前的代碼
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function(module) {
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, './node_modules')
) === 0
)
}
}),
]複製代碼
上述配置,是經過 CommonsChunkPlugin
生成一個名爲 vendor
的 js
文件,它抽取入口文件也就是 index.js
中來源於 node_modules
的依賴組成。此例中就是 vue
與 jquery
。打包出來畫風是這樣的:
此時看上去解決了咱們的問題,將依賴的類庫抽取抽來獨立打包,加上緩存就能被瀏覽器緩存了。然而事情沒那麼簡單,不行你隨意改一下入口的 index.js
代碼,再次打包:
絕望地發現 vendor.js
文件的 hash
改變了。簡單說,這是由於模塊標識產生了變化所致使的,更具體的緣由能夠查看相關的中文文檔~修正的方法其實也挺簡單,就是再使用 CommonsChunkPlugin
抽取一次模塊,將不變的類庫沉澱下來,將變化的抽離出去。於是添以下代碼:
plugins: [
//...此前的代碼
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function(module) {
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, './node_modules')
) === 0
)
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor', 'index']
})
]複製代碼
打包後, dist/js
目錄下多出一個名爲 manifest
的 js
文件,此時你不管如何改變 index.js
的代碼,打包後的 vendor.js
的 hash
都再也不會改變了。
然而稍等,當你想拍拍手收工的時候,思考一下這樣的場景:隨着項目不斷迭代,vendor
中的依賴不斷被添加與刪除,使得它的 hash
會不斷變化,這顯然不符合咱們的利益,這到底如何解決呢?
既然 CommonsChunkPlugin
是能夠按照咱們的需求抽取模塊,而依賴的外部模塊多是不斷變化的,那麼爲什麼不將基礎的依賴模塊抽取出來做爲一個文件,其餘的依賴如插件等做爲另外一個文件呢?
簡單說,如咱們的項目中 vue
是基本的依賴,必須用到它,而 jquery
等則是後加的類庫,以後可能變動。那麼將 vue
獨立打包一個文件,有利於瀏覽器緩存,由於不管此後添加更多的類庫或刪去 jquery
時, vue
文件的緩存依然是生效的。於是咱們能夠這麼作,首先新建一個入口:
entry: {
index: path.join(__dirname, 'index.js'),
vendor: ['vue'],
},複製代碼
此處主要是用於指明須要獨立打包的依賴有哪些。以後在 plugins
中作以下修改:
plugins: [
//...此前的代碼
new webpack.HashedModuleIdsPlugin(),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: Infinity,
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
minChunks: function(module) {
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, './node_modules')
) === 0
)
},
chunks: ['index'],
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor', 'common', 'index']
})
]複製代碼
插件 HashedModuleIdsPlugin
,是用於保持模塊引用的 module id
不變。而 CommonsChunkPlugin
則提取入口指定的依賴獨立打包,minChunks: Infinity,
的用意是讓插件別管其餘,就按照設置的數組提取文件就好。以後修改一下原來的 vendor
,重命名爲 common
,指定它從入口 index.js
中抽取來自 node_modules
的依賴。最後就是抽取 webpack
運行時的函數及其模塊標識組成 manifest
。運行一下 webpack
,構建出來如圖:
能夠看到 vue
與 jquery
被分開打包成了兩個文件,咱們嘗試添加一下新的依賴 vuex
,打包後結果以下:
如此一來,咱們的優化目的就達到了,不變的都提取出來,變化的能夠動態配置~
webpack
插件 CommonsChunkPlugin
就介紹到這裏了,然而優化仍是有不少的,好比開啓壓縮,去除註釋等。而當項目體積逐漸增大時,CommonsChunkPlugin
就不必定是提取代碼的最優解了。在打包速度與控制構建的精細程度來講,結合 DLLPlugin
會有更好的表現。根據不一樣的場景組合不一樣的插件以達到咱們的目的,原本就是 webpack
的魅力之一。
感謝各位看官大人看到這裏,知易行難,但願本文對你有所幫助,全部的代碼均會被上傳到 github 上,滾求 star
~謝謝!