使用Angular cli升級AngularJS專案——(一)引導Angular混合應用

益生菌。發表於2019-02-14

前言

都9102年了,筆者所在的公司的主要專案還是用AngularJS 1.6這種史詩的框架進行開發的。另外由於歷史的原因,程式碼的凌亂程度早已超越想象。為此,筆者決定痛下決心把整個專案重構了一遍…從此踏上了Angular升(跳)級(坑)之路。

先說說升級前後的變化:
專案管理:gulp -> gulp + Angular CLI
框架:AngularJS 1.6 -> AngularJS 1.6 + Angular 7
應用結構:多個AngularJS應用 -> 主專案:Angular、衛星專案:AngularJS

這個系列文章中涉及到

  1. Angular與AngularJS如何共存開發
  2. 使用Angular Cli編譯及開發Angular、AngularJS混合應用
    —下面是坑,待填
  3. 如何在Hash模式中同步AngularJS、Angular的路由
  4. 在gulp或其他自動化構建工具中使用Angular CLI
  5. 在Angular中使用AngularJS的元件
  6. 在AngularJS中使用Angular的元件

本文使用的例子專案

AngularJS的例子專案angular-phonecat

為什麼升級為Angular框架

在筆者公司內部,大部分新專案已經開始使用Vue進行開發。筆者也更加傾向於Vue簡單、優雅的開發形式,較為符合前端(浪蕩)的開發模式。同時對於新手而言Vue更加容易上手。但對於筆者手上的專案而言,升級為Angular是為數不多可行的方案:

  1. 漸近式升級
    由於專案年代久遠,專案涉及到了公司各個業務的方方面面。難以在短時間內完成全部的重構工作。在重構的同時,也需要兼顧到新業務的開發。(曾經這個專案在多個大佬的帶領下重構過,但無一倖免的全部夭折)。為此,選擇升級為Angular的第一考量的物件就是是否可以“在原有的基礎上進行重構”,而Angular官方提供的@angular/upgrade則很好的解決了這個問題。直至完全重構為止,舊的程式碼仍能直接執行在專案中,不受重構的影響。
  2. 更加嚴謹的開發
    在改造前的專案中包含了幾個5000+行的檔案,每次新增都非常“蛋疼”,出現這種問題的主要原因就是在這幾年間,都沒有對專案提交程式碼進行規範,同時也沒有進行Code Review等操作。使用TypeScript可以讓一部分Freshman放棄他們浪蕩的程式碼風格。此外,對於太過爛的程式碼,Angular甚至不能讓其編譯通過。這種框架以及語言特性決定了Angular更加擅長於開發更加嚴謹的專案。
    當然,Vue也能使用TypeScript,經過規範的Vue編碼風格也能使其變得更嚴謹,前提是你得忍受編輯器對vue中的ts語言的支援:)

一、前期準備

檢查你的專案是否包含Angular cli無法支援的編譯特性。

在筆者公司專案中,使用gulp作為專案管理工具。其中包含了gulp-file-include在html檔案中引入其他html片段的外掛,但是如果使用Angular cli(以下簡述為:ng cli)作為專案編譯開發工具,這些過程是不能被支援的。因此,應當先將它們去除。

安裝Angular CLI

筆者使用的是yarn:

  yarn global add @angular/cli
複製程式碼

如果你是使用npm:

  npm i @angular/cli -g
複製程式碼

二、新建一個種子專案

Angular的迭代更新速度是有目共睹的,筆者建議直接新建一個種子專案,而非直接複製本文提及的依賴關係。

使用Angular cli升級AngularJS專案——(一)引導Angular混合應用

具體的使用方法見官方文件
執行完畢後,將以下檔案複製到你的專案中:

  • package.json
    若專案中已存在package.json你可以直接複製與angular有關的依賴。
    "dependencies": {
      "@angular/animations": "~7.1.0",
      "@angular/common": "~7.1.0",
      "@angular/compiler": "~7.1.0",
      "@angular/core": "~7.1.0",
      "@angular/forms": "~7.1.0",
      "@angular/platform-browser": "~7.1.0",
      "@angular/platform-browser-dynamic": "~7.1.0",
      "@angular/router": "~7.1.0",
      "core-js": "^2.5.4",
      "rxjs": "~6.3.3",
      "tslib": "^1.9.0",
      "zone.js": "~0.8.26"
    },
    "devDependencies": {
      "@angular-devkit/build-angular": "~0.11.0",
      "@angular/cli": "~7.1.2",
      "@angular/compiler-cli": "~7.1.0",
      "@angular/language-service": "~7.1.0",
      "typescript": "~3.1.6"
    }
    複製程式碼
  • tsconfig.json。typescript配置檔案
  • angular.json。angular配置檔案
  • src 目錄。angular原始碼資料夾,你可以將其放到你的專案中適當的地方。

