Angular 9使用关联库时应用构建失败的问题解决咨询
刚升级到Angular 9后遇到这种本地开发的协同问题太常见了,我来一步步帮你搞定npm link的问题,再给你推荐更顺畅的替代方案:
一、先搞定npm link不生效的核心配置问题
从你贴的库package.json来看,缺少正确的入口文件配置,这是npm link没起作用的关键。Angular 9的库构建后需要明确告诉npm它的编译产物在哪里:
补充库根目录package.json的入口字段
执行npm run build-lib后,dist/my-lib里会自动生成一个package.json,把里面的main、module、typings字段复制到你库项目根目录的package.json里,比如:{ "name": "my-lib", "version": "1.2.0", // 新增这三个字段,路径对应你的dist产物 "main": "./dist/my-lib/bundles/my-lib.umd.js", "module": "./dist/my-lib/fesm2015/my-lib.js", "typings": "./dist/my-lib/my-lib.d.ts", // 你原有的其他配置... }别搞错了,是库项目根目录的package.json,不是dist里的那个!
必须用
--prod构建库
你的build-lib脚本已经是ng build --prod my-lib,这点很对——因为你配置了库不使用Ivy,prod构建会生成兼容非Ivy的产物,和应用用Ivy的配置匹配,千万别用普通的ng build,不然产物会有问题。
二、正确的npm link操作流程(别搞反顺序!)
按这个步骤来,保证不出错:
先处理库项目:
npm run build-lib # 先把库构建好 npm link # 把库链接到全局npm仓库再处理应用项目:
npm link my-lib # 把全局的my-lib链接到应用的node_modules里启动应用必须加
--preserve-symlinks参数
这是最容易忘的一步!Angular CLI默认会把符号链接解析成实际路径,导致没法检测到库的变化,所以启动应用时要这么写:ng serve --preserve-symlinks开启库的watch模式
在库项目里执行:ng build my-lib --watch --prod这样你改库代码的时候,它会自动重新构建,应用因为开了
preserve-symlinks,能立刻感知到变化并重新编译,完美替代原来的复制操作。
三、为啥原来复制dist会报__ivy_ngcc_bak错?
Angular 9的ngcc(Ivy兼容性编译器)会给非Ivy库的文件生成备份文件,你直接覆盖node_modules里的库文件,就会触发这个冲突。而npm link用的是符号链接,不会直接修改node_modules里的文件,从根源上避免了这个问题。
四、更省心的替代方案:把库和应用放同一个workspace
如果npm link还是觉得麻烦,直接把库和应用放到同一个Angular workspace里,协同开发会更顺畅:
- 把库项目移动到应用所在workspace的
projects目录下 - 确保workspace的angular.json里,库的
architect.build配置中enableIvy设为false(符合你的升级配置),outputPath指向dist/my-lib - 应用的package.json里,把
my-lib的依赖改成本地项目:{ "dependencies": { "my-lib": "file:../projects/my-lib" } } - 同时启动库的watch构建和应用:
这样改库代码,应用自动跟着更,完全不用手动操作,爽得很。ng build my-lib --watch --prod & ng serve
五、几个小提醒
- 库的
postinstall脚本里的ngcc,本地开发时可以临时注释掉,避免本地构建时触发不必要的ngcc操作,发布的时候再打开就行 - 如果npm link后还是没触发应用构建,去检查应用的angular.json里
build.options.preserveSymlinks是不是设为true了,或者启动时一定要加--preserve-symlinks参数
内容的提问来源于stack exchange,提问作者Tanmay Ray

