The purpose of this tutorial is to provide another way to do the migration from an AngularJS application to the latest version of Angular. At the time that this guideline was done, Angular is at the version 9.
本教程的目的是提供从AngularJS应用程序迁移到最新版本的Angular的另一种方法。 在完成本指南时,Angular的版本为9。
The PhoneCat Upgrade Tutorial will be used as starting point. The oficial Angular documentation about upgrading from AngularJS to Angular uses that project as starting point as well. Find the starting repo here.
PhoneCat升级教程将作为起点。 有关从AngularJS升级到Angular的官方Angular文档也以该项目为起点。 在此处找到起始仓库。
The approach that will be taken to migrate that application is different from the one that the official documentation propose. There are different strategies to migrate the application. From the experience of migrating real projects, the approach of taking as starting point a new Angular application builded through the Angular CLI seems to be a good one as it ensures a proper set up, where we will configure a hybrid application so both versions will be working together during the migration time, providing the possibility of new features development at the same time (if needed).
迁移该应用程序所采用的方法与官方文档中提出的方法不同。 迁移应用程序有不同的策略。 从迁移实际项目的经验来看,将通过Angular CLI构建的新Angular应用程序作为起点的方法似乎是一种不错的方法,因为它可以确保正确的设置,在此我们将配置混合应用程序,因此两个版本都可以在迁移期间一起工作,从而可以同时开发新功能(如果需要)。
Steps:
脚步:
- Get the AngularJS application 获取AngularJS应用程序
- Create a new Angular application using Angular CLI 使用Angular CLI创建新的Angular应用程序
- Copy AngularJS code 复制AngularJS代码
- Bootstrapping an hybrid application 引导混合应用程序
- Set AngularJS as a global variable 将AngularJS设置为全局变量
- Include AngularJS route 包括AngularJS路线
- Fix errors 修正错误
- Migrate the application’s features 迁移应用程序的功能
- Adjust Routes 调整路线
- Remove AngularJS 删除AngularJS
1.获取AngularJS应用程序 (1. Get the AngularJS application)
Clone the PhoneCat Upgrade Tutorial from the official repository. This code will be the original AngularJS application that will be migrated.
从官方存储 库克隆PhoneCat升级教程 。 此代码将是将要迁移的原始AngularJS应用程序。
2.使用Angular CLI创建一个新的Angular应用程序 (2. Create a new Angular application using Angular CLI)
Our starting point will be an empty application that will be generated using the Angular Command Line Interface.
我们的起点将是一个空应用程序,它将使用Angular命令行界面生成。
Install globally the CLI using the npm
package manager:
使用npm
软件包管理器全局安装CLI:
npm install -g @angular/cli
Current version of Angular CLI: 9.1.3
当前版本的Angular CLI:9.1.3
Create a new angular project:
创建一个新的角度项目:
ng new angularjs-to-angular
Build and server the application:
生成并管理应用程序:
cd angularjs-to-angularng serve
Check that the application is up and running (http://localhost:4200/).
检查应用程序是否已启动并正在运行( http:// localhost:4200 / )。
Clean the existing app.component.html
to remove the example code:
清理现有的app.component.html
以删除示例代码:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/7d96c2782f7d194e98a30fd457feef44.png)
Check the project’s code at this point.
此时检查项目的代码 。
3.复制AngularJS代码 (3. Copy AngularJS code)
The way that the application will be migrated is going to support the hybrid application, that means that both AngularJS and Angular running at the same time. In order to achieve that we will be moving some code from the original AngularJS application into the Angular application that we have created on the previous step.
应用程序的迁移方式将支持混合应用程序,这意味着AngularJS和Angular同时运行。 为了实现这一点,我们将一些代码从原始AngularJS应用程序移至在上一步中创建的Angular应用程序。
3.1更新Package.json (3.1 Update Package.json)
Copy the dependencies from AngularJS package.json file into the package.json file of the Angular application.
将AngularJS package.json文件中的依赖项复制到Angular应用程序的package.json文件中。
![package.json](https://miro.medium.com/max/9999/1*vtCvTPi1KOLru7MXORfqhg.png)
After that change, we need to update project, so the new dependencies will be installed:
更改之后,我们需要更新项目,因此将安装新的依赖项:
npm i
3.2更新第三方库: (3.2 Update third party libraries:)
In an AngularJS application, the third party libraries are defined in the index.html
file. Whereas Angular declares all the third parties libraries in the file angular.json
under the scripts
section:
在AngularJS应用程序中,第三方库在index.html
文件中定义。 而Angular在scripts
部分下的angular.json
文件中声明了所有第三方库:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/5e2df582d5d86b8acdeee38421dc7bd1.png)
In order to apply this changes, we need to stop and run the serve again.
为了应用此更改,我们需要停止并再次运行服务。
3.3更新样式: (3.3 Update styles:)
The scaffold of the Angular application already creates a style.scss
file. Here we can import any external style library:
Angular应用程序的支架已经创建了style.scss
文件。 在这里,我们可以导入任何外部样式库:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/ab69b826c3c21f1d51be4513aae35379.png)
In order to get the same style of the original project, copy the existing code of app.css
into app.component.scss
为了获得与原始项目相同的样式,请将app.css
的现有代码复制到app.component.scss
3.4更新AppModule (3.4 Updating the AppModule)
Copy the app.module.js
from the original AngularJS application into the new Angular application under src/app
and rename it to app.module.ajs.js
. Renaming it will remind us that this file is needed for the AngularJS (that’s why .ajs.
is added)
将app.module.js
从原始AngularJS应用程序复制到src/app
下的新Angular应用src/app
,并将其重命名为app.module.ajs.js
。 重命名它会提醒我们AngularJS需要此文件(这就是添加.ajs.
的原因)
Modify the file top import the external/internal dependencies:
修改文件顶部,导入外部/内部依赖项:
![Image for post](https://miro.medium.com/max/9999/1*TgsX2QYW28r-Y8okwPhsng.png)
Import the app.module.ajs.js
into the main.ts
file:
将app.module.ajs.js
导入main.ts
文件:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/c3e5b8d692fef1f85dcd8aaf0d386c1e.png)
3.5更新index.html (3.5 Update index.html)
Copy the body content of the file index.html
of the AngularJS application in the same file of the new Angular application:
将AngularJS应用程序的index.html
文件的主体内容复制到新Angular应用程序的同一文件中:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/f936889019073983b57b564bb2413bc4.png)
3.6添加原始代码 (3.6 Add original code)
Copy the folder app/core
, app/phone-details
, app/phone-list
into src/app
.
将文件夹app/core
, app/phone-details
, app/phone-list
复制到src/app
。
Check the project’s code at this point.
此时检查项目的代码 。
4.引导混合应用程序 (4. Bootstrapping an hybrid application)
In order to be using both versions of Angular, we need to bootstrap the AngularJS into the new Angular.
为了同时使用两个版本的Angular,我们需要将AngularJS引导到新的Angular中。
Install @angular/upgrade
:
安装@angular/upgrade
:
npm install @angular/upgrade --save
Import UpgradeModule
, remove AppComponent from the bootstrap array and override the ngDoBootstrap
method:
导入UpgradeModule
,从引导数组中删除AppComponent并重写ngDoBootstrap
方法:
![Image for post](https://miro.medium.com/max/9999/1*_0cfy-BiBYmZRPVgEWcWQg.png)
Where phonecatApp is the same name set in theng-app
on the index.html
file in the AngularJS application. For more information check the official documentation.
其中phonecatApp是AngularJS应用程序中index.html
文件上ng-app
设置的相同名称。 有关更多信息,请查阅官方文档 。
Check the project’s code at this point.
此时检查项目的代码 。
5.将AngularJS设置为全局变量 (5. Set AngularJS as a global variable)
The @angular/upgrade/static
library exposes a setAngularJSGlobal
function. We can use this to load AngularJS into the Angular library.
@angular/upgrade/static
库公开了setAngularJSGlobal
函数。 我们可以使用它来将AngularJS加载到Angular库中。
![Image for post](https://miro.medium.com/max/9999/1*yWBqVbPX3x1o5c8lGg0f-A.png)
Check the project’s code at this point.
此时检查项目的代码 。
6.包含AngularJS路由器 (6. Include AngularJS router)
Copy the app.config.js
from the original AngularJS application into the new Angular application under src/app
and rename it to app.config.ajs.js
. Renaming it will remind us that this file is needed for the AngularJS (that’s why .ajs.
is added)
将app.config.js
从原始AngularJS应用程序复制到src/app
下的新Angular应用src/app
,并将其重命名为app.config.ajs.js
。 重命名它会提醒我们AngularJS需要此文件(这就是添加.ajs.
的原因)
Having this configuration file will allow to run the hybrid application without the need to rewrite everything at the beginning. As far as we progress on the migration, this file will be partially modified and deleted at the end of the process.
具有此配置文件将允许运行混合应用程序,而无需一开始就重写所有内容。 就我们在迁移方面的进展而言,该文件将在流程结束时进行部分修改和删除。
Modify the existing code to export a function:
修改现有代码以导出功能:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/9d7b12187667e992c6346e44fc13c93f.png)
Import the app.config.ajs.js
into the main.ts
file:
将app.config.ajs.js
导入main.ts
文件:
![Image for post](https://miro.medium.com/max/9999/1*ptRqoZ1VYhpWN2dPRWWBpA.png)
Check the project’s code at this point.
此时检查项目的代码 。
7.修正错误 (7. Fix errors)
Open the browser console to check and fix the errors:
打开浏览器控制台以检查并修复错误:
Error: [$injector:nomod] Module ‘ngResource’ is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument. → Include
import ‘angular-resource';
in thephone.module.js
file错误:[$ injector:nomod]模块'ngResource'不可用! 您可能拼错了模块名称,或者忘记了加载它。 如果注册模块,请确保将依赖项指定为第二个参数。 →包括
import 'angular-resource';
在phone.module.js
文件中angular.js:15635 Error: [$templateRequest:tpload] Failed to load template: phone-list/phone-list.template.html (HTTP status: 404 Not Found) → add
src/app
underassets
section onangular.json
thesrc/app
. Also modify thetemplateUrl
of thephone-list.component.html
to point to./app/phone-list/phone-list.template.html
. Stop and run again the server to apply the changes.angular.js:15635错误:[$ templateRequest:tpload]无法加载模板:phone-list / phone-list.template.html(HTTP状态:404未找到)→将
src/app
添加到angular.json
的assets
部分下src/app
。 还修改templateUrl
中的phone-list.component.html
以点./app/phone-list/phone-list.template.html
。 停止并再次运行服务器以应用更改。http://localhost:4200/phones/phones.json 404 (Not Found). Copy the folder
app/img
andapp/phones
undersrc/assets
. Modify the json files to point to the proper route in order to get the images (replace any"img/phones…
for"assets/img/phones...
). Modify the reference insidephone.service.js
http:// localhost:4200 / phones / phones.json 404(未找到)。 复制文件夹
src/assets
下的app/img
和app/phones
。 修改json文件以指向正确的路由以获取图像(将所有"img/phones…
替换为"assets/img/phones...
)。 修改phone.service.js
的参考
The application should be render properly.
该应用程序应正确呈现。
Check the project’s code at this point.
此时检查项目的代码 。
8.迁移应用程序的功能 (8. Migrate the application’s features)
8.1准备使用打字稿 (8.1 Prepare to use Typescript)
Before moving forward to upgrade services and components, we need to start using Typescript. TypeScript is a typed language that compiles to JavaScript. It provides advanced autocompletion, navigation, and refactoring.
在继续升级服务和组件之前,我们需要开始使用Typescript。 TypeScript是一种可编译为JavaScript的类型化语言。 它提供了高级自动完成,导航和重构。
To make use of Typescript, we need adjust the configuration:
要使用Typescript,我们需要调整配置:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/62a0d780f9655bac60b91e54d5b168c1.png)
Check the project’s code at this point.
此时检查项目的代码 。
8.2升级服务 (8.2 Upgrading Services)
Open app.module.ts
file, import and add HttpClientModule
to the imports
array of the AppModule
. HttpClientModule
replaces ngResource
in the new version of Angular.
打开app.module.ts
文件,导入HttpClientModule
并将其添加到AppModule
的imports
数组中。 HttpClientModule
在新版本的Angular中替换了ngResource
。
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/0808b8b2cdd31dd458653e632888ffa8.png)
Replace the implementation of src/app/core/phone/phone.service.js
for an Angular class using typescript (rename to phone.service.ts
):
使用打字稿(重命名为phone.service.ts
),将src/app/core/phone/phone.service.js
的实现替换为Angular类:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/044e47558fbeb3d67f6c22b9b4b7423d.png)
Downgrade the service so it could be used by AngularJS components:
降级服务,以便AngularJS组件可以使用它:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/c8b5b653793f82f7f4527d5a3ea673e6.png)
Load thephone.service.ts
through the AppModule:
加载phone.service.ts
通过的AppModule:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/4eeb25ef70430ed0f2791f9421108708.png)
Check the project’s code at this point.
此时检查项目的代码 。
8.3升级组件 (8.3 Upgrading Components)
Prepare the component code to be migrated, convert the templates into Angular syntax:
准备要迁移的组件代码,将模板转换为Angular语法:
![Image for post](https://miro.medium.com/max/9999/1*YrMeYLO3I8SC3PpQ-7FY3g.png)
Do the following changes in the html file:
在html文件中进行以下更改:
replace
.template.html
for.component.html
将
.template.html
替换为.component.html
replace
$ctrl
forvm
将
$ctrl
替换为vm
- replace AngularJS syntax to Angular (e.g. ng-repeat to *ngFor) 将AngularJS语法替换为Angular(例如,将ng-repeat替换为* ngFor)
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/daf19df927c1cc05f05a989dc6ab51e3.png)
Do the same with phone-detail
.
对phone-detail
进行相同的操作。
Convert both components to typescript and make use of the Phone Service (already migrated to Angular):
将两个组件都转换为打字稿,并使用电话服务(已迁移到Angular):
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/e07e6a944cdae24c613b45409d555d10.png)
![Image for post](https://miro.medium.com/max/9999/1*aRJW5KZMr-ioExQrt0unEg.png)
Convert AngularJS component definition object into an Angular @Component
decorator:
将AngularJS组件定义对象转换为Angular @Component
装饰器:
![Image for post](https://miro.medium.com/max/9999/1*_Q1Yi8ERVMrwp46q127wAw.png)
![Image for post](https://miro.medium.com/max/9999/1*RC-pwCNyoocwT5nq5pWH4g.png)
The new PhoneListComponent
uses the Angular ngModel
directive, located in the FormsModule
. Add the FormsModule
to NgModule
imports, declare the new PhoneListComponent
and finally add it to entryComponents
since you downgraded it:
新PhoneListComponent
使用角ngModel
指令,坐落在FormsModule
。 将FormsModule
添加到NgModule
导入中,声明新的PhoneListComponent
并最终将其添加到entryComponents
因为您将其降级了:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/33382e282b8ab505020de6d0b1d27a2d.png)
Do the same with phone-detail
.
对phone-detail
进行相同的操作。
Check the project’s code at this point.
此时检查项目的代码 。
8.4将过滤器转换为管道 (8.4 Transform filters into pipes)
The AngularJS directive has a checkmark
filter. Turn that into an Angular pipe. There is no upgrade method to convert filters into pipes, it needs to be rewritten.
AngularJS指令具有一个checkmark
过滤器 。 将其变成角度管。 没有将过滤器转换为管道的升级方法,需要重写。
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/927f162eb1dae4e50fd726e3739cb497.png)
Now import and declare the newly created pipe:
现在导入并声明新创建的管道:
![Image for post](https://miro.medium.com/max/9999/1*GP1VfF9yDhE_32UQoeHUBg.png)
The filer and orderBy pipe are not provided, so it is needed to create them.
未提供filer和orderBy管道,因此需要创建它们。
Check the project’s code at this point.
此时检查项目的代码 。
9.调整路线 (9. Adjust Routes)
Translate the existing code in app.config.ajs.js
into the existing file app-routing.module.ts
:
将app.config.ajs.js
的现有代码转换为现有文件app-routing.module.ts
:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/fd1dea123251155411fcbc32a538dd96.png)
Update the phone-detail component to use the proper route:
更新电话详细信息组件以使用正确的路由:
![Image for post](https://miro.medium.com/max/9999/1*HLxdGcFNmrZzGVbkTPIsiw.png)
Check the project’s code at this point.
此时检查项目的代码 。
10.删除AngularJS (10. Remove AngularJS)
Remove AngularJS injection, the file main.ts
may return to the original code:
删除AngularJS注入,文件main.ts
可能返回原始代码:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/cf3fda1dc9cbd1e3538086d05f2c5926.png)
Remove all references to the UpgradeModule
from app.module.ts
:
从app.module.ts
删除对UpgradeModule
所有引用:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/1ccde9e0c33930842d1242144fc99a77.png)
Also remove any downgradeInjectable()
or downgradeComponent()
you find, together with the associated AngularJS factory or directive declarations. Since you no longer have downgraded components, you no longer list them in entryComponents
.
还要删除找到的所有downgradeInjectable()
或downgradeComponent()
以及关联的AngularJS工厂或指令声明。 由于不再具有降级的组件,因此不再将它们列出在entryComponents
。
Remove as well as any factory provider for AngularJS services, and the app/ajs-upgraded-providers.ts
file.
删除AngularJS服务的所有工厂提供程序以及app/ajs-upgraded-providers.ts
文件。
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/79e3edd464ea749c2792b91446a8c21a.png)
You may also completely remove the following files. They are AngularJS module configuration files and not needed in Angular:
您也可以完全删除以下文件。 它们是AngularJS模块配置文件,在Angular中不需要:
app/app.module.ajs.js
app/app.module.ajs.js
app/app.config.ajs.js
app/app.config.ajs.js
app/core/core.module.js
app/core/core.module.js
app/core/phone/phone.module.js
app/core/phone/phone.module.js
app/phone-detail/phone-detail.module.js
app/phone-detail/phone-detail.module.js
app/phone-list/phone-list.module.js
app/phone-list/phone-list.module.js
The external typings for AngularJS may be uninstalled as well. The only ones you still need are for Jasmine and Angular polyfills. The @angular/upgrade
package can also go.
AngularJS的外部类型也可以被卸载。 您仍然唯一需要的是Jasmine和Angular polyfills。 @angular/upgrade
包也可以。
npm uninstall @angular/upgrade angular angular-animate angular-resource angular-route angular-mocks --save
Update bootstraping:
更新引导程序:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/b22913b015bdb4929cb30870b9ef3a2c.png)
Add this <app-root>
element to the index.html
. It replaces the old AngularJS ng-view
directive:
将此<app-root>
元素添加到index.html
。 它替换了旧的AngularJS ng-view
指令:
![Image for post](https://i-blog.csdnimg.cn/blog_migrate/e4c077e77aed7f9ddf5f3520b87d6252.png)
Check the project’s code at this point. At this point we have the application migrated to the new version of Angular :)
此时检查项目的代码 。 至此,我们已经将应用程序迁移到了新版本的Angular :)