iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 17
0
Modern Web

使用 webpack 模組化你的程式碼,讓人生更美好。系列 第 17

<17 - 再續心法 3> Code Splitting - Libraries

  • 分享至 

  • xImage
  •  

今天想要來談談關於使用第三方程式碼的時候,該如何將它們抽離出來呢?其實在 <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 lodashmoment,所以 ./dist/app.js 檔裡面也會包含 lodashmoment,顯然這樣重覆了,因為變成在 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 lodashmoment,但其實 bundle 後的 ./dist/app.js 並不會包含 lodashmoment 了,這才真正的達到我們的需求:將 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,希望有好的解法,敬請期待!/images/emoticon/emoticon41.gif


上一篇
<16 - 再續心法 2> Code Splitting - CSS
下一篇
<18 - Plugins 小幫手 01> 自動產生 html 檔,並包含 bundle 後的檔案路徑 - html-webpack-plugin
系列文
使用 webpack 模組化你的程式碼,讓人生更美好。30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言