一. 什麼是Code Splitting?
在最開始使用Webpack的時候, 都是將所有的js檔案全部打包到一個build.js
檔案中(檔名取決與在webpack.config.js
檔案中output.filename
), 但是在大型專案中, build.js
可能過大, 導致頁面載入時間過長. 這個時候就需要code splitting
, code splitting
就是將檔案分割成塊(chunk)
, 我們可以定義一些分割點(split point)
, 根據這些分割點對檔案進行分塊, 並實現按需載入.
二. Code Splitting的作用?
- 第三方類庫單獨打包:
由於第三方類庫的內容基本不會改變, 可以將其與業務程式碼分離出來, 這樣就可以最大化的利用瀏覽器的快取機制, 減少請求. - 按需載入:
Webpack支援定義分割點, 通過require.ensure
進行按需載入.
三. 如何進行Code Splitting?
下面的程式碼是基於vue-cli
的webpack-simple
模板生成的演示文件
//cmd
vue init webpack-simple code_spliting_demo
複製程式碼
(一) 第三方類庫單獨打包
我們假設專案中引入了jquery.js
和respond.js
, 那麼我們可以在webpack.config.js
中配置多入口來進行將這兩個第三方類庫單獨打包.
在
webpack.config.js
進行配置//webpack.config.js //在entry中新增相應第三方類庫 entry: { bundle: './src/main.js', vendor: ['./src/lib/jquery-1.10.2.min.js', './src/lib/respond.min.js'] } //在plugins中新增CommonChunkPlugin plugins:[ new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'vendor.bundle.js' }) ] 複製程式碼
執行
npm run build
, 此時dist
目錄下生成了兩個檔案, 分別是build.js
和vendor.bundle.js
npm run build後的生成檔案在
index.html
中引入, 注意:vendor.bundle.js
優先於build.js
引入//index.html <script src="/dist/vendor.bundle.js"></script> <script src="/dist/build.js"></script> 複製程式碼
(二) 按需載入
我們可以在router
中進行配置, 實現元件的按需載入, 在一些單個元件檔案較大的時候, 採用按需載入能夠減少build.js
的體積, 優化載入速度(如果元件的體積較小, 那麼採用按需載入會增加額外的http請求
, 反倒增加了載入時間)
這裡, 我們增加3個元件,分別是
A.vue
,B.vue
,C.vue
//A.vue <template> <h1>這裡是A.vue元件</h1> </template> //B.vue <template> <h1>這裡是B.vue元件</h1> </template> //C.vue <template> <h1>這裡是C.vue元件</h1> </template> 複製程式碼
在路由中進行配置 (注意:這裡是為了方便, 是在
app.js
中新增的路由, 在實際的專案中, 路由應該單獨抽取出來)//app.js import Vue from 'vue' import App from './App.vue' import VueRouter from 'vue-router' Vue.use(VueRouter) //AMD規範的非同步載入 const ComA = resolve => require(['./components/A.vue' ], resolve); const ComB = resolve => require(['./components/B.vue' ], resolve); const ComC = resolve => require(['./components/C.vue' ], resolve); const router = new VueRouter({ routes: [ { name: 'component-A', path: '/a', component: ComA }, { name: 'component-B', path: '/b', component: ComB }, { name: 'component-C', path: '/c', component: ComC } ] }) new Vue({ el: '#app', router: router, render: h => h(App) }) 複製程式碼
在
webpack.config.js
中進行配置output.chunkFilename
,
//webpack.config.js
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js',
//新增chundkFilename
chunkFilename: '[name].[chunkhash:5].chunk.js'
}
複製程式碼
執行
npm run build
, 此時dist
目錄下生成了5個檔案, 多出的3個檔案,就是對應的A.vue
,B.vue
,C.vue
這三個元件npm run build後生成的檔案
CMD規範的非同步載入
剛才在路由引入的時候, 使用的是AMD規範
的非同步載入. webpack
提供了require.ensure()
這個方法實現CMD規範
的非同步載入. 這同樣也是webpack
推薦的載入方式.想深入瞭解ensure
, 請點選《webpack程式碼分離 ensure 看了還不懂,你打我》
- 下面的程式碼是使用
require.ensure()
方法對路由進行配置
//app.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
//AMD風格的非同步載入
// const ComA = resolve => require(['./components/A.vue' ], resolve);
// const ComB = resolve => require(['./components/B.vue' ], resolve);
// const ComC = resolve => require(['./components/C.vue' ], resolve);
//CMD風格的非同步載入
const ComA = resolve => require.ensure([], () => resolve(require('./components/A.vue')));
const ComB = resolve => require.ensure([], () => resolve(require('./components/B.vue')));
const ComC = resolve => require.ensure([], () => resolve(require('./components/C.vue')));
const router = new VueRouter({
routes: [
{
name: 'component-A',
path: '/a',
component: ComA
},
{
name: 'component-B',
path: '/b',
component: ComB
},
{
name: 'component-C',
path: '/c',
component: ComC
}
]
})
new Vue({
el: '#app',
router: router,
render: h => h(App)
})
複製程式碼
- 執行
npm run build
後,dist
目錄下同樣生成5個檔案npm run build後生成的檔案
- 按需載入效果演示:按需載入效果演示