jvinhit//lab

Search posts

Type to search across journal entries.

navigate open esc close

Webpack · Part 9 — Bundle Analysis & Performance

Measure what is actually in your bundle: webpack-bundle-analyzer treemaps, finding bloat and duplicates, performance budgets that fail the build, and prefetch/preload hints. With an interactive bundle analyzer.

Bạn không thể tối ưu cái không thấy. Đa số bundle phình to vì những lý do nhàm chán, sửa được: một thư viện ngày tháng ship mọi locale, một import lodash đầy đủ, hai phiên bản của cùng phụ thuộc. Phần này là về tìm và sửa chúng.

Bấm các khối trong treemap bên dưới để sửa các thủ phạm phổ biến và xem bundle giảm dưới ngân sách:


1. Đo trước

Thêm webpack-bundle-analyzer và chạy nó trên bản build production:

npm install --save-dev webpack-bundle-analyzer
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");

module.exports = {
  plugins: [new BundleAnalyzerPlugin({ analyzerMode: "static" })],
};

Nó mở một treemap tương tác nơi kích thước khối = kích thước file. Khối to là nơi byte của bạn đi. Bạn cũng có thể tạo stats --json và xem bằng công cụ online.


2. Các thủ phạm thường gặp

Triệu chứngSửa
moment ~230 KBđổi sang dayjs, hoặc IgnorePlugin để bỏ locale
full lodashimport { debounce } from "lodash-es" + import có tên + tree shaking
duplicate deps (two axios versions)resolve.alias về một bản, hoặc npm dedupe
huge polyfillsnhắm trình duyệt hiện đại; cắt targets
source maps in bundledùng source-map không inline-source-map

Trong demo analyzer, bấm moment, lodash, và khối axios trùng để áp các fix này và xem tổng giảm.


3. Bỏ locale của moment

Nếu phải giữ moment, bỏ locale không dùng:

const webpack = require("webpack");

plugins: [
  new webpack.IgnorePlugin({
    resourceRegExp: /^\.\/locale$/,
    contextRegExp: /moment$/,
  }),
],

Một plugin đó có thể cắt ~200 KB. Nhưng dayjs hoặc date-fns là lựa chọn dài hạn tốt hơn.


4. Ngân sách hiệu năng

Cho Webpack lỗi hoặc cảnh báo khi một bundle vượt ngưỡng kích thước, để bắt phình to trong CI:

module.exports = {
  performance: {
    maxEntrypointSize: 250000, // bytes
    maxAssetSize: 250000,
    hints: "warning", // or "error" to fail the build
  },
};

Một ngân sách biến “bundle dần phình to trong sáu tháng” thành “PR vượt giới hạn bị fail review”. Thanh ngân sách của demo hiện đường 250 KB.


5. Prefetch & preload

Khi đã tách (Phần 6), dùng resource hint để điều hướng tức thì mà không phình tải ban đầu:

import(/* webpackPrefetch: true */ "./routes/Settings"); // fetch when idle
import(/* webpackPreload: true */ "./CriticalChart");      // fetch with parent
  • = “user có lẽ sẽ cần sớm” — ưu tiên thấp, lúc rảnh.
  • = “trang này cần ngay bây giờ” — ưu tiên cao, song song.

Dùng prefetch thoải mái cho route có khả năng tiếp theo, preload tiết kiệm cho chunk quan trọng của trang hiện tại.


6. Các thắng lợi tốc độ khác

  • cache công việc build giữa các lần chạy, build lại nhanh hơn nhiều.
  • transpile nhanh hơn Babel.
  • loại một phụ thuộc tải-từ-CDN khỏi bundle hoàn toàn.
  • Thu hẹp include/exclude để loader chạy trên ít file nhất.
module.exports = {
  cache: { type: "filesystem" }, // huge rebuild speedup
};

7. Bài tập

1. Analyzer hiện khối 230 KB cho moment, chủ yếu là file locale bạn không dùng. Hai cách thu nhỏ?

Lời giải

IgnorePlugin để bỏ locale, hoặc thay moment bằng dayjs/date-fns.

2. Bạn muốn CI fail khi ai đó push PR làm bundle chính vượt 250 KB. Cấu hình gì?

Lời giải

performance: { maxEntrypointSize: 250000, hints: "error" }.

3. Analyzer hiện hai bản axios phiên bản khác nhau. Khử trùng lặp thế nào?

Lời giải

Đồng bộ phiên bản (npm dedupe) hoặc ép một bản với resolve.alias.

Nâng cao:trong demo analyzer, sửa moment, lodash, và axios trùng, và xác nhận bundle chuyển từ vượt-ngân-sách (đỏ) sang trong-ngân-sách (xanh).


Điểm chính

  • Đo bằng webpack-bundle-analyzer trước khi tối ưu.
  • Phình phổ biến: locale moment, lodash đầy đủ, phụ thuộc trùng, polyfill to.
  • Đặt ngân sách hiệu năng để bắt thoái lui trong CI.
  • Dùng gợi ý prefetch/preload để tải thông minh.
  • cache: { type: "filesystem" } tăng tốc build lại đáng kể.

Tiếp theo

Phần 10 — Resolve nâng cao + tự viết loader & plugin: nội bộ resolve và externals, rồi viết một loader tùy chỉnh và một plugin tùy chỉnh để hiểu Webpack từ bên trong.