今天想要來談談關於使用第三方程式碼的時候,該如何將它們抽離出來呢?其實在 <04 - 心法1 - 根源> Entry 已經有提到了一個方式,就是直接建立一個 ./app/vendors.js
檔,然後自行將要 import 的檔案直接寫進去,例外:
import _ from 'lodash';
那能不能透過 webpack 的設定檔直接幫我們做到這件事呢?這樣就不用再自己建立 ./app/vendors.js
檔了,有的,我們透過 webpack
內建的 CommonsChunkPlugin
來做到這件事情:來動手做吧!
先前我們已經安裝過 lodash
了,我們在另外裝一個 Moment.js 來當做範例
Moment.js
$ npm install --save moment
./app/index.js
在最上方新增以下兩行:(也就是表示在 ./app/index.js
會使用到 lodash 以及 moment。)
var _ = require('lodash');
var moment = require('moment');
…
webpack.config.js
將以下的兩行:
vendors: './app/vendors.js'
…
filename: '[name].js',
改成:
vendor: ['lodash', 'moment']
…
filename: '[chunkhash].[name].js',
然後再執行 webpack
指令,最後會產生 [hash].vendor.js
檔案([hash]就是一串編碼後的數字),而這個檔案就是包含了 lodash
以及 moment
了。而 ./app/index.js
最後會產生 ./dist/app.js
,但因為./app/index.js
這個檔有 require lodash
和 moment
,所以 ./dist/app.js
檔裡面也會包含 lodash
和 moment
,顯然這樣重覆了,因為變成在 vendor.js 以及 app.js 都有 lodash
和 'moment'。
這時我們需要在修改一下 webpack.config.js
,新增以下的 new webpack.optimize.CommonsChunkPlugin
:
…
plugins: [
…
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor' // Specify the common bundle's name.
})
]
…
這個時間再執行 webpack
指令,即使 ./app/index.js
有 require lodash
和 moment
,但其實 bundle 後的 ./dist/app.js
並不會包含 lodash
和 moment
了,這才真正的達到我們的需求:將 Libraries 抽離出來到另外的檔案。
Manifest File
再優化這邊再提一下,根據官方說法,當 application code(以此例來說就是 ./app/index.js
檔),有做任何改變的時候,然後再執行 webpack
指令後,所 bundle 出來的 ./dist/[hash].app.js
、./dist/[hash].vendor.js
,都會完全產生新的檔案,這其實就不太好了,因為我們會希望 ./dist/[hash].vendor.js
應該是不需要變動的,否則瀏覽器會視為不同的檔案而再重新載入。造成這樣的原因是因為 webpack 本身有自己的 runtime code
,這會造成每次執行 webpack
時,都會被視為不同的檔案,而造成 [hash]
數值不一樣。
所以為了解決此問題,需要再修改一下 webpack.config.js
:
將原來的:
…
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor' // Specify the common bundle's name.
})
…
改成:
…
new webpack.optimize.CommonsChunkPlugin({
name: ['vendor', 'manifest'] // Specify the common bundle's name.
})
…
這個時候再執行 webpack
指令,會額外產生 ./dist/[hash].manifest.js
檔,就是將 runtime code
挪出來了。之後我們只要有修改 application code(./app/index.js
),再進行 webpack
指令的話,./app/vendor.js
所 bundle 出來的檔案,就都會是同一個了,[hash]
碼也會一樣,而達到 vendor cache 的效果。
其實今天寫到這,也已經過了一半以上的天數了,我原本還在想 webpack
可以寫到 30 天嗎?嗯…看來可以,愈寫我愈覺得… webpack
很深奧,而明天,我還要挑戰下個問題…
這邊要提一下明天要講的 html-webpack-plugin
,現在若執行 webpack-dev-server --open
的話,瀏覽 http://localhost:8080/
,於 console 檔中會看到載入的檔案檔名是有誤的,因為我在 webpack.config.js
檔中的 output 的 filename 中,我改成了 filename: '[chunkhash].[name].js',
,這會造成每次執行webpack
指令時,若hash碼有更動,那我們於 ./index.html
檔中的路徑就需要再改寫,豈不是很麻煩嗎?
有沒有辦法自動載入正確的檔案呢?我明天來研究一下 html-webpack-plugin,希望有好的解法,敬請期待!