三、新增升級依賴

在種子專案中,是不包含AngularJS升級模組的,你需要手動新增該模組。

yarn add @angular/upgrade
複製程式碼

四、將AngularJS的js、style交給angular cli管理

使用Angular cli升級AngularJS專案——(一)引導Angular混合應用

AngularJS的引入方式一般有兩種形式

  1. 使用了模組化的
    如果本身已經使用了模組化的程式設計,那麼你要做的就是移除原本的模組引導器(如SystemJs等)、在index.html中移除ng-app。並在main.ts中import AngularJS入口檔案即可。
    注意:你或許還需在tsconfig.json中加入:

     "compilerOptions": {
       ...
       "allowJs": true,
       ...
     }
    複製程式碼
  2. 一般引入形式的
    如果專案中使用的是傳統引入形式,你需要將他們全部刪除掉,並在angular.json中projects -> porjectName -> architect -> build中的stylesscripts屬性新增相應的樣式、js檔案。在此新增的檔案,angular cli會在編譯、開發過程中,進行合併壓縮操作。然後在index.html中將ng-app移除。

使用Angular cli升級AngularJS專案——(一)引導Angular混合應用

新增assets資料夾

在AngularJS中,存在一些如templateURL等,需要從伺服器載入的內容。因此,我們需要在angular.json中對映原始碼資料夾,使它能在serve的過程中,能被訪問到。
具體路徑:angular.json projects -> porjectName -> architect -> build -> assets

五、在index.html中新增angular的入口

<app-root></app-root>是angular的入口標記,你可以將其新增至index.html中合適的位置,一般為了結構一致,會放在與AngularJS相鄰的地方。

使用Angular cli升級AngularJS專案——(一)引導Angular混合應用

六、引導AngularJS模組

到這裡,你已經可以使用ng serve進行開發了。但實際上,如果此時開始執行的話,在頁面中只會有Angular模組的內容,沒有AngularJS模組的內容。

使用Angular cli升級AngularJS專案——(一)引導Angular混合應用

實際上,js的指令碼已經通過ng cli進行處理,併合併為scripts.js,但由於在此前的操作中,我們將AngularJS的ng-app指令移除了。為此我們需要在angular載入過程中手動載入AngularJS模組。

app.module.ts

import { BrowserModule } from `@angular/platform-browser`;
import { NgModule, DoBootstrap, ApplicationRef } from `@angular/core`;
import { AppRoutingModule } from `./app-routing.module`;
import { AppComponent } from `./app.component`;
import { UpgradeModule } from `@angular/upgrade/static`;

@NgModule({
  declarations: [
    AppComponent
  ],
  entryComponents: [AppComponent],
  imports: [
    BrowserModule,
    AppRoutingModule,
    UpgradeModule
  ],
  providers: [],
})
export class AppModule implements DoBootstrap {
  constructor(private upgrade: UpgradeModule){}

  // 手動接管載入程式
  ngDoBootstrap(appRef: ApplicationRef) {
    this.upgrade.bootstrap(document.documentElement, [`phonecatApp`]); // 引導AngularJS模組
    appRef.bootstrap(AppComponent) // 引導Angular模組
  }
 }

複製程式碼

七、大功告成

現在執行ng serve就可以看到同時執行Angular、AngularJS的頁面了!

使用Angular cli升級AngularJS專案——(一)引導Angular混合應用

(未完待續)

原始碼

由於篇幅有限,實際上還有幾處修改未在文段中展示。在此,你可以獲取到本文修改後的angular-phonecat專案。
[github.com/yskun/angul…]

參考

  1. 從 AngularJS 升級到 Angular
  2. 升級 AngularJS 至 Angular

相關文章