整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          在 Webpack 中執行代碼分割

          在 Webpack 中執行代碼分割

          三種常用的代碼分離方法:

          • 入口起點:使用 entry 配置手動地分離代碼。
          • 防止重復:使用 CommonsChunkPlugin 去重和分離 chunk。
          • 動態導入:通過模塊的內聯函數調用來分離代碼。

          1、入口起點

          這是迄今為止最簡單、最直觀的分離代碼的方式。不過,這種方式手動配置較多

          webpack.config.js


          1. const path=require('path');
          2. const HTMLWebpackPlugin=require('html-webpack-plugin');
          3. module.exports={
          4. entry: {
          5. index: './src/index.js',
          6. another: './src/another-module.js'
          7. },
          8. plugins: [
          9. new HTMLWebpackPlugin({
          10. title: 'Code Splitting'
          11. })
          12. ],
          13. output: {
          14. filename: '[name].bundle.js',
          15. path: path.resolve(__dirname, 'dist')
          16. }
          17. };

          這將生成如下構建結果


          1. Hash: 309402710a14167f42a8
          2. Version: webpack 2.6.1
          3. Time: 570ms
          4. Asset Size Chunks Chunk Names
          5. index.bundle.js 544 kB 0 [emitted] [big] index
          6. another.bundle.js 544 kB 1 [emitted] [big] another
          7. [0] ./~/lodash/lodash.js 540 kB {0} {1} [built]
          8. [1] (webpack)/buildin/global.js 509 bytes {0} {1} [built]
          9. [2] (webpack)/buildin/module.js 517 bytes {0} {1} [built]
          10. [3] ./src/another-module.js 87 bytes {1} [built]
          11. [4] ./src/index.js 216 bytes {0} [built]

          正如前面提到的,這種方法存在一些問題:

          • 如果入口 chunks 之間包含重復的模塊,那些重復模塊都會被引入到各個 bundle 中。
          • 這種方法不夠靈活,并且不能將核心應用程序邏輯進行動態拆分代碼。

          2、防止重復

          CommonsChunkPlugin 插件可以將公共的依賴模塊提取到已有的入口 chunk 中,或者提取到一個新生成的 chunk。讓我們使用這個插件,將之前的示例中重復的 lodash 模塊去除:

          webpack.config.js


          1. const path=require('path');
          2. + const webpack=require('webpack');
          3. const HTMLWebpackPlugin=require('html-webpack-plugin');
          4. module.exports={
          5. entry: {
          6. index: './src/index.js',
          7. another: './src/another-module.js'
          8. },
          9. plugins: [
          10. new HTMLWebpackPlugin({
          11. title: 'Code Splitting'
          12. - })
          13. + }),
          14. + new webpack.optimize.CommonsChunkPlugin({
          15. + name: 'common' // 指定公共 bundle 的名稱。
          16. + })
          17. ],
          18. output: {
          19. filename: '[name].bundle.js',
          20. path: path.resolve(__dirname, 'dist')
          21. }
          22. };

          這里我們使用 CommonsChunkPlugin 之后,現在應該可以看出,index.bundle.js 中已經移除了重復的依賴模塊。需要注意的是,CommonsChunkPlugin 插件將 lodash 分離到單獨的 chunk,并且將其從 main bundle 中移除,減輕了大小。執行 npm run build 查看效果:


          1. Hash: 70a59f8d46ff12575481
          2. Version: webpack 2.6.1
          3. Time: 510ms
          4. Asset Size Chunks Chunk Names
          5. index.bundle.js 665 bytes 0 [emitted] index
          6. another.bundle.js 537 bytes 1 [emitted] another
          7. common.bundle.js 547 kB 2 [emitted] [big] common
          8. [0] ./~/lodash/lodash.js 540 kB {2} [built]
          9. [1] (webpack)/buildin/global.js 509 bytes {2} [built]
          10. [2] (webpack)/buildin/module.js 517 bytes {2} [built]
          11. [3] ./src/another-module.js 87 bytes {1} [built]
          12. [4] ./src/index.js 216 bytes {0} [built]

          以下是由社區提供的,一些對于代碼分離很有幫助的插件和 loaders:

          • ExtractTextPlugin: 用于將 CSS 從主應用程序中分離。
          • bundle-loader: 用于分離代碼和延遲加載生成的 bundle。
          • promise-loader: 類似于 bundle-loader ,但是使用的是 promises。

          CommonsChunkPlugin 插件還可以通過使用顯式的 vendor chunks 功能,從應用程序代碼中分離 vendor 模塊。

          3、動態導入

          當涉及到動態代碼拆分時, 一般使用使用webpack提供的符合 ECMAScript 提案 的 import() 語法。

          new Vue({


          1. el: '#app',
          2. components: {
          3. AsyncComponent: ()=> import('./AsyncComponent.vue')
          4. }
          5. });

          實施代碼分割并不難,難在搞清楚在什么時候、什么地方進行。

          Vue.js 單頁應用進行代碼分割有三種思路:

          • 按頁面分割
          • 使用折疊
          • 按條件分割

          1. 按頁面

          按頁面來進行代碼分割,是最明顯的一種方式。

          如果能確保每個單文件組件代表一個頁面,如 Home.vue, About.vue 以及 Contact.vue,那么我們就可以使用 Webpack 的 "動態導入" 函數 (import) 來將它們分割至單獨的構建文件中。之后后,當用戶訪問一個新頁面的時候,Webpack 將異步加載該請求的頁面文件。

          如果用到了 vue-router,由于頁面已經分割成了單獨的組件,實施起來會非常方便。


          1. const Home=()=> import(/* webpackChunkName: "home" */ './Home.vue');
          2. const About=()=> import(/* webpackChunkName: "about" */ './About.vue');
          3. const Contact=()=> import(/* webpackChunkName: "contact" */ './Contact.vue');
          4. const routes=[
          5. { path: '/', name: 'home', component: Home },
          6. { path: '/about', name: 'about', component: About },
          7. { path: '/contact', name: 'contact', component: Contact }
          8. ];

          代碼編譯完成后,通過查看生成的統計數據得知:每個頁面都有自己單獨的文件,同時有多出來一個名為 build_main.js 的打包文件。里面包含一些公共的代碼以及邏輯,用來異步加載其它文件,因此它需要在用戶訪問路由之前加載完成。

          2. 折疊

          “折疊” 是指頁面初次加載時,視圖的不可見部分。用戶通常會花費 1~2 秒來瀏覽可視區域,特別是第一次訪問網站的時候(可能更久),之后才開始向下滑動頁面。

          這個時候,可以異步加載剩余的內容。

          3. 條件展示內容

          代碼分割另一種比較好的備選方式,是按條件展示。比如:模態框、標簽頁、下拉菜單之類。

          如果我們需要一個模態框,給模態框設置 v-if 屬性,綁定了 show 變量。一方面用來控制模態框是否顯示,同時也決定了是否應該渲染模態框組件。當頁面加載的時候,它的值為 false,模態框的代碼只有當它顯示的時候才會被加載。如果用戶永遠不打開這個模態框,這部分代碼就永遠不會被下載。缺點是,可能會增加很小的用戶體驗成本:用戶點擊按鈕后,需要等待代碼文件下載完成。

          代碼分離是webpack最關注的特性之一,此特性可以將代碼分離到不同的bundle,以及控制加載資源優先級別,代碼分離后可以壓縮代碼文件的大小,如果使用合理可以大幅提高資源文件的加載速度。

          有三種常用的分離方法:

          入口分離:使用entry手動配置分離代碼。

          防止重復:使用CommonsChunkPlugin去除重復和分離chunk.

          動態導入:通過模塊的內聯函數調用來分離代碼。

          入口起點是最簡單最直觀的分離代碼的方式。不過這種方式手動配置比較多,會有點坑。但是這些坑注定還是要解決的。

          先建個demo項目,項目結構如下:

          another-module.js:

          index.js:

          webpack.config.js:

          可以看到index.js和another-module.js同時都有引入了lodash,這樣做必然會產生重復引入loadsh。

          構建項目結果:

          這種方式雖然可以實現代碼,但是造成代碼重復引用。還好webpack提供了CommonsChunkPlugin插件去除重復,將重復的一部分抽取到單獨一個公共文件里面。

          現在修改一下webpack.config.js文件

          new webpack.optimize.CommonsChunkPlugin({

          name:'common'

          })

          添加抽取公共代碼實例對象,common公共文件名稱的前綴。

          執行構建命令,在dist文件夾下多了common.bundle.js。這個就是公共文件

          打開index.html,在控制臺還是可以看到有index.js和another-module.js打印的信息。

          在webpack中還有一種方式是動態導入的方式,這個可以去搜一下,這里就不演示了。

          碼分離是 webpack 中最引人注目的特性之一。此特性能夠把代碼分離到不同的 bundle 中,然后可以按需加載或并行加載這些文件。代碼分離可以用于獲取更小的 bundle,以及控制資源加載優先級,如果使用合理,會極大影響加載時間。

          常用的代碼分離方法有三種:

          • 入口起點:使用 entry 配置手動地分離代碼。
          • 防止重復:使用 Entry dependencies 或者 SplitChunksPlugin 去重和分離 chunk。
          • 動態導入:通過模塊的內聯函數調用來分離代碼。

          1.8.1 入口起點

          這是迄今為止最簡單直觀的分離代碼的方式。不過,這種方式手動配置較多,并有一些隱患,我們將會解決這些問題。先來看看如何從 main bundle 中分離 another module(另一個模塊):

          src目錄下創建 another-module.js文件:

          09-code-splitting/src/another-module.js

          import _ from 'lodash'
          
          console.log(_.join(['Another', 'module', 'loaded!'], ' '))

          這個模塊依賴了 lodash,需要安裝一下:

           [felix] webpack5 $ npm install lodash --save-dev

          修改配置文件:

          module.exports={
             entry: {
               index: './src/index.js',
               another: './src/another-module.js',
             },
             output: {
               filename: '[name].bundle.js'
             },
           }

          09-code-splitting/webpack.config.js

          //...
          
          module.exports={
          entry: {
             index: './src/index.js',
             another: './src/another-module.js',
          },
          
          output: {
             filename: '[name].bundle.js'
              //...
            },
          
           //...
          }

          執行編譯:

          [felix] 09-code-splitting $ npx webpack
          assets by status 744 KiB [cached] 4 assets
          assets by status 1.44 MiB [emitted]
            asset another.bundle.js 1.38 MiB [emitted] (name: another)
            asset index.bundle.js 65.1 KiB [emitted] (name: index)
            asset app.html 441 bytes [emitted]
          Entrypoint index 68.9 KiB (740 KiB)=styles/4a9cff551c7a105e1554.css 3.81 KiB index.bundle.js 65.1 KiB 3 auxiliary assets
          Entrypoint another 1.38 MiB=another.bundle.js
          runtime modules 3.23 KiB 12 modules
          cacheable modules 549 KiB (javascript) 738 KiB (asset) 2.65 KiB (css/mini-extract)
            javascript modules 546 KiB
              modules by path ../node_modules/ 540 KiB 9 modules
              modules by path ./src/ 5.48 KiB 8 modules
            asset modules 3.1 KiB (javascript) 738 KiB (asset)
              ./src/assets/img-1.png 42 bytes (javascript) 101 KiB (asset) [built] [code generated]
              ./src/assets/webpack-logo.svg 2.99 KiB [built] [code generated]
              ./src/assets/example.txt 25 bytes [built] [code generated]
              ./src/assets/qianfeng-sem.jpg 42 bytes (javascript) 637 KiB (asset) [built] [code generated]
            json modules 565 bytes
              ./src/assets/json/data.toml 188 bytes [built] [code generated]
              ./src/assets/json/data.yaml 188 bytes [built] [code generated]
              ./src/assets/json/data.json5 189 bytes [built] [code generated]
            css ../node_modules/css-loader/dist/cjs.js!./src/style.css 2.65 KiB [built] [code generated]
          webpack 5.54.0 compiled successfully in 854 ms

          asset another.bundle.js 1.38 MiB [emitted] (name: another) , 我們發現 lodash.js也被打包到 another.bundle.js 中。

          查看 app.html

          09-code-splitting/dist/app

          <!DOCTYPE html>
          <html lang="en">
          
          <head>
          <meta charset="UTF-8">
          <meta http-equiv="X-UA-Compatible" content="IE=edge">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>千鋒大前端教研院-Webpack5學習指南</title>
          <link href="styles/4a9cff551c7a105e1554.css" rel="stylesheet">
          </head>
          
          <body>
          <script defer src="index.bundle.js"></script>
          <script defer src="another.bundle.js"></script>
          </body>
          
          </html>

          兩個入口的 bundle文件都被鏈接到了 app.html中。

          我們再來修改一下 index.js文件:

          import _ from 'lodash'
          
          console.log(_.join(['index', 'module', 'loaded!'], ' '))

          09-code-splitting/src/index.js

          // 導入模塊
          //...
          import _ from 'lodash'
          
          //...
          
          console.log(_.join(['index', 'module', 'loaded!'], ' '))

          執行編譯:

          [felix] 09-code-splitting $ npx webpack
          assets by status 744 KiB [cached] 4 assets
          assets by path . 2.82 MiB
            asset index.bundle.js 1.44 MiB [emitted] (name: index)
            asset another.bundle.js 1.38 MiB [compared for emit] (name: another)
            asset app.html 441 bytes [compared for emit]
          Entrypoint index 1.44 MiB (740 KiB)=styles/4a9cff551c7a105e1554.css 3.81 KiB index.bundle.js 1.44 MiB 3 auxiliary assets
          Entrypoint another 1.38 MiB=another.bundle.js
          runtime modules 3.35 KiB 13 modules
          cacheable modules 549 KiB (javascript) 738 KiB (asset) 2.65 KiB (css/mini-extract)
            javascript modules 546 KiB
              modules by path ../node_modules/ 540 KiB 9 modules
              modules by path ./src/ 5.57 KiB 8 modules
            asset modules 3.1 KiB (javascript) 738 KiB (asset)
              ./src/assets/img-1.png 42 bytes (javascript) 101 KiB (asset) [built] [code generated]
              ./src/assets/webpack-logo.svg 2.99 KiB [built] [code generated]
              ./src/assets/example.txt 25 bytes [built] [code generated]
              ./src/assets/qianfeng-sem.jpg 42 bytes (javascript) 637 KiB (asset) [built] [code generated]
            json modules 565 bytes
              ./src/assets/json/data.toml 188 bytes [built] [code generated]
              ./src/assets/json/data.yaml 188 bytes [built] [code generated]
              ./src/assets/json/data.json5 189 bytes [built] [code generated]
            css ../node_modules/css-loader/dist/cjs.js!./src/style.css 2.65 KiB [built] [code generated]
          webpack 5.54.0 compiled successfully in 898 ms

          觀察一下:

          assets by path . 2.82 MiB
            asset index.bundle.js 1.44 MiB [emitted] (name: index)
            asset another.bundle.js 1.38 MiB [compared for emit] (name: another)
            asset app.html 441 bytes [compared for emit]

          我們發現:index.bundle.js 文件大小也驟然增大了,可以 lodash.js也被打包到了 index.bundle.js中了。

          正如前面提到的,這種方式的確存在一些隱患:

          • 如果入口 chunk 之間包含一些重復的模塊,那些重復模塊都會被引入到各個 bundle 中。
          • 這種方法不夠靈活,并且不能動態地將核心應用程序邏輯中的代碼拆分出來。

          以上兩點中,第一點對我們的示例來說無疑是個問題,因為之前我們在 ./src/index.js 中也引入過 lodash,這樣就在兩個 bundle 中造成重復引用。

          1.8.2 防止重復

          • 入口依賴 配置 "https://webpack.docschina.org/configuration/entry-context/#dependencies">dependOn option 選項,這樣可以在多個 chunk 之間共享模塊:
          module.exports={
            entry: {
              index: {
                import: './src/index.js',
                dependOn: 'shared',
              },
              another: {
                import: './src/another-module.js',
                dependOn: 'shared',
              },
              shared: 'lodash',
            }
          }

          09-code-splitting/webpack.config.js

          //...
          
          module.exports={
          entry: {
          index: {
           import: './src/index.js',
           dependOn: 'shared',
          },
          another: {
           import: './src/another-module.js',
             dependOn: 'shared',
             },
              shared: 'lodash',
            },
          
           //...
          }

          執行編譯

          [felix] 09-code-splitting $ npx webpack
          assets by status 744 KiB [cached] 4 assets
          assets by status 1.45 MiB [emitted]
          asset shared.bundle.js 1.39 MiB [emitted] (name: shared)
          asset index.bundle.js 57.1 KiB [emitted] (name: index)
          asset another.bundle.js 1.53 KiB [emitted] (name: another)
          asset app.html 487 bytes [emitted]
          Entrypoint index 60.9 KiB (740 KiB)=styles/4a9cff551c7a105e1554.css 3.81 KiB index.bundle.js 57.1 KiB 3 auxiliary assets
          Entrypoint another 1.53 KiB=another.bundle.js
          Entrypoint shared 1.39 MiB=shared.bundle.js
          runtime modules 4.47 KiB 9 modules
          cacheable modules 549 KiB (javascript) 738 KiB (asset) 2.65 KiB (css/mini-extract)
          javascript modules 546 KiB
          modules by path ../node_modules/ 540 KiB 9 modules
          modules by path ./src/ 5.57 KiB 8 modules
          asset modules 3.1 KiB (javascript) 738 KiB (asset)
          ./src/assets/img-1.png 42 bytes (javascript) 101 KiB (asset) [built] [code generated]
          ./src/assets/webpack-logo.svg 2.99 KiB [built] [code generated]
          ./src/assets/example.txt 25 bytes [built] [code generated]
          ./src/assets/qianfeng-sem.jpg 42 bytes (javascript) 637 KiB (asset) [built] [code generated]
          json modules 565 bytes
          ./src/assets/json/data.toml 188 bytes [built] [code generated]
          ./src/assets/json/data.yaml 188 bytes [built] [code generated]
          ./src/assets/json/data.json5 189 bytes [built] [code generated]
          css ../node_modules/css-loader/dist/cjs.js!./src/style.css 2.65 KiB [built] [code generated]
          webpack 5.54.0 compiled successfully in 1237 ms

          觀察一下:

           assets by status 1.45 MiB [emitted]
            asset shared.bundle.js 1.39 MiB [emitted] (name: shared)
            asset index.bundle.js 57.1 KiB [emitted] (name: index)
            asset another.bundle.js 1.53 KiB [emitted] (name: another)
            asset app.html 487 bytes [emitted]

          index.bundle.jsanother.bundle.js共享的模塊lodash.js被打包到一個單獨的文件shared.bundle.js中。

          SplitChunksPlugin

          SplitChunksPlugin 插件可以將公共的依賴模塊提取到已有的入口 chunk 中,或者提取到一個新生成的 chunk。讓我們使用這個插件,將之前的示例中重復的 lodash 模塊去除:

          entry: {
          	index: './src/index.js',
            another: './src/another-module.js'
          },
              
          optimization: {
            splitChunks: {
            	chunks: 'all',
            },
          },

          09-code-splitting/webpack.config.js

          //...
          
          module.exports={
          // entry: {
          //   index: {
          //     import: './src/index.js',
          //     dependOn: 'shared',
          //   },
          //   another: {
          //     import: './src/another-module.js',
          //     dependOn: 'shared',
          //   },
          //   shared: 'lodash',
          // },
          entry: {
           index: './src/index.js',
           another: './src/another-module.js'
          },
          
          //...
          
          optimization: {
             //...
          
           splitChunks: {
             chunks: 'all',
           }
           },
          }

          執行編譯

          執行編譯:
          [felix] 09-code-splitting $ npx webpack
          assets by status 744 KiB [cached] 4 assets
          assets by status 1.46 MiB [emitted]
            asset vendors-node_modules_lodash_lodash_js.bundle.js 1.37 MiB [emitted] (id hint: vendors)
            asset index.bundle.js 75.3 KiB [emitted] (name: index)
            asset another.bundle.js 17.2 KiB [emitted] (name: another)
            asset app.html 518 bytes [emitted]
          Entrypoint index 1.45 MiB (740 KiB)=vendors-node_modules_lodash_lodash_js.bundle.js 1.37 MiB styles/4a9cff551c7a105e1554.css 3.81 KiB index.bundle.js 75.3 KiB 3 auxiliary assets
          Entrypoint another 1.39 MiB=vendors-node_modules_lodash_lodash_js.bundle.js 1.37 MiB another.bundle.js 17.2 KiB
          runtime modules 8.1 KiB 17 modules
          cacheable modules 549 KiB (javascript) 738 KiB (asset) 2.65 KiB (css/mini-extract)
            javascript modules 546 KiB
              modules by path ../node_modules/ 540 KiB 9 modules
              modules by path ./src/ 5.57 KiB 8 modules
            asset modules 3.1 KiB (javascript) 738 KiB (asset)
              ./src/assets/img-1.png 42 bytes (javascript) 101 KiB (asset) [built] [code generated]
              ./src/assets/webpack-logo.svg 2.99 KiB [built] [code generated]
              ./src/assets/example.txt 25 bytes [built] [code generated]
              ./src/assets/qianfeng-sem.jpg 42 bytes (javascript) 637 KiB (asset) [built] [code generated]
            json modules 565 bytes
              ./src/assets/json/data.toml 188 bytes [built] [code generated]
              ./src/assets/json/data.yaml 188 bytes [built] [code generated]
              ./src/assets/json/data.json5 189 bytes [built] [code generated]
            css ../node_modules/css-loader/dist/cjs.js!./src/style.css 2.65 KiB [built] [code generated]
          webpack 5.54.0 compiled successfully in 914 ms

          觀察一下

          assets by status 1.46 MiB [emitted]
            asset vendors-node_modules_lodash_lodash_js.bundle.js 1.37 MiB [emitted] (id hint: vendors)
            asset index.bundle.js 75.3 KiB [emitted] (name: index)
            asset another.bundle.js 17.2 KiB [emitted] (name: another)
            asset app.html 518 bytes [emitted]

          使用 optimization.splitChunks 配置選項之后,現在應該可以看出,index.bundle.jsanother.bundle.js 中已經移除了重復的依賴模塊。需要注意的是,插件將 lodash 分離到單獨的 chunk,并且將其從 main bundle 中移除,減輕了大小。

          1.8.3 動態導入

          當涉及到動態代碼拆分時,webpack 提供了兩個類似的技術。第一種,也是推薦選擇的方式是,使用符合 ECMAScript 提案 的 "https://webpack.docschina.org/api/module-methods/#import-1">import() 語法 來實現動態導入。第二種,則是 webpack 的遺留功能,使用 webpack 特定的 require.ensure。讓我們先嘗試使用第一種……

          創建 async-module.js文件:

          內容如下:

          09-code-splitting/src/async-module.js

          function getComponent() {
           return import('lodash')
              .then(({
                default: _
              })=> {
                const element=document.createElement('div')
          
                element.innerHTML=_.join(['Hello', 'webpack'], ' ')
                return element
              })
              .catch((error)=> 'An error occurred while loading the component')
          }
          
          getComponent().then((component)=> {
           document.body.appendChild(component)
          })

          在入口文件中導入:

          import './async-module'

          09-code-splitting/src/index.js

          // 導入模塊
          //...
          import './async-module'
          
          //...

          執行編譯:

                 [felix] 09-code-splitting $ npx webpack
          assets by status 744 KiB [cached] 4 assets
          assets by status 1.53 MiB [compared for emit]
            assets by chunk 1.46 MiB (id hint: vendors)
              asset vendors-node_modules_lodash_lodash_js.bundle.js 1.37 MiB [compared for emit] (id hint: vendors)
              asset vendors-node_modules_babel_runtime_regenerator_index_js-node_modules_css-loader_dist_runtime_-86adfe.bundle.js 93.8 KiB [compared for emit] (id hint: vendors)
            asset index.bundle.js 54.3 KiB [compared for emit] (name: index)
            asset another.bundle.js 17.2 KiB [compared for emit] (name: another)
            asset app.html 658 bytes [compared for emit]
          Entrypoint index 1.52 MiB (740 KiB)=vendors-node_modules_lodash_lodash_js.bundle.js 1.37 MiB vendors-node_modules_babel_runtime_regenerator_index_js-node_modules_css-loader_dist_runtime_-86adfe.bundle.js 93.8 KiB styles/4a9cff551c7a105e1554.css 3.81 KiB index.bundle.js 54.3 KiB 3 auxiliary assets
          Entrypoint another 1.39 MiB=vendors-node_modules_lodash_lodash_js.bundle.js 1.37 MiB another.bundle.js 17.2 KiB
          runtime modules 9.21 KiB 18 modules
          ....

          從打印的結果看,除了公共的 lodash 代碼被單獨打包到一個文件外,還生成了一個 vendors-node_modules_babel_runtime_regenerator_index_js-node_modules_css-loader_dist_runtime_-86adfe.bundle.js 文件。

          我們看到,靜態和動態載入的模塊都正常工作了。

          1.8.4 懶加載

          懶加載或者按需加載,是一種很好的優化網頁或應用的方式。這種方式實際上是先把你的代碼在一些邏輯斷點處分離開,然后在一些代碼塊中完成某些操作后,立即引用或即將引用另外一些新的代碼塊。這樣加快了應用的初始加載速度,減輕了它的總體體積,因為某些代碼塊可能永遠不會被加載。

          創建一個 math.js 文件,在主頁面中通過點擊按鈕調用其中的函數:

          09-code-splitting/src/math.js

          export const add=()=> {
          	return x + y
          }
          
          export const minus=()=> {
          	return x - y
          }

          編輯 index.js文件:

          const button=document.createElement('button')
          button.textContent='點擊執行加法運算'
          button.addEventListener('click', ()=> {
            import(/* webpackChunkName: 'math' */ './math.js').then(({ add })=> {
              console.log(add(4, 5))
            })
          })
          document.body.appendChild(button)

          這里有句注釋,我們把它稱為 webpack 魔法注釋:webpackChunkName: 'math', 告訴webpack打包生成的文件名為 math

          啟動服務,在瀏覽器上查看:

          ?

          第一次加載完頁面,math.bundle.js不會加載,當點擊按鈕后,才加載 math.bundle.js文件。

          1.8.5 預獲取/預加載模塊

          Webpack v4.6.0+ 增加了對預獲取和預加載的支持。

          在聲明 import 時,使用下面這些內置指令,可以讓 webpack 輸出 "resource hint(資源提示)",來告知瀏覽器:

          • prefetch(預獲取):將來某些導航下可能需要的資源
          • preload(預加載):當前導航下可能需要資源

          下面這個 prefetch 的簡單示例中,編輯 index.js文件:

          const button=document.createElement('button')
          button.textContent='點擊執行加法運算'
          button.addEventListener('click', ()=> {
            import(/* webpackChunkName: 'math', webpackPrefetch: true */ './math.js').then(({ add })=> {
              console.log(add(4, 5))
            })
          })
          document.body.appendChild(button)

          添加第二句魔法注釋:webpackPrefetch: true

          告訴 webpack 執行預獲取。這會生成 <link rel="prefetch" href="math.js"> 并追加到頁面頭部,指示著瀏覽器在閑置時間預取 math.js 文件。

          09-code-splitting/src/index.js

          // 導入模塊
          //...
          import './async-module'
          
          //...
          
          const button=document.createElement('button')
          button.textContent='點擊執行加法運算'
          button.addEventListener('click', ()=> {
          import( /* webpackChunkName: 'math', webpackPrefetch: true */ './math.js').then(({
             add
          })=> {
             console.log(add(4, 5))
          })
          })
          document.body.appendChild(button)

          啟動服務,在瀏覽器上查看:


          我們發現,在還沒有點擊按鈕時,math.bundle.js就已經下載下來了。同時,在 app.html里webpack自動添加了一句:

          ?

          點擊按鈕,執行 4+5的加法運算。

          與 prefetch 指令相比,preload 指令有許多不同之處:

          • preload chunk 會在父 chunk 加載時,以并行方式開始加載。prefetch chunk 會在父 chunk 加載結束后開始加載。
          • preload chunk 具有中等優先級,并立即下載。prefetch chunk 在瀏覽器閑置時下載。
          • preload chunk 會在父 chunk 中立即請求,用于當下時刻。prefetch chunk 會用于未來的某個時刻。
          • 瀏覽器支持程度不同。

          創建一個 print.js文件:

          export const print=()=> {
            console.log('preload chunk.')
          }

          修改 index.js文件:

          const button2=document.createElement('button')
          button2.textContent='點擊執行字符串打印'
          button2.addEventListener('click', ()=> {
            import(/* webpackChunkName: 'print', webpackPreload: true */ './print.js').then(({ print })=> {
              print(4, 5)
            })
          })
          document.body.appendChild(button2)

          09-code-splitting/src/index.js

          // 導入模塊
          //...
          
          import './async-module'
          
          //...
          
          const button2=document.createElement('button')
          button2.textContent='點擊執行字符串打印'
          button2.addEventListener('click', ()=> {
          import( /* webpackChunkName: 'print', webpackPreload: true */ './print.js').then(({
             print
          })=> {
             print()
          })
          })
          document.body.appendChild(button2)

          啟動服務,打開瀏覽器:

          ?仔細觀察,發現 print.bundle.js未被下載,因為我們配置的是 webpackPreload, 是在父 chunk 加載時,以并行方式開始加載。點擊按鈕才加載的模塊不會事先加載的。

          我們修改一下引入方式:

          09-code-splitting/src/index.js

          //...
          import( /* webpackChunkName: 'print', webpackPreload: true */ './print.js').then(({
          print
          })=> {
          print()
          })

          再次刷新瀏覽器頁面:

          print.bundle.js被加載下來,是和當前index.bundle.js并行加載的。


          主站蜘蛛池模板: 国偷自产一区二区免费视频| 少妇人妻精品一区二区三区| 极品尤物一区二区三区| 精品视频一区二区三区免费| 国产AV一区二区三区无码野战 | 国产经典一区二区三区蜜芽| 久久精品一区二区三区四区| 麻豆高清免费国产一区| 国产精品久久无码一区二区三区网| 夜夜高潮夜夜爽夜夜爱爱一区| 日本美女一区二区三区| 视频一区精品自拍| 精品人妻中文av一区二区三区| 无码人妻精品一区二区三区9厂| 美女AV一区二区三区| 亚洲乱色熟女一区二区三区丝袜 | 国产伦精品一区二区三区女| 日本一区中文字幕日本一二三区视频| 亚洲国产av一区二区三区| 色窝窝无码一区二区三区色欲| 国产未成女一区二区三区| 精品一区二区三区免费视频| 精品国产乱子伦一区二区三区 | 国产成人一区在线不卡| 精品一区二区三区波多野结衣| 国产精品免费视频一区| 熟妇人妻一区二区三区四区| 亚洲日本va一区二区三区| 日本精品高清一区二区| 亚洲欧美日韩一区二区三区| 在线免费视频一区| 色欲AV蜜臀一区二区三区| 日韩一区二区三区在线精品| 精品国产一区二区三区麻豆 | 国产精品一区三区| 亚洲AV网一区二区三区| 熟女精品视频一区二区三区| 日本一区二区三区在线视频| 精品国产一区二区三区久久久狼| 大伊香蕉精品一区视频在线| 怡红院AV一区二区三区|