Angular 13 .mjs构建包使用require()及切回.js扩展方案咨询
ng-packagr 13 构建兼容方案
切回.js扩展构建产物的实现方式
ng-packagr 13 遵循 Angular 13 新版APF包规范,默认输出ESM格式的.mjs产物,官方没有提供直接修改输出扩展名的配置项,可通过构建后置流程适配,无需全量替换现有require()写法:
- 编写轻量Node.js脚本作为构建后置钩子:在
ng build执行完成后,遍历构建输出目录,将所有.mjs后缀文件重命名为.js,同步批量替换所有文件内容中引用路径里的.mjs后缀为.js;同时将配套的.mjs.mapsourcemap文件重命名为.js.map,修改map文件内file字段对应的后缀值,避免调试时sourcemap失效。 - 调整包配置:如果项目根目录
package.json中设置了"type": "module",需在构建输出目录下新增单独的package.json文件,写入{"type": "commonjs"},让Node环境识别输出的.js文件为CommonJS格式,保证require()可正常加载;同步修改package.json中的main、module、exports字段,将原指向.mjs的入口路径替换为重命名后的.js路径。
注意:不要通过降级ng-packagr版本的方式回退产物格式,会和Angular 13的Ivy编译器版本不兼容,抛出编译错误。
可选依赖动态导入的构建兼容方案
直接将require()替换为静态import或固定路径的动态import()时,构建工具会做静态依赖分析,找不到对应文件就会在编译阶段抛错,无法适配可选依赖按需加载的场景,可通过两种方式解决:
- 保留原有
require()写法:在项目tsconfig.json中开启"esModuleInterop": true、"allowSyntheticDefaultImports": true配置,在使用require()的文件顶部添加declare const require: (path: string) => any;类型声明绕开TS校验。ng-packagr 13 不会对这种显式声明的CommonJS require做强制ESM转换,配合前面的.js产物适配,运行时会保留原有的按需加载逻辑,不会在构建阶段校验可选依赖是否存在。 - 使用ESM原生动态导入写法:不要传入固定字符串作为
import()的参数,将包名存为变量传入,同时添加构建忽略注释,示例代码如下:
let optionalService = null; const pkgName = 'your-optional-package'; try { // 该注释会告知底层rollup构建工具跳过静态分析 optionalService = await import(/* @rollup-ignore */ pkgName); } catch (err) { // 可选包未安装时走降级逻辑 }
这种写法完全符合ESM规范,构建阶段不会校验对应包是否存在,行为和CommonJS的require()一致。
内容的提问来源于stack exchange,提问作者vp310
相关产品推荐
相关产品推荐

