모듈 및 코드 분할 작업

此章節會介紹 Webpack 中的 模組(모듈) 以及程式碼分離(코드 분할) 兩個 Webpack 特色,透過以上特色使專案代碼分割並以最適合方式割的

此章節包含內容:
  • 웹팩 중 모듈
  • 了解 Code Splitting 機制
  • 將所需要的模組預先載入
  • 範例展示

  • 기준 치수



    透過 Webpack 模組會將共用的方法集合在同一檔案內,並會依照不同類型進行分類,如下圖所釋:

    Webpack 根據不同的模組標準有以下幾種語句:



    ECMA 2015 : 가져오기
    CommonJS : 필수
    ASM(Asynchronous Module Definition) : 정의/요구
    CSS : @import 스타일시트

    模組支援語言



    確保 Webpack 支援這些模組,必須要使用允許的程式語言,透過 Webpack 社群所建立的 로더 支援了大量的語言例如以下幾種.
  • 타입스크립트
  • SASS
  • C++
  • 바벨
  • 부트스트랩

  • 載入模組路徑


  • 絕對路徑
    從根目錄開始定位到引用檔案
    import 'C:\사용자\프로젝트\파일';
  • 相對路徑
    根據當前檔案定位到引用檔案
    가져오기 '../src/파일';
  • 模組路徑
    從模組中搜尋名稱,引用模組內的檔案
    import '모듈/하위 디렉토리/파일';

  • 코드 분할



    允許使用者將片段的程式放入不同的套件中,並且可以按需求或是並行載入,被認為是 Webpack 最具矚目的功能.

    達成方法


  • 진입점: 可以手動設置片段程式進入點設定檔
  • SplitChunksPlugin: 並免相同程式載入,將片段的程式碼整合成群組這種群組稱為 "덩어리"
  • Dynamic Imports: 透過程式來動態將片段程式碼載入

  • 진입점



    사용 진입점 是最簡單可以達成 코드 분할 的方法.

    我們根據第一章範例的專案,增改以下內容

    src/다른 모듈.js

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


    webpack.config.js

    const path = require('path');
    module.exports = {
      mode: 'development',
      entry: {
        index: './src/index.js',
        another: './src/another-module.js'
      },
      output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
      }
    };
    


    編譯專案

    $ npm run build
    Asset Size Chunks Chunk Names
    another.bundle.js 550 KiB another [emitted] another
    index.bundle.js 550 KiB index [emitted] index
    Entrypoint index = index.bundle.js
    Entrypoint another = another.bundle.js
    


    編譯完成後再 dist 目錄下產生了 index.bundle.js/another.bundle.js 倆的檔案,但因為兩支js程式都有加載 lodash 導致兩支程式代碼重複.

    SplitChunksPlugin



    預防重複程式碼

    從剛剛의 진입점 結果我們的程式碼重複了,為了避免這個狀況我們可以使用 SplitChunks 的 Webpack 套件

    webpack.config.js
    모듈에서 中 增加 최적화 參數,再進行編譯

    const path = require('path');
    module.exports = {
      mode: 'development',
      entry: {
        index: './src/index.js',
        another: './src/another-module.js'
      },
      output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
      },
      optimization: {
        splitChunks: {
          chunks: 'all'
        }
      }
    };
    


    編譯專案

    $npm run build
    
    > [email protected] build
    > webpack --config webpack.config.js
    asset vendors-node_modules_lodash_lodash_js.bundle.js 550 KiB [emitted] (id hint: vendors)
    asset index.bundle.js 8.83 KiB [emitted] (name: index)
    asset another.bundle.js 8.75 KiB [emitted] (name: another)
    Entrypoint index 559 KiB = vendors-node_modules_lodash_lodash_js.bundle.js 550 KiB index.bundle.js 8.83 KiB
    Entrypoint another 559 KiB = vendors-node_modules_lodash_lodash_js.bundle.js 550 KiB another.bundle.js 8.75 KiB
    runtime modules 7.3 KiB 16 modules
    cacheable modules 532 KiB
      ./src/index.js 212 bytes [built] [code generated]
      ./src/another-module.js 83 bytes [built] [code generated]
      ./node_modules/lodash/lodash.js 531 KiB [built] [code generated]
    webpack 5.69.1 compiled successfully in 326 ms
    


    此時除了 anotherjs 與 indexjs 外多了一個檔案 "vendors-node_modules_lodash_lodash_js.bundle.js"lodash 的代碼就統一放在這個檔案,避免代碼重複



    現在我們了解了如何避免重複代碼,接下來就要換到另一個更難的主題,Dynamic Imports.

    동적 가져오기



    동적 가져오기는 온디맨드 가져오기를 구현하는 방법입니다.

    webpack.config.js
    출력 中增加 chunkFilename 指定Dynamic Import Moudle 檔案名稱

    const path = require('path');
    module.exports = {
      mode: 'development',
      entry: {
        index: './src/index.js'
      },
      output: {
        filename: '[name].bundle.js',
        chunkFilename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
      },
    };
    


    index.js
    透過在程式中 import 以動態的方式載入第三方模組,編譯過後就會產生相應檔案,並透過 webpackChunkName 指定產出名稱.

    function getComponent() {
      return import(/* webpackChunkName: "lodash" */ 'lodash').then(({ default: _ }) => {
      var 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);
    });
    


    編譯專案

    $npm run build
    > [email protected] build
    > webpack --config webpack.config.js
    
    asset another.bundle.js 554 KiB [emitted] (name: another)
    asset lodash.bundle.js 550 KiB [emitted] (name: lodash) (id hint: vendors)
    asset index.bundle.js 14.2 KiB [emitted] (name: index)
    runtime modules 9.2 KiB 17 modules
    cacheable modules 532 KiB
      ./src/index.js 390 bytes [built] [code generated]
      ./src/another-module.js 83 bytes [built] [code generated]
      ./node_modules/lodash/lodash.js 531 KiB [built] [code generated]
    webpack 5.69.1 compiled successfully in 316 ms
    


    透過這些方法可以改善瀏覽器的快取速度.

    캐싱



    章節最後也介紹了其他的 Plugin 來協助我們來預先載入或是減少記憶體用量.

    const path = require("path");
    const { CleanWebpackPlugin } = require("clean-webpack-plugin");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    module.exports = {
      entry: "./src/index.js",
      plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
          title: "Output Management",
          title: "Caching",
        }),
      ],
      output: {
        filename: "bundle.js",
        filename: "[name].[contenthash].js",
        path: path.resolve(__dirname, "dist"),
      },
    };
    


    好了我們的第二章節 모듈 작업 및 코드 분할 結束 🎉
    後面的章節會再介紹有關 Webpack 的強大功能!敬請期待!

    좋은 웹페이지 즐겨찾기