Sử dụng bộ nhớ đệm trong thời gian dài

Cách webpack giúp lưu thành phần vào bộ nhớ đệm

Điều tiếp theo (sau khi tối ưu hoá kích thước ứng dụng để cải thiện thời gian tải ứng dụng là lưu vào bộ nhớ đệm. Sử dụng tính năng này để lưu giữ các phần của ứng dụng trên máy khách và tránh phải tải lại các phần đó mỗi khi cần.

Phương pháp phổ biến của việc lưu vào bộ nhớ đệm là:

  1. yêu cầu trình duyệt lưu tệp vào bộ nhớ đệm trong một thời gian rất dài (ví dụ: một năm):

    # Server header
    Cache-Control: max-age=31536000
    

    Nếu bạn chưa hiểu rõ chức năng của Cache-Control, hãy xem bài đăng rất hay của Jake Archibald về các phương pháp hay nhất để lưu vào bộ nhớ đệm.

  2. và đổi tên tệp khi tệp đó thay đổi để buộc tải lại:

    <!-- Before the change -->
    <script src="./index-v15.js"></script>
    
    <!-- After the change -->
    <script src="./index-v16.js"></script>
    

Phương pháp này yêu cầu trình duyệt tải tệp JS xuống, lưu vào bộ nhớ đệm và sử dụng bản sao đã lưu vào bộ nhớ đệm. Trình duyệt sẽ chỉ truy cập mạng nếu tên tệp thay đổi (hoặc nếu một năm trôi qua).

Với webpack, bạn cũng làm như vậy, nhưng thay vì số phiên bản, bạn chỉ định hàm băm tệp. Để đưa hàm băm vào tên tệp, hãy sử dụng [chunkhash]:

// webpack.config.js
module.exports = {
  entry: './index.js',
  output: {
    filename: 'bundle.[chunkhash].js' // → bundle.8e0d62a03.js
  }
};

Nếu bạn cần tên tệp để gửi tệp đó đến ứng dụng, hãy sử dụng HtmlWebpackPlugin hoặc WebpackManifestPlugin.

HtmlWebpackPlugin là một phương pháp đơn giản nhưng kém linh hoạt hơn. Trong quá trình biên dịch, trình bổ trợ này sẽ tạo một tệp HTML bao gồm tất cả tài nguyên đã biên dịch. Nếu logic máy chủ của bạn không phức tạp, thì bạn chỉ cần:

<!-- index.html -->
<!DOCTYPE html>
<!-- ... -->
<script src="bundle.8e0d62a03.js"></script>

WebpackManifestPlugin là một phương pháp linh hoạt hơn, hữu ích nếu bạn có một phần máy chủ phức tạp. Trong quá trình tạo bản dựng, công cụ này sẽ tạo một tệp JSON có mối liên kết giữa tên tệp không có hàm băm và tên tệp có hàm băm. Hãy sử dụng JSON này trên máy chủ để tìm hiểu xem cần làm việc với tệp nào:

// manifest.json
{
  "bundle.js": "bundle.8e0d62a03.js"
}

Tài liệu đọc thêm

Trích xuất các phần phụ thuộc và thời gian chạy vào một tệp riêng

Phần phụ thuộc

Các phần phụ thuộc ứng dụng thường thay đổi ít thường xuyên hơn so với mã ứng dụng thực tế. Nếu bạn di chuyển các tệp này vào một tệp riêng biệt, trình duyệt sẽ có thể lưu các tệp này vào bộ nhớ đệm riêng biệt – và sẽ không tải lại các tệp này mỗi khi mã ứng dụng thay đổi.

Để trích xuất các phần phụ thuộc thành một phân đoạn riêng biệt, hãy thực hiện 3 bước:

  1. Thay thế tên tệp đầu ra bằng [name].[chunkname].js:

    // webpack.config.js
    module.exports = {
      output: {
        // Before
        filename: 'bundle.[chunkhash].js',
        // After
        filename: '[name].[chunkhash].js'
      }
    };
    

    Khi tạo ứng dụng, webpack sẽ thay thế [name] bằng tên của một phần. Nếu không thêm phần [name], chúng ta sẽ phải phân biệt các đoạn bằng hàm băm – điều này khá khó!

  2. Chuyển đổi trường entry thành một đối tượng:

    // webpack.config.js
    module.exports = {
      // Before
      entry: './index.js',
      // After
      entry: {
        main: './index.js'
      }
    };
    

    Trong đoạn mã này, "main" là tên của một đoạn. Tên này sẽ được thay thế cho [name] từ bước 1.

    Bây giờ, nếu bạn tạo ứng dụng, phần này sẽ bao gồm toàn bộ mã ứng dụng – giống như chúng ta chưa thực hiện các bước này. Nhưng điều này sẽ thay đổi trong giây lát.

  3. Trong webpack 4, hãy thêm tuỳ chọn optimization.splitChunks.chunks: 'all' vào cấu hình webpack:

    // webpack.config.js (for webpack 4)
    module.exports = {
      optimization: {
        splitChunks: {
          chunks: 'all'
        }
      }
    };
    

    Tuỳ chọn này cho phép phân tách mã thông minh. Với nó, webpack sẽ trích xuất mã nhà cung cấp nếu mã này lớn hơn 30 kB (trước khi rút gọn và gzip). Trình tạo gói cũng sẽ trích xuất mã chung – điều này hữu ích nếu bản dựng của bạn tạo ra một số gói (ví dụ: nếu bạn chia ứng dụng thành các tuyến).

    Trong webpack 3, hãy thêm CommonsChunkPlugin:

    // webpack.config.js (for webpack 3)
    module.exports = {
      plugins: [
        new webpack.optimize.CommonsChunkPlugin({
        // A name of the chunk that will include the dependencies.
        // This name is substituted in place of [name] from step 1
        name: 'vendor',
    
        // A function that determines which modules to include into this chunk
        minChunks: module => module.context && module.context.includes('node_modules'),
        })
      ]
    };
    

    Trình bổ trợ này lấy tất cả các mô-đun có đường dẫn bao gồm node_modules và chuyển các mô-đun đó vào một tệp riêng có tên là vendor.[chunkhash].js.

Sau những thay đổi này, mỗi bản dựng sẽ tạo ra hai tệp thay vì một: main.[chunkhash].jsvendor.[chunkhash].js (vendors~main.[chunkhash].js đối với webpack 4). Trong trường hợp webpack 4, gói nhà cung cấp có thể không được tạo nếu các phần phụ thuộc nhỏ – và điều này không sao cả:

$ webpack
Hash: ac01483e8fec1fa70676
Version: webpack 3.8.1
Time: 3816ms
                        Asset      Size  Chunks             Chunk Names
 ./main.00bab6fd3100008a42b0.js   82 kB       0  [emitted]  main
./vendor.d9e134771799ecdf9483.js  47 kB       1  [emitted]  vendor

Trình duyệt sẽ lưu các tệp này vào bộ nhớ đệm riêng – và chỉ tải xuống lại mã thay đổi.

Mã thời gian chạy Webpack

Rất tiếc, việc chỉ trích xuất mã nhà cung cấp là chưa đủ. Nếu bạn cố gắng thay đổi nội dung nào đó trong mã ứng dụng:

// index.js



// E.g. add this:
console.log('Wat');

bạn sẽ nhận thấy hàm băm vendor cũng thay đổi:

                           Asset   Size  Chunks             Chunk Names
./vendor.d9e134771799ecdf9483.js  47 kB       1  [emitted]  vendor

                            Asset   Size  Chunks             Chunk Names
./vendor.e6ea4504d61a1cc1c60b.js  47 kB       1  [emitted]  vendor

Điều này xảy ra vì gói webpack, ngoài mã của các mô-đun, còn có thời gian chạy – một đoạn mã nhỏ quản lý quá trình thực thi mô-đun. Khi bạn chia mã thành nhiều tệp, đoạn mã này sẽ bắt đầu bao gồm mối liên kết giữa mã nhận dạng đoạn và các tệp tương ứng:

// vendor.e6ea4504d61a1cc1c60b.js
script.src = __webpack_require__.p + chunkId + "." + {
    "0": "2f2269c7f0a55a5c1871"
}[chunkId] + ".js";

Webpack đưa thời gian chạy này vào phần đã tạo gần đây nhất, trong trường hợp này là vendor. Và mỗi khi bất kỳ đoạn nào thay đổi, đoạn mã này cũng sẽ thay đổi, khiến toàn bộ đoạn mã vendor thay đổi.

Để giải quyết vấn đề này, hãy di chuyển thời gian chạy vào một tệp riêng. Trong webpack 4, bạn có thể thực hiện điều này bằng cách bật tuỳ chọn optimization.runtimeChunk:

// webpack.config.js (for webpack 4)
module.exports = {
  optimization: {
    runtimeChunk: true
  }
};

Trong webpack 3, hãy thực hiện việc này bằng cách tạo thêm một phần trống bằng CommonsChunkPlugin:

// webpack.config.js (for webpack 3)
module.exports = {
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: module => module.context && module.context.includes('node_modules')
    }),
    // This plugin must come after the vendor one (because webpack
    // includes runtime into the last chunk)
    new webpack.optimize.CommonsChunkPlugin({
      name: 'runtime',
      // minChunks: Infinity means that no app modules
      // will be included into this chunk
      minChunks: Infinity
    })
  ]
};

