2019年11月9日 星期六

[morse]建立 Angular Library 函式庫專案 Part-I

我們先建立一個 Angular 專案

ng new emp20191109

上例中我把專案的名稱定為 "emp20191109",然而在這個新的專案中是可包含多個 Angular 專案在其中的, 你可以在這個專案的根目錄中找到 "angular.json", 如下 :

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "emp20191109": {
      "projectType": "application",
      "schematics": {},
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/emp20191109",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "aot": false,
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.css"
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "2mb",
                  "maximumError": "5mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "6kb",
                  "maximumError": "10kb"
                }
              ]
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "emp20191109:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "emp20191109:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "emp20191109:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.spec.json",
            "karmaConfig": "karma.conf.js",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.css"
            ],
            "scripts": []
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "tsconfig.app.json",
              "tsconfig.spec.json",
              "e2e/tsconfig.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        },
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "emp20191109:serve"
          },
          "configurations": {
            "production": {
              "devServerTarget": "emp20191109:serve:production"
            }
          }
        }
      }
    }},
  "defaultProject": "emp20191109"
}


其中你可以找到 projects 節點,這裡就是定義多專案的設定。


如果我們只想在專案中增加一個函式庫專案,那麼你可以採用下列的 Angular 指令:

ng g library morse-library --prefix=mos


上例中我把函式庫的名稱定義為 "morse-library", 對 Angular 應用程式來說,通常所有 Comeponts 與 Directives 都會以 app 作為前置詞(prefix),但開發給任意專案共用的函式庫,通常不會這樣命名。在上例中我用的前置詞是 mos 基本上它並沒有什麼特別限制,你可依你的想自已給它個名,這裡我個人建議是別用 "app"就好了。


在專案加入了函式庫後 "angular.json" 內容異動如下:

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "emp20191109": {
      "projectType": "application",
      "schematics": {},
      "root": "",
      "sourceRoot": "src",
      "prefix": "app",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/emp20191109",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.app.json",
            "aot": false,
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.css"
            ],
            "scripts": []
          },
          "configurations": {
            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "2mb",
                  "maximumError": "5mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "6kb",
                  "maximumError": "10kb"
                }
              ]
            }
          }
        },
        "serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "emp20191109:build"
          },
          "configurations": {
            "production": {
              "browserTarget": "emp20191109:build:production"
            }
          }
        },
        "extract-i18n": {
          "builder": "@angular-devkit/build-angular:extract-i18n",
          "options": {
            "browserTarget": "emp20191109:build"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "src/test.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "tsconfig.spec.json",
            "karmaConfig": "karma.conf.js",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.css"
            ],
            "scripts": []
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "tsconfig.app.json",
              "tsconfig.spec.json",
              "e2e/tsconfig.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        },
        "e2e": {
          "builder": "@angular-devkit/build-angular:protractor",
          "options": {
            "protractorConfig": "e2e/protractor.conf.js",
            "devServerTarget": "emp20191109:serve"
          },
          "configurations": {
            "production": {
              "devServerTarget": "emp20191109:serve:production"
            }
          }
        }
      }
    },
    "morse-library": {
      "projectType": "library",
      "root": "projects/morse-library",
      "sourceRoot": "projects/morse-library/src",
      "prefix": "mos",
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-ng-packagr:build",
          "options": {
            "tsConfig": "projects/morse-library/tsconfig.lib.json",
            "project": "projects/morse-library/ng-package.json"
          }
        },
        "test": {
          "builder": "@angular-devkit/build-angular:karma",
          "options": {
            "main": "projects/morse-library/src/test.ts",
            "tsConfig": "projects/morse-library/tsconfig.spec.json",
            "karmaConfig": "projects/morse-library/karma.conf.js"
          }
        },
        "lint": {
          "builder": "@angular-devkit/build-angular:tslint",
          "options": {
            "tsConfig": [
              "projects/morse-library/tsconfig.lib.json",
              "projects/morse-library/tsconfig.spec.json"
            ],
            "exclude": [
              "**/node_modules/**"
            ]
          }
        }
      }
    }},
  "defaultProject": "emp20191109"
}

紅字部分是自動增加的內容。


專案目錄的配置如下:



增加了上圖中紅框的配置。

另在專案的幾個配置檔案也都有異動,例如:"tsconfig.json" 配置異動如下:

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "module": "esnext",
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "es2015",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2018",
      "dom"
    ],
    "paths": {
      "morse-library": [
        "dist/morse-library"
      ],
      "morse-library/*": [
        "dist/morse-library/*"
      ]
    }
  },
  "angularCompilerOptions": {
    "fullTemplateTypeCheck": true,
    "strictInjectionParameters": true
  }
}

增加了上例的紅字內容。


在 "projects\morse-library\src" 目錄中的 "public-api.ts" 如下:

/*
 * Public API Surface of morse-library
 */

export * from './lib/morse-library.service';
export * from './lib/morse-library.component';
export * from './lib/morse-library.module';

這函式庫預設生成的內容,你也可以依需作增減,其本上它的內容是可以包含服務(service)、元件(compoment)、模組(module)...等。


Angular 專案中,我們可以透過引用 'MorseLibraryModule' 來 import 函式庫中的任何模組或服務元件,如下:

import { MorseLibraryModule } from 'projects/morse-library/src/public-api';


你可以調整專案的 "app.module.ts" 成如下,以達到整個函式庫引用的目的:

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

import { AppComponent } from './app.component';
import { MorseLibraryModule } from 'projects/morse-library/src/public-api';


@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    MorseLibraryModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }


紅字部分是調整的內容。


我試著增加函式於 "projects\morse-library\src\lib\morse-library.service.ts" 中,如下:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class MorseLibraryService {

  constructor() { }

  getTitle(){
    return "Morse Library Project";
  }
}

紅字部分是增加的內容。


然後試著在專案的 "app.component.ts" 中叫用它 [getTitle()],如下

import { Component, OnInit } from '@angular/core';
import { MorseLibraryService } from 'projects/morse-library/src/public-api';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  title = 'emp20191109';

  constructor(
    private _morseLibrary: MorseLibraryService
  ){}

  ngOnInit(){
    this.title = this._morseLibrary.getTitle();
  }  
  
}

紅字部分是調整的內容。


執行結果:






這樣我們就為 Angular 專案完成了自定義函數庫的配置了。


沒有留言:

張貼留言