現代化全棧項目框架NX快速入門

NX是一個全棧工程集成框架,提供了一套完整的解決方案和工具來實現全棧項目開發。Nx使用了諸如Cypress,Jest,Prettier,TypeScript等現代化工具來實現包括Angular、React和Node、Nest、Express等各種框架的集成開發,並且提供了深度圖、依賴檢測等功能,使小型團隊也能使用像Google,Facebook和微軟一樣的開發工具和流程。本文基於Nx官方入門案例,以實現對Nx的使用流程和特性的熟悉和入門。

1. 創建一個新的nx工程

使用下面任意一種即可。注意國內安裝cypress會很慢,最好在.npmrc文件中修改路徑。 預設模板選擇empty,選擇Angular CLI作為命令行工具。這樣就創建了一個空的工程。

<code>npx create-nx-workspace@latest myworkspace
npm init nx-workspace myworkspace
yarn create nx-workspace myworkspace
cd myworkspace/<code>

2. 創建一個Angular應用

如果已經安裝有Angular CLI(推薦),可以用ng命令快速開始 先用默認參數添加angular,然後創建一個名為todos的應用

<code>ng add @nrwl/angular --defaults
ng g @nrwl/angular:application todos/<code>

命令會生成一個空的Angular應用和對應的E2E測試程序。 輸入ng serve todos運行程序。

3. 添加測試

Nx默認使用Cypress運行E2E測試。 修改apps/todos-e2e/src/support/app.po.ts文件.

<code>export const getTodos = () => cy.get('li.todo');
export const getAddTodoButton = () => cy.get('button#add-todo');/<code>

然後修改apps/todos-e2e/src/integration/app.spec.ts

<code>import { getAddTodoButton, getTodos } from '../support/app.po';

describe('TodoApps', () => {
beforeEach(() => cy.visit('/'));

it('should display todos', () => {

getTodos().should(t => expect(t.length).equal(2));
getAddTodoButton().click();
getTodos().should(t => expect(t.length).equal(3));
});
});/<code>

停止ng serve,運行ng e2e todos-e2e或者ng e2e todos-e2e --watch啟動測試程序,會打開一個UI界面。如果加上--headless後綴,則打開無頭瀏覽器(不顯示前端界面)。

4. 修改Angular程序以通過測試

打開apps/todos/src/app/app.component.ts文件。並修改如下:

<code>import { Component } from '@angular/core';

interface Todo {
title: string;
}

@Component({
selector: 'myorg-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
todos: Todo[] = [{ title: 'Todo 1' }, { title: 'Todo 2' }];

addTodo() {
this.todos.push({
title: `New todo ${Math.floor(Math.random() * 1000)}`
});
}
}/<code>

打開apps/todos/src/app/app.component.html文件並修改如下:

<code>

Todos




  • {{ t.title }}



<button>Add Todo/<button>/<code>

重複運行前一步的測試,可以看到測試已經通過。(如果前一步打開watch選項,則測試會自動重新運行)。

5. 連接API服務

導入HttpClientModule來使用Http服務。在apps/todos/src/app/app.module.ts中添加Import語句,並且在@NgModule聲明的import部分加以聲明。

<code>import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';

@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, HttpClientModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}/<code>

修改apps/todos/src/app/app.component.ts文件,使用http服務:

<code>import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

interface Todo {
title: string;
}

@Component({
selector: 'myorg-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
todos: Todo[] = [];


constructor(private http: HttpClient) {
this.fetch();
}

fetch() {
this.http.get<todo>('/api/todos').subscribe(t => (this.todos = t));
}

addTodo() {
this.http.post('/api/addTodo', {}).subscribe(() => {
this.fetch();
});
}
}/<todo>/<code>

運行ng serve,因為此時服務端還不能提供api接口服務,因此頁面看不到任何數據。

6. 添加後端API服務接口

本例使用Nest框架提供後端服務接口,這是一個非常優秀的後端框架。在各種後端項目中得到廣泛應用。 使用下面的命令生成一個api服務,在待輸入的目錄選項中直接回車即可(不需要分api目錄級別)

<code>ng g @nrwl/nest:app api --frontendProject=todos/<code>

在工作空間的apps目錄下面可以看到前端工程文件夾todos,後端工程文件夾api,以及前端測試工程todos-e2e,等等。在nx前後端一體的工程中,通過這樣的文件架構,nx可以在同一個工作空間管理和執行前端、後端和測試工程的各個環節。 可以巡幸下列命令來執行後端項目。 - ng serve api運行後端應用 - ng build api編譯後端應用 - ng test api運行後端測試 打開apps/api/src/app/app.service.ts文件並添加服務。

<code>import { Module } from '@nestjs/common';

import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
imports: [],
controllers: [AppController],
providers: [AppService]
})
export class AppModule {}/<code>

打開apps/api/src/app/app.controller.ts文件並添加服務。

<code>import { Controller, Get, Post } from '@nestjs/common';

import { AppService } from './app.service';

@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}

@Get('todos')
getData() {
return this.appService.getData();
}

@Post('addTodo')
addTodo() {
return this.appService.addTodo();
}
}/<code>

再打開命令行輸入http://localhost:3333/api/todos就可以看到默認的todos內容。如果使用VSCode可以用Rest Client插件測試POST http://localhost:3333/api/addtodo功能。或者使用curl或者Postman等其他測試工具均可。POST之後再Get,會發現新的Todo條目已經添加進去了。

7. 設置代理

在前一步添加api服務的時候,我們使用了--frontendProject=todos的參數。這個參數實際上添加了供Angular在開發時訪問服務端的能力。其中的魔法在根目錄下的angular.json文件中。