Sau những thay đổi này, mỗi bản dựng sẽ tạo 3 tệp:

$ webpack
Hash: ac01483e8fec1fa70676
Version: webpack 3.8.1
Time: 3816ms
                            Asset     Size  Chunks             Chunk Names
   ./main.00bab6fd3100008a42b0.js    82 kB       0  [emitted]  main
 ./vendor.26886caf15818fa82dfa.js    46 kB       1  [emitted]  vendor
./runtime.79f17c27b335abc7aaf4.js  1.45 kB       3  [emitted]  runtime

Đưa các phần tử này vào index.html theo thứ tự ngược lại – và bạn đã hoàn tất:

<!-- index.html -->
<script src="./runtime.79f17c27b335abc7aaf4.js"></script>
<script src="./vendor.26886caf15818fa82dfa.js"></script>
<script src="./main.00bab6fd3100008a42b0.js"></script>

Tài liệu đọc thêm

Môi trường thời gian chạy gói web nội tuyến để lưu thêm yêu cầu HTTP

Để cải thiện hơn nữa, hãy thử đưa thời gian chạy webpack vào phản hồi HTML. Tức là thay vì:

<!-- index.html -->
<script src="./runtime.79f17c27b335abc7aaf4.js"></script>

thực hiện việc này:

<!-- index.html -->
<script>
!function(e){function n(r){if(t[r])return t[r].exports;…}} ([]);
</script>

