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

Cách gói web giúp lưu tài sản vào bộ nhớ đệm

Việc 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. Hãy sử dụng API này để giữ lại các phần của ứng dụng trên máy khách và tránh tải lại các phần đó xuống mỗi lần.

Sử dụng tạo phiên bản gói và tiêu đề bộ nhớ đệm

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

  1. yêu cầu trình duyệt lưu một 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õ các chức năng của Cache-Control, hãy xem các phương pháp hay nhất về lưu vào bộ nhớ đệm của Jake Archibald.

  2. và đổi tên tệp khi tệp được thay đổi để buộc tải xuống 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 được 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 gói web, bạn cũng làm như vậy, nhưng bạn chỉ định hàm băm tệp thay vì số phiên bản. Để đư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 cho ứng dụng khách, 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 tạo một tệp HTML chứa 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ì logic đó là đủ cho bạn:

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

WebpackManifestPlugin là một phương pháp linh hoạt hơn. Phương pháp này sẽ 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ó ánh xạ giữa các 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 ra tệp sẽ hoạt động:

// 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 có xu hướng ít thay đổi hơn mã ứng dụng thực tế. Nếu bạn di chuyển các báo cáo này vào một tệp riêng, trình duyệt có thể lưu chúng vào bộ nhớ đệm riêng biệt – và sẽ không tải lại những báo cáo này xuống 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 riêng biệt, hãy thực hiện 3 bước sau:

  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 gói web tạo ứng dụng, gói web đó sẽ thay thế [name] bằng tên của một phân đoạ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 – 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 bằng [name] ở bước 1.

    Hiện tại, nếu bạn xây dựng ứ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 tình trạng này sẽ thay đổi sau 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 của bạn:

    // 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 phương thức này, webpack sẽ trích xuất mã nhà cung cấp nếu kích thước lớn hơn 30 kB (trước khi giảm kích thước và gzip). Thao tác này cũng trích xuất mã phổ biến – điều này sẽ hữu ích nếu bản dựng của bạn tạo ra nhiều gói (ví dụ: nếu bạn chia ứng dụng thành các tuyến).

    Trong gói web 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ả mô-đun có đường dẫn node_modules rồi di 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 hai tệp thay vì một: main.[chunkhash].jsvendor.[chunkhash].js (vendors~main.[chunkhash].js cho gói web 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ỏ – điều này không có vấn đề gì:

$ 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 biệt – và chỉ tải xuống lại mã có thay đổi.

Mã thời gian chạy gói web

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ì ngoài mã của các mô-đun, gói webpack 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 dữ liệu liên kết giữa mã phân đ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 đoạn được tạo cuối cùng, trong trường hợp của chúng ta là vendor. Và mỗi khi có bất kỳ phân đoạn nào thay đổi, đoạn mã này cũng thay đổi, khiến toàn bộ phân đoạn vendor cũng thay đổi.

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

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

Trong gói web 3, hãy thực hiện việc này bằng cách tạo thêm một đoạ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

Bạn có thể thêm chúng vào index.html theo thứ tự ngược lại – thế là xong:

<!-- 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

Thời gian chạy gói web cùng dòng để lưu một yêu cầu HTTP bổ sung

Để cải thiện mọi thứ, hãy thử đưa thời gian chạy gói web vào cùng dòng vào phản hồi HTML. Tức là, thay vì thế này:

<!-- 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à cùng dòng sẽ giúp bạn lưu yêu cầu HTTP (khá quan trọng với HTTP/1; ít quan trọng với HTTP/2 nhưng vẫn có thể phát sinh hiệu ứng).

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

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

Nếu bạn sử dụng HtmlWebpackPlugin để tạo tệp HTML, InlineSourcePlugin là tất cả những gì bạn cần:

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 gói web 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()
      ]
    };
    

    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. Đặt nội tuyến nội dung của đoạn thời gian chạy 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 gói web 3:

  1. Đặt tên thời gian chạy ở dạng 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 tuyến runtime.js 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 từng phần mã mà bạn hiện không cần

Đôi khi, một trang có nhiều và ít phần quan trọng hơn:

  • Nếu tải một trang video trên YouTube, bạn sẽ quan tâm đến video hơn là bình luận. Ở đây, video quan trọng hơn bình luận.
  • Nếu mở một bài viết trên một 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 và tải từng phần các phần còn lại sau. Hãy sử dụng hàm import()phân tách mã để thực hiện 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 động một mô-đun cụ thể. Khi gói web nhìn thấy import('./module.js'), gói web sẽ di chuyển mô-đun này thành một phân đoạn riêng biệt:

$ 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 tệp này 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, việc này còn cải thiện khả năng lưu vào bộ nhớ đệm – nếu bạn thay đổi mã trong đoạn chính, các đ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 duy nhất chứa mã (một phân đoạn main), thì có thể bạn đang phân phát thêm byte cho 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ủ Kiến thức cơ bản về web

họ không cần phải tải mã để hiển thị bài viết trên một trang khác – nhưng họ sẽ tải bài viết đó. Hơn nữa, nếu người dùng luôn chỉ truy cập vào trang chủ và bạn thực hiện thay đổi trong mã bài viết, thì gói web 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 các tuyến, nếu đó là ứng dụng một trang), thì người dùng sẽ chỉ tải mã 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ủ, gói web sẽ chỉ vô hiệu hoá phân đoạn tương ứng.

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

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

Đối với các ứ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 gói web. 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 đó phải có 3 mục:

// 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, gói web 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ì các 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 vào trang chủ.

Tuy nhiên, cây phụ thuộc riêng biệt có một số hạn chế. Nếu 2 đ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 của 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 của bạn:

// 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, gói web sẽ tự động tìm mã phổ biến và trích xuất mã đó vào các tệp riêng biệt.

Hoặc trong gói web 3, hãy sử dụng CommonsChunkPlugin – công 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ể thử dùng giá trị minChunks để tìm giá trị phù hợp nhất. Nhìn chung, bạn muốn duy trì kích thước nhỏ, nhưng sẽ tăng lên nếu số lượng phân đoạn tăng lên. Ví dụ: đối với 3 phân đoạn, minChunks có thể là 2, nhưng đối với 30 phân đoạn thì có thể là 8 – vì nếu bạn giữ ở mức 2, thì có quá nhiều mô-đun sẽ được đưa vào tệp chung, khiến nó tăng lên 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 gán một mã nhận dạng cho mỗi mô-đun. 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 là 0, mô-đun thứ hai có mã nhận dạng là 1, v.v.). Vấn đề này là 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 các 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 thành quả! comments.js hiện có mã 5 thay vì 4

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

ads.js hiện có mã 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 đoạ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 đoạn đó không thay đổi. Trong trường hợp của chúng ta, phân đoạn 0 (phân đoạn có comments.js) và phân đoạn main (phân đoạn có mã ứng dụng khác) sẽ không hợp lệ – trong khi chỉ có một phân đoạn main là không hợp lệ.

Để 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. Hàm này thay thế mã nhận dạng dựa trên bộ đếm bằng hàm băm của đườ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 ID của các mô-đun khác.

Để bật trình bổ trợ, 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ổng hợp

  • Lưu gói vào bộ nhớ đệm và phân biệt các phiên bản bằng cách thay đổi tên gói
  • Chia gói thành mã ứng dụng, mã nhà cung cấp và thời gian chạy
  • Cùng dòng thời gian chạy để lưu yêu cầu HTTP
  • Tải từng phần mã không quan trọng 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