在进行angular-cli项目迁移的时候,特别是项目比较复杂的时候,很容易掉坑。下面我就自己的实践经验总结一下自己在进行CLI迁移的时候掉过的一些坑
1.Module build Failed: Error: Angular Compiler was detected but it was an instance of the wrong class. This likely means you have several @ngtools/webpack packages installed. You can check this with npm ls @ngtools/webpack
,and then remove the extra copies.
大意就是,你原来的项目使用了webpack的版本和现在Angular CLI内部使用的webpack的版本冲突了,需要改成同样的版本。
2.JavaScript Heap Out of Memory
在package.json中的scripts下增加一行命令
“clibuild”: "node --max-old-space-size=4096 ./node_modules/@angular/cli/bin/ng build"
npm run clibuild
3.各种版本冲突
我们发现package.json的dependencies中,有的版本号前面加了~,有的加了^,有的没有加,那么它们有什么区别呢?
波浪符号(~):它会更新到当前minor version(也就是中间的那位数字)中最新的版本。比如body-parser:~1.15.2,这个库会去匹配更新到1.15.x的最新版本,如果出了一个新的版本为1.16.0,则不会自动升级。
插入符号(^):它将会把当前库的版本更新到当前major version(也就是第一位数字)中最新的版本。比如bluebird:^3.3.4,这个库会去匹配3.x.x中最新的版本,但是他不会自动更新到4.0.0。
所以如果对于出现了~和^的版本,可能在npm install的时候版本进行了自动升级而导致某些版本冲突,所以如果你需要精确的某个版本,那么可以去掉~和^符号。
另外,当你更改了package.json中的某些包的版本时,可能你会把node_modules全部删掉再重新npm install,其实有个简单的方法:执行“npm install --force”即可完成更新。
4.多环境编译
environments文件中放置多种配置文件,如environment.prod.ts:
export const environment = { production: true };
if (environment.production) { enableProdMode(); }
ng build或者ng serve时加参数说明使用何种环境配置:
ng build: $ ng build --environment=production 或 $ ng b -prod
ng serve: $ ng serve --environment=production 或 $ ng s -prod
5.Angular和CLI的版本如果不一致可能会出现一些很奇怪而无法解释的问题,一般来说,CLI1.6.3是和Angular5兼容的比较好的,但是如果之前的项目是Angular4写的话,需要升级到Angular5,然而升级的过程也是一个不断解决兼容性问题的过程,“Angular Update Guide”这篇文章给出了一些升级中的注意的问题。
其中我就遇到过OpaqueToken需要用InjectionTokens代替,还有ngOutletContext需要用ngTemplateOutletContext代替的问题,其中ngOutletContext过时的这个问题很隐晦,是由于某些第三方的引用库并没有兼容Angular5的“ngTemplateOutletContext”这个特性导致的,所以你需要洞察出哪些第三方库可能需要升级到兼容Angular5的版本了。
升级过程中还有个问题只得一提,就是在Angular5对于Angular Material的兼容性问题。原来MaterialModule已经在Angular5中废弃不用了,所以我们需要自己写一个ngModule来import所用到的material lib,相当于把用到的material lib都集中在一个material module下,然后在项目中用到angular material的modules引入这个material module即可。
6.我还遇到一个比较诡异的错误,运行ng命令的时候报如下错误:
module.js:471 throw err; ^ Error: Cannot find module 'rxjs/operators/map'
一开始我一直以为是npm或者cli有问题,其实是rxjs的版本不对,升级到5.5.2以上就能解决这个问题了。
7.Unit Test迁移到Angular CLI上也会出现各种各样的问题,我们首先来梳理一下Angular CLI是如何启动Unit Test的。入口自然还是.angular.cli.json的"test":"test.js","test.js"一般都是标准写法,它会去启动karma,其中karma的配置文件也是在.angular.cli.json中指定的。“test”: { "karma": { "config": "...."}}。最主要的就是karma的配置文件了,有以下几点需要注意的地方:(1)basePath,强烈建议不要空着,虽然后续的文件地址有方法去覆盖它,但是如果你用到了karma-fixture,如果你的basePath是空的,那么karma-fixture的文件映射会以绝对路径作为key,那么在spec文件中loadFixture的时候就会因为找不到对应的key而报错。(2)frameworks: 最好加上@angular/cli(3)plugins:除了用到的插件如karma-fixture,karma-json-fixtures-preprocessor等要引入进来以外,最好引入@angular/cli/plugins/karma.(4)files:需要引入的一些文件,如第三方的js库文件,HTML文件,JSON文件等等,但是HTML和JSON需要转化为JS文件,Karma才可以处理,所以需要preprocessors去指定用什么插件去把HTML和JSON转化成JS。(5)preporcessors: 指定插件对HTML和JSON等非JS文件进行预处理,转化成JS文件,以便Karma框架去调用。