Thời gian chạy nhỏ và việc nội tuyến sẽ giúp bạn tiết kiệm một yêu cầu HTTP (khá quan trọng với HTTP/1; ít quan trọng hơn với HTTP/2 nhưng vẫn có thể tạo ra hiệu ứng).

Sau đây là cách thực hiện.

Nếu bạn tạo HTML bằng HtmlWebpackPlugin

Nếu sử dụng HtmlWebpackPlugin để tạo tệp HTML, thì bạn chỉ cần InlineSourcePlugin:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const InlineSourcePlugin = require('html-webpack-inline-source-plugin');

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      inlineSource: 'runtime~.+\\.js',
    }),
    new InlineSourcePlugin()
  ]
};

Nếu bạn tạo HTML bằng logic máy chủ tuỳ chỉnh

Với webpack 4:

  1. Thêm WebpackManifestPlugin để biết tên được tạo của đoạn thời gian chạy:

    // webpack.config.js (for webpack 4)
    const ManifestPlugin = require('webpack-manifest-plugin');
    
    module.exports = {
      plugins: [
        new ManifestPlugin()
      ]
    };
    

    Một bản dựng có trình bổ trợ này sẽ tạo một tệp có dạng như sau:

    // manifest.json
    {
      "runtime~main.js": "runtime~main.8e0d62a03.js"
    }
    
  2. Đưa nội dung của phân đoạn thời gian chạy vào cùng dòng một cách thuận tiện. Ví dụ: với Node.js và Express:

    // server.js
    const fs = require('fs');
    const manifest = require('./manifest.json');
    const runtimeContent = fs.readFileSync(manifest['runtime~main.js'], 'utf-8');
    
    app.get('/', (req, res) => {
      res.send(`
    
        <script>${runtimeContent}</script>
    
      `);
    });
    

Hoặc với webpack 3:

  1. Đặt tên thời gian chạy ở chế độ tĩnh bằng cách chỉ định filename:

    module.exports = {
      plugins: [
        new webpack.optimize.CommonsChunkPlugin({
          name: 'runtime',
          minChunks: Infinity,
          filename: 'runtime.js'
        })
      ]
    };
    
  2. Nội dung runtime.js cùng dòng theo cách thuận tiện. Ví dụ: với Node.js và Express:

    // server.js
    const fs = require('fs');
    const runtimeContent = fs.readFileSync('./runtime.js', 'utf-8');
    
    app.get('/', (req, res) => {
      res.send(`
    
        <script>${runtimeContent}</script>
    
      `);
    });
    