<code>{
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "todos:build",
"proxyConfig": "apps/todos/proxy.conf.json"
},
"configurations": {
"production": {
"browserTarget": "todos:build:production"
}
}
}
}/<code>

其中proxyConfig條目聲明瞭代理的位置。打開該文件:

<code>{
"/api": {
"target": "http://localhost:3333",
"secure": false
}
}/<code>

這裡把所有/api的請求自動轉向至api後端。這時候如果分別在兩個終端裡輸入ng serve api和ng serve todos,再打開網址http://127.0.0.1:4200,會發現todos應用已經可以正常工作了。

8. 代碼共享

目前,程序前後端工作良好,但Nx的框架特點並沒有體現出來,Todo接口在前後端同時聲明,隨著項目擴展,前後端的銜接會逐漸出現問題,因此需要Nx框架來創建數據library來集成數據。 在根目錄下運行ng g @nrwl/workspace:lib data生成data目錄。

打開/libs/data/src/lib/data.ts,定義Todo接口。

<code>export interface Todo {
title: string;
}/<code>

分別在後端文件apps/api/src/app/app.service.ts和前端文件apps/todos/src/app/app.component.ts中分別引入lib中的Todo接口來替換之前的聲明。

<code>import { Todo } from '@myorg/data' ;/<code>

9.創建共享庫(lib)

Nxde的共享庫不僅僅可以用來共享代碼,更可以通過工廠模式通過公開API接口將代碼組織為更好的小模塊。

UI界面庫

此處通過創建一個Angular組件來說明。運行ng g @nrwl/angular:lib ui來創建一個anular ui共享庫。 指令會創建libs/ui/庫,在libs/ui/src/lib/ui.module.ts文件中會初始化創建如下代碼:

<code>ng g @nrwl/angular:lib ui
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

@NgModule({
imports: [CommonModule]
})
export class UiModule {}/<code>

創建一個組件

接下來通過如下命令在ui庫中創建一個angular 組件todos。

<code>ng g component todos --project=ui --export/<code>

像在angular中一樣修改生成的libs/ui/src/lib/todos/todos.component.ts文件和todos.component.html文件。注意這裡也用到了上一節創建的Todo接口。

<code>//todos.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { Todo } from '@myorg/data';

@Component({
selector: 'myorg-todos',
templateUrl: './todos.component.html',
styleUrls: ['./todos.component.css']
})
export class TodosComponent implements OnInit {
@Input() todos: Todo[];

constructor() {}

ngOnInit() {}
}
//todos.component.html

  • {{t.title}}

/<code>

使用創建的 UI庫

用生成的ui庫替換之前創建的組件。 更新apps/todos/src/app/app.module.ts來引入組件。

<code>import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { HttpClientModule } from '@angular/common/http';
import { UiModule } from '@myorg/ui';

@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, HttpClientModule, UiModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}/<code>

更新app.component.html來使用組件。

<code>

Todos



<myorg-todos>

<button>Add Todo/<button>/<code>

生成系統架構圖Dep Graph

一個大型工程可能包含成百上千個組件和應用,很快這些組件之間的依賴就會變得錯綜複雜難以理解。Nx為此提供了一個專門用於生成組件關係圖的命令行工具Dep Graph。可以讓開發人員對組件關係一目瞭然。運行下列命令。Nx會打開瀏覽器http://127.0.0.1:4211生成系統架構圖。

<code>npm run dep-graph/<code>

本項目生成的架構圖如下:

現代化全棧項目框架NX快速入門


檢查依賴影響

除了生成依賴圖表,Nx還可以檢查項目中相互影響關係的變動。在嘗試該步驟前需要與git配合,如果系統中沒有安裝git需要先安裝。此外,由於本項目是從git倉庫中下載來的,因此如果要推送到遠程倉庫需要先重置遠程倉庫目標來退送到自己的倉庫中。 執行下列命令提交到目前為止的變更。

<code>git add .
git commit -am 'init'/<code>

接下來修改程序源代碼,比如在libs/ui/src/lib/todos/todos.component.html文件的符號前加一個錯誤改為 !。 然後運行下列命令,系統會列出affected:apps todos.表示該修改影響了依賴組件todos。

<code>npm run affected:apps/<code>

如果輸入下面命令,會顯示受到影響的共享庫(這裡是ui)。

<code>npm run affected:libs/<code>

影響測試

除了手動運行上述命令檢查變動牽連到了哪些組件和共享庫之外,也可以運行影響測試,來檢查改動是否對測試產生影響(還能不能通過測試)。因為我們修改了程序之後一直沒有修改對應的測試文件,所以這裡運行是通不過測試的。

<code>npm run affected:test/<code>

運行影響測試命令會重新開始運行測試程序,並列舉出測試問題,如果只想看到沒有通過測試的內容,可以傳入--only-failed參數。

同步測試

為了加快測試速度,可以傳入--parallel參數來使用同步技術加快測試速度。

變動構建(build)

代碼變動後可進行變動構建以快速構建變動部分。

<code>npm run affected:build #變動構建
npm run affected -- -- target=build #和上一命令等價/<code>

彙總

通過本項目實現了以下工作。 - 使用前端框架Angular和後端框架Nest實現全棧工程開發 - 在前端和後端工程之間實現了代碼共享 - 創建了一個UI庫 - 使用Nx的深度圖工具來生成項目依賴關係圖 - 通過Nx的依賴檢測工具實現了依賴變動的檢測


現代化全棧項目框架NX快速入門


分享到:


相關文章: