webpack原理

1.webpack核心概念

entry: 一個(gè)可執(zhí)行模塊或庫的入口文件。
chunk :多個(gè)文件組成的一個(gè)代碼塊终蒂,例如把一個(gè)可執(zhí)行模塊和它所有依賴的模塊組合和一個(gè) chunk 這體現(xiàn)了webpack的打包機(jī)制雹顺。
loader :文件轉(zhuǎn)換器,例如把es6轉(zhuǎn)換為es5霎苗,scss轉(zhuǎn)換為css白热。
plugin :插件庸诱,用于擴(kuò)展webpack的功能,在webpack構(gòu)建生命周期的節(jié)點(diǎn)上加入擴(kuò)展hook為webpack加入功能晤揣。

2.webpack構(gòu)建流程

從啟動(dòng)webpack構(gòu)建到輸出結(jié)果經(jīng)歷了一系列過程,它們是:

2.1 解析webpack配置參數(shù)朱灿,合并從shell傳入和webpack.config.js文件里配置的參數(shù)昧识,生產(chǎn)最后的配置結(jié)果。

2.2 注冊(cè)所有配置的插件盗扒,好讓插件監(jiān)聽webpack構(gòu)建生命周期的事件節(jié)點(diǎn)跪楞,以做出對(duì)應(yīng)的反應(yīng)。

2.3 從配置的entry入口文件開始解析文件構(gòu)建AST語法樹侣灶,找出每個(gè)文件所依賴的文件甸祭,遞歸下去。

2.4 在解析文件遞歸的過程中根據(jù)文件類型和loader配置找出合適的loader用來對(duì)文件進(jìn)行轉(zhuǎn)換褥影。

2.5 遞歸完后得到每個(gè)文件的最終結(jié)果池户,根據(jù)entry配置生成代碼塊chunk。

2.6 輸出所有chunk到文件系統(tǒng)凡怎。

3 概括

webpack是一個(gè)打包模塊化js的工具校焦,可以通過loader轉(zhuǎn)換文件,通過plugin擴(kuò)展功能统倒。

4.Webpack的Code Splitting實(shí)現(xiàn)按需加載

4.1. 什么是Code Splitting?**

在最開始使用Webpack的時(shí)候, 都是將所有的js文件全部打包到一個(gè)build.js文件中(文件名取決與在webpack.config.js文件中output.filename), 但是在大型項(xiàng)目中, build.js可能過大, 導(dǎo)致頁面加載時(shí)間過長(zhǎng). 這個(gè)時(shí)候就需要code splitting, code splitting就是將文件分割成塊(chunk), 我們可以定義一些分割點(diǎn)(split point), 根據(jù)這些分割點(diǎn)對(duì)文件進(jìn)行分塊, 并實(shí)現(xiàn)按需加載.

4.2 Code Splitting的作用?**

  1. 第三方類庫單獨(dú)打包:
    由于第三方類庫的內(nèi)容基本不會(huì)改變, 可以將其與業(yè)務(wù)代碼分離出來, 這樣就可以最大化的利用瀏覽器的緩存機(jī)制, 減少請(qǐng)求.
  2. 按需加載:
    Webpack支持定義分割點(diǎn), 通過require.ensure進(jìn)行按需加載.

4.3 如何進(jìn)行Code Splitting?**

下面的代碼是基于vue-cliwebpack-simple模板生成的演示文檔

//cmd
vue init webpack-simple code_spliting_demo

(一) 第三方類庫單獨(dú)打包

我們假設(shè)項(xiàng)目中引入了jquery.jsrespond.js, 那么我們可以在webpack.config.js中配置多入口來進(jìn)行將這兩個(gè)第三方類庫單獨(dú)打包.

  • webpack.config.js進(jìn)行配置

    //webpack.config.js
    
    //在entry中添加相應(yīng)第三方類庫
    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'  
        })
    ]
    
    
  • 執(zhí)行npm run build, 此時(shí)dist目錄下生成了兩個(gè)文件, 分別是build.jsvendor.bundle.js

    npm run build后的生成文件
  • index.html中引入, 注意: vendor.bundle.js優(yōu)先于build.js引入

    //index.html
    
    <script src="/dist/vendor.bundle.js"></script>
    <script src="/dist/build.js"></script>
    
    

(二) 按需加載

我們可以在router中進(jìn)行配置, 實(shí)現(xiàn)組件的按需加載, 在一些單個(gè)組件文件較大的時(shí)候, 采用按需加載能夠減少build.js的體積, 優(yōu)化加載速度(如果組件的體積較小, 那么采用按需加載會(huì)增加額外的http請(qǐng)求, 反倒增加了加載時(shí)間)

  • 這里, 我們?cè)黾?個(gè)組件,分別是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>
    
    
  • 在路由中進(jìn)行配置 (注意:這里是為了方便, 是在app.js中添加的路由, 在實(shí)際的項(xiàng)目中, 路由應(yīng)該單獨(dú)抽取出來)

    //app.js
    
    import Vue from 'vue'
    import App from './App.vue'
    import VueRouter from 'vue-router'
    Vue.use(VueRouter)
    
    //AMD規(guī)范的異步載入
    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中進(jìn)行配置output.chunkFilename,