Tải mã từng phần mà bạn không cần ngay lúc này

Đôi khi, một trang có các phần quan trọng hơn và kém quan trọng hơn:

  • Khi tải một trang video trên YouTube, bạn quan tâm đến video hơn là bình luận. Trong trường hợp này, video quan trọng hơn bình luận.
  • Nếu mở một bài viết trên trang web tin tức, bạn sẽ quan tâm đến văn bản của bài viết hơn là quảng cáo. Ở đây, văn bản quan trọng hơn quảng cáo.

Trong những trường hợp như vậy, hãy cải thiện hiệu suất tải ban đầu bằng cách chỉ tải nội dung quan trọng nhất xuống trước rồi tải từng phần các phần còn lại sau. Hãy sử dụng hàm import()code-splitting cho việc này:

// videoPlayer.js
export function renderVideoPlayer() {  }

// comments.js
export function renderComments() {  }

// index.js
import {renderVideoPlayer} from './videoPlayer';
renderVideoPlayer();

// …Custom event listener
onShowCommentsClick(() => {
  import('./comments').then((comments) => {
    comments.renderComments();
  });
});

import() chỉ định rằng bạn muốn tải một mô-đun cụ thể một cách linh động. Khi thấy import('./module.js'), webpack sẽ di chuyển mô-đun này vào một phân đoạn riêng:

$ webpack
Hash: 39b2a53cb4e73f0dc5b2
Version: webpack 3.8.1
Time: 4273ms
                            Asset     Size  Chunks             Chunk Names
      ./0.8ecaf182f5c85b7a8199.js  22.5 kB       0  [emitted]
   ./main.f7e53d8e13e9a2745d6d.js    60 kB       1  [emitted]  main
 ./vendor.4f14b6326a80f4752a98.js    46 kB       2  [emitted]  vendor
./runtime.79f17c27b335abc7aaf4.js  1.45 kB       3  [emitted]  runtime

và chỉ tải xuống khi quá trình thực thi đạt đến hàm import().

Điều này sẽ làm cho gói main nhỏ hơn, cải thiện thời gian tải ban đầu. Hơn nữa, điều này sẽ cải thiện quá trình lưu vào bộ nhớ đệm – nếu bạn thay đổi mã trong đoạn chính, thì đoạn nhận xét sẽ không bị ảnh hưởng.

Tài liệu đọc thêm

Chia mã thành các tuyến và trang

Nếu ứng dụng của bạn có nhiều tuyến hoặc trang, nhưng chỉ có một tệp JS chứa mã (một đoạn main duy nhất), thì có thể bạn đang phân phát thêm byte trên mỗi yêu cầu. Ví dụ: khi người dùng truy cập vào trang chủ trên trang web của bạn:

Trang chủ của WebFundamentals

không cần tải mã để hiển thị một bài viết trên một trang khác – nhưng sẽ tải mã đó. Hơn nữa, nếu người dùng luôn chỉ truy cập vào trang chủ và bạn thay đổi mã bài viết, thì webpack sẽ vô hiệu hoá toàn bộ gói – và người dùng sẽ phải tải lại toàn bộ ứng dụng xuống.

Nếu chúng ta chia ứng dụng thành các trang (hoặc tuyến, nếu đó là ứng dụng một trang), người dùng sẽ chỉ tải mã có liên quan xuống. Ngoài ra, trình duyệt sẽ lưu mã ứng dụng vào bộ nhớ đệm tốt hơn: nếu bạn thay đổi mã trang chủ, webpack sẽ chỉ vô hiệu hoá phần tương ứng.

Đối với ứng dụng trang đơn

Để phân tách ứng dụng một trang theo tuyến đường, hãy sử dụng import() (xem phần "Mã tải lười mà bạn không cần ngay bây giờ"). Nếu bạn sử dụng một khung, thì khung đó có thể có giải pháp hiện có cho vấn đề này:

Đối với ứng dụng nhiều trang truyền thống

