webpack代碼分割
webpack 可以幫助我們將代碼分成不同的邏輯塊,在需要的時候加載這些代碼。
使用 require.ensure() 來拆分代碼
require.ensure() 是一種使用 CommonJS 的形式來異步加載模塊的策略。在代碼中通過 require.ensure([<fileurl>]) 引用模塊
require.ensure(dependencies: String[], callback: function(require), chunkName: String)
使用 require.ensure() 來拆分代碼
require.ensure() 是一種使用 CommonJS 的形式來異步加載模塊的策略。在代碼中通過 require.ensure([<fileurl>]) 引用模塊
require.ensure(dependencies: String[], callback: function(require), chunkName: String)
第一個參數指定依賴的模塊,
第二個參數是一個函數,
在這個函數里面你可以使用 require 來加載其他的模塊,webpack 會收集 ensure 中的依賴,將其打包在一個單獨的文件中,
在后續用到的時候使用 jsonp 異步地加載進去。
js懶加載
直接上代代碼吧,看着直接。
require.ensure(['./a'],function(require){ let b = require('./b'); let a = require('./a'); console.log(a+b); })
以上代碼,a 和 b 會被打包在一起,在代碼中執行到這段代碼的時候,會異步地去加載,加載完成后執行函數里面的邏輯。
那就是說a和b合並成一個文件,代碼走到這里的時候才會去下載這個文件。當然這里是不是要加一個轉圈呢啥的,畢竟是異步加載嘛。
這個稍微麻煩點,可以自己去百度。
webpack代碼分割
還記得webpack中的chunkFilename嗎?不知道沒關系。
output: { path: config.build.assetsRoot, filename: utils.assetsPath('js/[name].[chunkhash].js'), chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') },
扣了一小段代碼。這個是vue腳手架里面的。在build/webpack.prod.conf.js文件中,這個是走npm run build才會進來的。
那怎么配合chunkFilename做代碼分割呢。
上代碼:
require.ensure(['./c'],function(require){ let a = require('./a'); console.log(a); },'d'); require.ensure(['./c'],function(require){ let b = require('./b'); console.log(b); },'d');
簡單介紹下以上代碼,這兒‘d’就是最終打包成的chunkFilename 中的name。
chunkFilename: utils.assetsPath('js/[name].[chunkhash].js')
name最終a,b,c會被打包到一個叫d.hash.js的文件中去。
require.ensure()與import的區別
在webpack 2的官網上寫了這么一句話:
require.ensure()特定於的WebPack並由進口import()取代。
所以,在webpack 2里面應該是不建議使用require.ensure()這個方法的。但是目前該方法仍然有效,所以可以簡單介紹一下。包括在webpack 1中也是可以使用。
import()
這個的進口不同於模塊引入時的導入,可以理解為一個動態加載的模塊的函數(函數等),傳入其中的參數就是相應的模塊。例如對於原有的模塊引入從 '反應' 導入寫為進口('反應')但是需要注意的是,進口()會返回一個無極對象因此,可以通過如下方式使用:
btn.addEventListener('click',e => { //在這里加載聊天組件相關資源chat.js import('/ components / chart')。then(mod => { someOperate(MOD); }); });
可以看到,使用方式非常簡單,和平時我們使用的承諾並沒有區別當然,也可以再加入一些異常處理:
btn.addEventListener('click',e => { import('/ components / chart')。then(mod => { someOperate(MOD); })。catch(err => { 的的console.log('失敗'); }); });
當然,由於進口()會返回一個承諾對象,因此要注意一些兼容性問題。解決這個問題也不困難,可以使用一些承諾的填充工具來實現兼容。可以看到,動態導入()的方式不論在語意上還是語法使用上都是比較清晰簡潔的。
VUE使用實例
例:require.ensure()實現
const notFound = r => require.ensure([], () => r(require('@views/common/404')), 'index') const login = r => require.ensure([], () => r(require('@views/common/login')), 'index') const register = r => require.ensure([], () => r(require('@views/common/register')), 'index') const main = r => require.ensure([], () => r(require('@views/main')), 'index') const myWorks = r => require.ensure([], () => r(require('@views/my/index')), 'my') const myAccountSetting = r => require.ensure([], () => r(require('@views/my/account-setting')), 'my') const makeIndex = r => require.ensure([], () => r(require('@views/make/index')), 'make')
例:import()實現
const notFound = () => import(/* webpackChunkName: "index" */ '@views/common/404') const login = () => import(/* webpackChunkName: "index" */ '@views/common/login') const register = () => import(/* webpackChunkName: "index" */ '@views/common/register') const main = () => import(/* webpackChunkName: "index" */ '@views/main') const myWorks = () => import(/* webpackChunkName: "my" */ '@views/my/index') const myAccountSetting = () => import(/* webpackChunkName: "my" */ '@views/my/account-setting') const makeIndex = () => import(/* webpackChunkName: "make" */ '@views/make/index')