Next.js使用dynamic动态引入组件后依赖仍在初始bundle中是什么原因?
下面是导致该问题的常见原因及对应修复方案:
类型导入未使用
import type导致模块被提前引入
你当前在index.tsx中导入类型的语句是普通导入:import { PhoneNumberInputProps } from "./components/PhoneNumberInput";如果未配置TS自动擦除纯类型导入,该导入语句会被保留到转译后的JS代码中,导致整个
PhoneNumberInput.tsx文件被打包进初始bundle,自然其依赖的react-phone-number-input也会被包含在内。
修复方法:改为仅导入类型的语法:import type { PhoneNumberInputProps } from "./components/PhoneNumberInput";动态导入写法不匹配命名导出规则
next/dynamic默认会读取导入模块的default导出,而你的PhoneNumberInput是命名导出,当前用as any强制跳过类型校验的写法会导致打包工具无法正确做tree shaking,甚至提前引入整个模块。
修复方法:调整动态导入语句,显式返回对应命名导出作为default:const PhoneNumberInput = dynamic<PhoneNumberInputProps>( () => import("./components/PhoneNumberInput").then(mod => ({ default: mod.PhoneNumberInput })) );其他初始加载模块引用了该依赖
检查项目所有初始加载的文件(比如全局layout、首页、全局公共组件、全局入口文件等),确认有没有其他地方直接导入了react-phone-number-input或者PhoneNumberInput组件,只要有一处非动态的引用,该依赖就会被打进初始bundle。打包配置导致依赖被强制纳入初始包
检查next.config.js配置,确认有没有手动把react-phone-number-input加入到了vendor拆分规则、或者依赖预打包的强制包含列表中;另外如果用了第三方打包分析工具,也要确认是不是把公共chunk的内容误判为了初始bundle的内容,可以用Next官方的@next/bundle-analyzer做二次校验。组件文件存在其他被外部引用的导出项
如果PhoneNumberInput.tsx中除了组件和对应类型之外,还导出了常量、工具函数等内容,且其他初始加载的模块导入了这些内容,也会导致整个文件被引入,连带依赖被打进初始包。修复方法是把非组件相关的导出拆分到独立的文件中。
内容的提问来源于stack exchange,提问作者Baptiste Arnaud