Để chia các ứng dụng truyền thống theo trang, hãy sử dụng điểm truy cập của webpack. Nếu ứng dụng của bạn có 3 loại trang: trang chủ, trang bài viết và trang tài khoản người dùng, thì ứng dụng đó nên có 3 mục nhập:

// webpack.config.js
module.exports = {
  entry: {
    home: './src/Home/index.js',
    article: './src/Article/index.js',
    profile: './src/Profile/index.js'
  }
};

Đối với mỗi tệp mục nhập, webpack sẽ tạo một cây phần phụ thuộc riêng và tạo một gói chỉ bao gồm các mô-đun mà mục nhập đó sử dụng:

$ webpack
Hash: 318d7b8490a7382bf23b
Version: webpack 3.8.1
Time: 4273ms
                            Asset     Size  Chunks             Chunk Names
      ./0.8ecaf182f5c85b7a8199.js  22.5 kB       0  [emitted]
   ./home.91b9ed27366fe7e33d6a.js    18 kB       1  [emitted]  home
./article.87a128755b16ac3294fd.js    32 kB       2  [emitted]  article
./profile.de945dc02685f6166781.js    24 kB       3  [emitted]  profile
 ./vendor.4f14b6326a80f4752a98.js    46 kB       4  [emitted]  vendor
./runtime.318d7b8490a7382bf23b.js  1.45 kB       5  [emitted]  runtime

Vì vậy, nếu chỉ có trang bài viết sử dụng Lodash, thì gói homeprofile sẽ không bao gồm thư viện này – và người dùng sẽ không phải tải thư viện này xuống khi truy cập trang chủ.

Tuy nhiên, các cây phụ thuộc riêng biệt vẫn có một số hạn chế. Nếu hai điểm truy cập sử dụng Lodash và bạn chưa di chuyển các phần phụ thuộc vào gói nhà cung cấp, thì cả hai điểm truy cập sẽ bao gồm một bản sao của Lodash. Để giải quyết vấn đề này, trong webpack 4, hãy thêm tuỳ chọn optimization.splitChunks.chunks: 'all' vào cấu hình webpack:

// webpack.config.js (for webpack 4)
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  }
};

Tuỳ chọn này cho phép phân tách mã thông minh. Với tuỳ chọn này, webpack sẽ tự động tìm kiếm mã chung và trích xuất mã đó vào các tệp riêng biệt.

Hoặc trong webpack 3, hãy sử dụng CommonsChunkPlugin – thao tác này sẽ di chuyển các phần phụ thuộc phổ biến vào một tệp mới được chỉ định:

module.exports = {
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'common',
      minChunks: 2    // 2 is the default value
    })
  ]
};

Bạn có thể tuỳ ý điều chỉnh giá trị minChunks để tìm giá trị phù hợp nhất. Nhìn chung, bạn nên giữ cho kích thước này nhỏ, nhưng tăng nếu số lượng phân đoạn tăng lên. Ví dụ: đối với 3 mảnh, minChunks có thể là 2, nhưng đối với 30 mảnh, minChunks có thể là 8 – vì nếu bạn giữ nguyên ở mức 2, quá nhiều mô-đun sẽ đi vào tệp chung, làm tăng kích thước tệp đó quá nhiều.

Tài liệu đọc thêm

Làm cho mã mô-đun ổn định hơn

Khi tạo mã, webpack sẽ gán cho mỗi mô-đun một mã nhận dạng. Sau đó, các mã nhận dạng này được dùng trong require() bên trong gói. Bạn thường thấy mã nhận dạng trong đầu ra của bản dựng ngay trước đường dẫn mô-đun:

$ webpack
Hash: df3474e4f76528e3bbc9
Version: webpack 3.8.1
Time: 2150ms
                           Asset      Size  Chunks             Chunk Names
      ./0.8ecaf182f5c85b7a8199.js  22.5 kB       0  [emitted]
   ./main.4e50a16675574df6a9e9.js    60 kB       1  [emitted]  main
 ./vendor.26886caf15818fa82dfa.js    46 kB       2  [emitted]  vendor
./runtime.79f17c27b335abc7aaf4.js  1.45 kB       3  [emitted]  runtime

↓ Tại đây

[0] ./index.js 29 kB {1} [built]
[2] (webpack)/buildin/global.js 488 bytes {2} [built]
[3] (webpack)/buildin/module.js 495 bytes {2} [built]
[4] ./comments.js 58 kB {0} [built]
[5] ./ads.js 74 kB {1} [built]
+ 1 hidden module

