如何优化包捆绑 (Package Bundling)

打包外部包可以显著提升应用性能。 默认情况下,应用中导入的包不会被自动打包。如果外部包未预先打包(例如从 monorepo 或 node_modules 导入),这可能会影响性能或导致无法运行。本指南将带您分析并配置包打包。

分析 JavaScript 包

@next/bundle-analyzer 是 Next.js 的一个插件,可帮助您管理应用包的大小。它会生成每个包及其依赖项大小的可视化报告。您可利用这些信息移除大型依赖项、拆分代码或进行懒加载 (lazy-load)

安装

运行以下命令安装插件:

npm i @next/bundle-analyzer
# 或
yarn add @next/bundle-analyzer
# 或
pnpm add @next/bundle-analyzer

然后,将打包分析器的配置添加到 next.config.js

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {}

const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
})

module.exports = withBundleAnalyzer(nextConfig)

生成报告

运行以下命令分析您的包:

ANALYZE=true npm run build
# 或
ANALYZE=true yarn build
# 或
ANALYZE=true pnpm build

报告将在浏览器中打开三个新标签页供您检查。定期评估应用的包有助于长期保持应用性能。

优化包导入

某些包(如图标库)可能导出数百个模块,这会在开发和生产环境中引发性能问题。

您可以通过在 next.config.js 中添加 optimizePackageImports 选项来优化这些包的导入方式。该选项仅加载您实际使用的模块,同时仍允许您使用包含多个命名导出的导入语句。

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    optimizePackageImports: ['icon-library'],
  },
}

module.exports = nextConfig

Next.js 还会自动优化部分库,因此它们无需包含在 optimizePackageImports 列表中。查看完整列表

打包特定包

要打包特定包,您可以在 next.config.js 中使用 transpilePackages 选项。此选项适用于打包未预先打包的外部包,例如来自 monorepo 或 node_modules 的包。

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  transpilePackages: ['package-name'],
}

module.exports = nextConfig

打包所有包

要自动打包所有包(应用路由 (App Router) 中的默认行为),您可以在 next.config.js 中使用 bundlePagesRouterDependencies 选项。

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  bundlePagesRouterDependencies: true,
}

module.exports = nextConfig

排除特定包不参与打包

如果启用了 bundlePagesRouterDependencies 选项,您可以通过在 next.config.js 中使用 serverExternalPackages 选项将特定包排除在自动打包之外:

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  // 在页面路由 (Pages Router) 中自动打包外部包:
  bundlePagesRouterDependencies: true,
  // 为应用路由和页面路由排除特定包不参与打包:
  serverExternalPackages: ['package-name'],
}

module.exports = nextConfig

On this page