//webpack.config.js

output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'build.js',
    //添加chundkFilename
    chunkFilename: '[name].[chunkhash:5].chunk.js'
}

  • 執(zhí)行npm run build, 此時(shí)dist目錄下生成了5個(gè)文件, 多出的3個(gè)文件,就是對(duì)應(yīng)的A.vue, B.vue, C.vue這三個(gè)組件

    npm run build后生成的文件

CMD規(guī)范的異步載入

剛才在路由引入的時(shí)候, 使用的是AMD規(guī)范的異步載入. webpack提供了require.ensure()這個(gè)方法實(shí)現(xiàn)CMD規(guī)范的異步載入. 這同樣也是webpack推薦的載入方式.想深入了解ensure, 請(qǐng)點(diǎn)擊《webpack代碼分離 ensure 看了還不懂寨典,你打我》

  • 下面的代碼是使用require.ensure()方法對(duì)路由進(jìn)行配置
//app.js

import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)

//AMD風(fēng)格的異步加載
// 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風(fēng)格的異步加載
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)
})

  • 執(zhí)行npm run build后, dist目錄下同樣生成5個(gè)文件

    npm run build后生成的文件

webpack Tree Shaking

隨著縮小和樹搖動(dòng),我們的捆綁現(xiàn)在變小了幾個(gè)字節(jié)房匆!雖然在這個(gè)人為的例子中看起來似乎并不多耸成,但是當(dāng)處理具有復(fù)雜依賴樹的較大應(yīng)用程序時(shí),樹抖動(dòng)會(huì)導(dǎo)致束大小顯著減少浴鸿。清除無用代碼井氢,減少文件體積。

webpack scope hoisting 范圍提升

為了檢測(cè)這些導(dǎo)入鏈可以在哪里展平并轉(zhuǎn)換為一個(gè)內(nèi)聯(lián)函數(shù)赚楚,而不會(huì)影響我們的代碼毙沾。我們不僅保存了額外的函數(shù)調(diào)用,還訪問了模塊數(shù)組宠页,因此我們的代碼運(yùn)行速度比以前更快左胞。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市举户,隨后出現(xiàn)的幾起案子烤宙,更是在濱河造成了極大的恐慌,老刑警劉巖俭嘁,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件躺枕,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)拐云,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門罢猪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人叉瘩,你說我怎么就攤上這事膳帕。” “怎么了薇缅?”我有些...
    開封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵危彩,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我泳桦,道長(zhǎng)汤徽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任灸撰,我火速辦了婚禮谒府,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘梧奢。我一直安慰自己狱掂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開白布亲轨。 她就那樣靜靜地躺著趋惨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪惦蚊。 梳的紋絲不亂的頭發(fā)上器虾,一...
    開封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音蹦锋,去河邊找鬼兆沙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛莉掂,可吹牛的內(nèi)容都是我干的葛圃。 我是一名探鬼主播,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼憎妙,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼库正!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起厘唾,我...
    開封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤褥符,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后抚垃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體喷楣,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡趟大,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了铣焊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逊朽。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖曲伊,靈堂內(nèi)的尸體忽然破棺而出惋耙,到底是詐尸還是另有隱情,我是刑警寧澤熊昌,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站湿酸,受9級(jí)特大地震影響婿屹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜推溃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一昂利、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧铁坎,春花似錦蜂奸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至朴乖,卻和暖如春祖屏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背买羞。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工袁勺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人畜普。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓期丰,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親吃挑。 傳聞我的和親對(duì)象是個(gè)殘疾皇子钝荡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 幼兒繪本《小老鼠亞歷山大》內(nèi)容簡(jiǎn)介: 《小老鼠亞歷山大》講的是一只小老鼠的故事。又是影子!冰箱的影子儒鹿、蔥的影子化撕、長(zhǎng)...
    修修寶媽閱讀 869評(píng)論 0 0
  • 回家過年植阴,親自帶了九幾天蟹瘾,結(jié)果小家伙就粘上我了,睡覺必須我陪掠手,反正你在他身邊他就聽話憾朴,離開就鬧。今天第一天開工喷鸽,跟...
    魚塘小八閱讀 143評(píng)論 0 0
  • 今天众雷,結(jié)合上一篇文章的抽獎(jiǎng)小游戲,用canvas來寫一個(gè)小游戲——刮刮樂做祝。首先砾省,用canvas做一個(gè)畫布,寬高各為...
    單純的色狼閱讀 1,129評(píng)論 6 16
  • (2) 很小的時(shí)候混槐,她就已經(jīng)失去了完整的家编兄。在還沒有記憶的時(shí)候,父親就用棍子打斷了他們之間所有的聯(lián)系声登。對(duì)于父親這個(gè)...
    彩色的肥皂泡閱讀 185評(píng)論 0 0