Theo mặc định, mã nhận dạng được tính bằng bộ đếm (tức là mô-đun đầu tiên có mã nhận dạng 0, mô-đun thứ hai có mã nhận dạng 1, v.v.). Vấn đề nằm ở chỗ khi bạn thêm một mô-đun mới, mô-đun đó có thể xuất hiện ở giữa danh sách mô-đun, thay đổi tất cả mã nhận dạng của mô-đun tiếp theo:

$ webpack
Hash: df3474e4f76528e3bbc9
Version: webpack 3.8.1
Time: 2150ms
                           Asset      Size  Chunks             Chunk Names
      ./0.5c82c0f337fcb22672b5.js    22 kB       0  [emitted]
   ./main.0c8b617dfc40c2827ae3.js    82 kB       1  [emitted]  main
 ./vendor.26886caf15818fa82dfa.js    46 kB       2  [emitted]  vendor
./runtime.79f17c27b335abc7aaf4.js  1.45 kB       3  [emitted]  runtime
   [0] ./index.js 29 kB {1} [built]
   [2] (webpack)/buildin/global.js 488 bytes {2} [built]
   [3] (webpack)/buildin/module.js 495 bytes {2} [built]

↓ Chúng tôi đã thêm một mô-đun mới…

[4] ./webPlayer.js 24 kB {1} [built]

↓ Và hãy xem kết quả! comments.js hiện có mã nhận dạng 5 thay vì 4

[5] ./comments.js 58 kB {0} [built]

ads.js hiện có mã nhận dạng 6 thay vì 5

[6] ./ads.js 74 kB {1} [built]
       + 1 hidden module

Thao tác này sẽ vô hiệu hoá tất cả các phần bao gồm hoặc phụ thuộc vào các mô-đun có mã nhận dạng đã thay đổi – ngay cả khi mã thực của các phần đó không thay đổi. Trong trường hợp của chúng ta, khối 0 (khối có comments.js) và khối main (khối có mã ứng dụng khác) sẽ bị vô hiệu – trong khi chỉ khối main mới bị vô hiệu.

Để giải quyết vấn đề này, hãy thay đổi cách tính mã mô-đun bằng cách sử dụng HashedModuleIdsPlugin. Phương thức này thay thế các mã nhận dạng dựa trên bộ đếm bằng hàm băm của các đường dẫn mô-đun:

$ webpack
Hash: df3474e4f76528e3bbc9
Version: webpack 3.8.1
Time: 2150ms
                           Asset      Size  Chunks             Chunk Names
      ./0.6168aaac8461862eab7a.js  22.5 kB       0  [emitted]
   ./main.a2e49a279552980e3b91.js    60 kB       1  [emitted]  main
 ./vendor.ff9f7ea865884e6a84c8.js    46 kB       2  [emitted]  vendor
./runtime.25f5d0204e4f77fa57a1.js  1.45 kB       3  [emitted]  runtime

↓ Tại đây

[3IRH] ./index.js 29 kB {1} [built]
[DuR2] (webpack)/buildin/global.js 488 bytes {2} [built]
[JkW7] (webpack)/buildin/module.js 495 bytes {2} [built]
[LbCc] ./webPlayer.js 24 kB {1} [built]
[lebJ] ./comments.js 58 kB {0} [built]
[02Tr] ./ads.js 74 kB {1} [built]
    + 1 hidden module

Với phương pháp này, mã nhận dạng của một mô-đun chỉ thay đổi nếu bạn đổi tên hoặc di chuyển mô-đun đó. Các mô-đun mới sẽ không ảnh hưởng đến mã của các mô-đun khác.

Để bật trình bổ trợ này, hãy thêm trình bổ trợ này vào phần plugins của cấu hình:

// webpack.config.js
module.exports = {
  plugins: [
    new webpack.HashedModuleIdsPlugin()
  ]
};

Tài liệu đọc thêm

Tóm tắt

  • Lưu gói vào bộ nhớ đệm và phân biệt giữa các phiên bản bằng cách thay đổi tên gói
  • Phân chia gói thành mã ứng dụng, mã nhà cung cấp và thời gian chạy
  • Nội tuyến thời gian chạy để lưu yêu cầu HTTP
  • Tải mã không quan trọng theo từng phần bằng import
  • Phân tách mã theo tuyến/trang để tránh tải nội dung không cần thiết