webpack的最後就是爲了獲得打包結果。css
那這是一個怎麼樣的過程,不一樣的配置,會有什麼樣的結果呢?html
本文的原文在個人博客中:github.com/RachelRen/b…,歡迎star。node
首先從最簡單的配置開始output
。告訴webpack在哪裏打包應用程序。webpack
output: {
path: path.resolve(__dirname, 'build'),
filename: 'js/[name].js',
publicPath: '/',
chunkFilename:'js/[name].chunk.js',
//chunkFilename:'js/[name].[chunkhash:8].chunk.js',
},
複製代碼
在這裏能夠看到不少類似,可是有不一樣含義的名次,如filename
和chunkFilename
,hash
和chunkhash
,那他們有什麼區別呢?git
而這裏的chunk又是什麼意思呢?github
webpack 將多個模塊打包以後的代碼集合稱爲 chunk。 這兩個的區別:chunkFilename 是無入口的chunk在輸出時的文件名稱。chunkFilename只用於在指定在運行過程當中生成的chunk在輸出時的文件名稱。web
但在webpack4以上的時候,發如今entry中配置的入口文件,打包的結果是index.chunckfile.js
,屬於chunkFilename,由於設置了promise
optimization: {
splitChunks: {
chunks: 'all',
name: 'common',
},
runtimeChunk: {
name: 'runtime',
}
},
複製代碼
當去掉runtimeChunk
這個配置時,那麼入口文件,又會變成filename。主要緣由是bash
經過設置 optimization.splitChunks.chunks: "all" 來啓動默認的代碼分割配置項。經過知足下面的條件,webpack會自動打包chunkside
optimization.runtimeChunk
經過設置 optimization.runtimeChunk: true 來爲每個入口默認添加一個只包含 runtime 的 chunk(webpack會添加一個只包含運行時(runtime)額外代碼塊到每個入口)。
output: {
filename: 'js/[name].[chunkhash:8].js',
path: path.join(__dirname, './build'),
publicPath: '/',
chunkFilename:'js/[name].[chunkhash:8].chunk.js',
},
複製代碼
在webpack 4這樣打包的話,會報錯。
ERROR in chunk runtime [entry]
js/[name].[chunkhash:8].js
Cannot use [chunkhash] or [contenthash] for chunk in 'js/[name].[chunkhash:8].js' (use [hash] instead)
複製代碼
因此就想搞明白這兩個的區別究竟是什麼。
[chunkhash] is replaced by the hash of the chunk.
chunkhash
表明的是chunk的hash值。chunk在webpack中的就是模塊的意思,那麼chunkhash就是根據模塊內容計算得出的hash值。
[hash] is replaced by the hash of the compilation.
hash 是compilation的hash值。
compilation對象表明某個版本的資源對應的編譯進程。在使用webpack的development中間件時,每次檢測到項目文件有變更時會建立一個compilation,因此可以針對改動生成全新的編譯文件。compilation對象包含當前模塊資源,編譯文件,有改動的文件盒監聽依賴的全部信息。
compiler和compilation的區別是。 compiler是配置完備的webpack環境。compiler只在webpack啓動時構建一次,由webpack組合全部的配置構建生成。compiler是不變的webpack環境,是針對webpack的。而compilation是針對隨時可變的項目文件,只要有文件改動,compilation就會被從新建立。
compilation在項目中任何一個文件改動後就會被從新建立,而後webpack計算新的compilation的hash值,這個hash值即是hash。
hash是compilation對象(所用compilation對象?)計算所得,而不是具體的項目文件計算所得。因此以上配置的編譯輸出文件,全部的文件名都會使用相同的hash指紋。
chunkhash是根據具體模塊文件的內容計算所得的hash值,因此某個文件的改動只會影響它自己的hash指紋,不會影響其餘文件
接上文所述,webpack的hash字段是根據每次編譯compilation的內容計算所得,也能夠理解爲項目整體文件的hash值,而不是針對每一個具體文件的。
因此若是用optimization.splitChunks.runtimeChunk
生成的文件,就是以hash做爲文件後綴的runtime.[hash].js
,並且每次文件修改,都會生成一個新的文件。
hash是跟整個項目的構建相關,只要項目裏有文件更改,整個項目構建的hash值都會更改,而且所有文件都共用相同的hash值
總之一句話: hash是總體的文件計算所得,chunkhash是具體模塊文件所得。
如今不少系統都是SPA,當發展愈來愈龐大的時候,js的拆分就愈來愈重要的。那麼怎麼拆分js就很重要了。
分離主要有三種方式:
這種方式是最簡單,最直觀的方式。可是有一些他的缺點:
SplitChunksPlugin
插件能夠將公共的依賴模塊提取到已有的 entry chunk 中,或者提取到一個新生成的 chunk。在webpack 4.0 以前是用CommonsChunkPlugin
來作代碼分離的
plugins: [
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest']
})
]
複製代碼
在webpack 4.0以後,就經過optimization.splitChunks
來分離代碼了。
optimization: {
splitChunks: {
chunks: 'all'
}
}
複製代碼
若是系統很龐大,將代碼一次性載入,就顯得太過於強大,最好能作到根據咱們的需求來選擇性地加載咱們須要的代碼。
webpack 提供了2種方式來拆分代碼。
在配置過程當中,也會遇到這兩個概念。
publicPath
: 用來爲項目中的全部資源指定一個基礎路徑。使用的是相對路徑。
filename:'[name]_[chunkhash:8].js'
publicPath: 'https://cdn.example.com/assets/'
複製代碼
那麼發佈上線的時候,路徑就是:
<script src='https://cdn.example.com/assets/a_12345678.js'></script>
複製代碼
靜態資源最終訪問路徑 = output.publicPath + 資源loader或插件等配置路徑
path
: 配置輸出文件存放在本地的目錄,必須是 string 類型的絕對路徑,一般經過 Node.js 的 path 模塊去獲取絕對路徑:
path: path.resolve(__dirname, 'dist_[hash]')
複製代碼