Angular 17+ 高級教程 – Library

前言

當你需要管理超過一個項目時,你就需要知道怎麼使用 Angular Library。

你可以把多個項目共享的組件放到這個 Library 了,就像 Angular Material 那樣。

 

參考

Sandro Roth – Building an Angular Library with multiple entry points (主要參考)

Docs – Creating libraries

Docs – Copy assets

Docs – Embed assets in CSS

Stack Overflow – Include assets when building angular library

 

Angualr Library の Get Started 版

我們先來一個 Get Started 版本,之後再補一個實戰版。

提醒:我這裏給的例子 Library 和 Application 會在同一個項目裏 (所謂的 Local Library)。如果要不同項目,那就需要把 Library 發佈到 npm 纔行。在本篇的結尾會講解如何 publish to npm。

Create project

ng new play-library --create-application=false

在創建項目的同時,不要創建 Application 先,因爲有 Library,folder 結構會不一樣。

目前 folder 結構長這樣

angular.json 長這樣

空空如也。

Create Application

接着創建 Application

ng g app my-app --routing=false --ssr=false --style=scss --skip-tests

folder 多了一個 projects/my-app

angular.json 也多了一個 projects.my-app 配置

Create Library

接着創建 Library

ng g lib stooges --prefix=stg

我的 Library 名字叫 stooges

folder 又多了一個 projects/stooges

stooges library 裏,Angular 默認會替我們創建一個 demo component 和 service。

angular.json 也多了一個 projects.stooges 配置

Build library

要使用 Library ,我們需要先 build 它。

ng build stooges --watch

build 也是可以 watch 的哦,每當我們修改,它就會 re-build (我不清楚是 re-build 修改的部分還是全部🤷‍♂️)

build 好之後,它會多一個 folder -- dist/stooges 

Use library in application

app.component.ts

import { Component } from '@angular/core';
import { StoogesComponent } from 'stooges'; // 1. import component from library

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [StoogesComponent],              // 2. import StoogesComponent
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss'
})
export class AppComponent {}

app.component.html

<stg-stooges />

run

ng serve --open

效果

哎喲,不錯哦!It just work😎。

The connection between the library and the application

你可能會好奇,app.component.ts 爲什麼可以 import 到 'stooges'

import { StoogesComponent } from 'stooges';

stooges library 在 dist 裏,並不在 node_modules 裏丫🤔。

它的祕密在 tsconfig.json 裏

在 ng g lib 時,它偷偷往裏頭做了一個 connection 配置,所以 Application 就和 Library 連上了。

總結

Get Started 只是讓大家感受以下 Angular Library 長啥樣,上面提到的幾個 folder 和 file 都是和 Library 比較有關係的,如果以後遇到什麼疑難雜症可以多往這幾個地方調查。

好,我們進入下一 part -- Angualr Library 實戰版。

 

Angualr Library の 實戰版

我們延續上面 Get Started 版本,把它改成實戰版。

Multiple export path

目前有一個問題 -- Library 只有一個出入口

import { StoogesComponent } from 'stooges';

假如我有 1000 個組件,由於它們都是通過 import .. from 'stooges' 導入,那它們就絕對不可以撞名字。

這對命名要求很高啊。

那...如果可以這樣...

import { StgDialogComponent, StgSameNameComponent as StgDialogSameNameComponent } from 'stooges/dialog';
import { StgCardComponent, StgSameNameComponent as StgCardSameNameComponent } from 'stooges/card';

stooges/table 和 stooges/select 都是 stooges library,但 stooges library 裏面又細分成了 2 個 namespace 'table' 和 'select'。

我們可以以 2 個不同的 path 做 import,這樣就大大減少了撞名字的可能性,即使撞了名字也可以通過 as alias 換名。

restructure folder

首先,把 src/lib/ folder 給刪了。

改成這樣

select 和 table 將成爲 2 個 export path,它們裏面裝了很多組件,細節我們下面再看。

index.ts 取代了原本的 src/public_api.ts

由於我沒有需要 root export (因爲有了 select 和 table 2 個 sub export),所以這裏做一個假 export 騙過它就好。

接着,ng-package.json 的路徑需要換一下

然後是 table 和 select folder

每一個要 sub export 的 folder 都需要加上 index.ts 和 ng-package.json。

index.ts 負責 export 組件

ng-package.json 就抄 root 的 ng-package.json

有兩個小區別:

  1. $schema 路徑多了一個 ../

  2. root 有一個 "dest" : "../../dist/stooges" 屬性,sub 不需要 "dest" 屬性。

select 和 table 一樣,也需要 index.ts 和 ng-package.json。

build library

接着 build library

ng build stooges --watch

效果

之前只有一個 lib folder,現在變成了 select 和 table 2 個 folders。

connect library

connect library 會比之前複雜一些。

首先是 tsconfig.ts

本來是直接鏈接到 dist library,現在改成鏈接到原本的 source library,然後結尾要用 /* 表示匹配 multiple path。

接着是 angular.json

把 /src 移除

再來是 /projects/my-app/tsconfig.app.json

這裏鏈接到 dist library,之前 root tsconfig 則是鏈接到 source library,一個 dist 一個 source 被搞錯哦。

test run application

build and connect 之後就可以 test run 了。

app.component.ts

import { Component } from '@angular/core';
import { StgSelectModule } from 'stooges/select'; // 1. import component from library
import { StgTableModule } from 'stooges/table';   // 2. import component from library

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [StgSelectModule, StgTableModule], 
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss'
})
export class AppComponent {}

兩個 module 分別 import from 各自的 path。

app.component.html

<stg-table>
  <stg-tr>
    <stg-td />
    <stg-td />
  </stg-tr>
</stg-table>

<stg-select>
  <stg-option />
  <stg-option />
</stg-select>

run

ng serve --open

效果

import sub path inside library

library 內如果需要互相 import,也是使用絕對路徑。

Export scss

除了 multiple export path,另一個常見的需求是要 export scss。

首先在 library 裏創建一個 styles forlder 

reset.scss 和 _theme.scss

添加 assets 配置到 ng-package.json

表示我們要 export styles 這個 folder 裏的所有 scss。

build library

ng build stooges --watch

效果

_theme.scss 和 reset.scss 被打包出來了。

connect library

添加 stylePreprocessorOptions 到 angular.json

這樣 application 就能鏈接到 dist library 的 styles 了。

test run application

run

ng serve --open

效果

margin 被 reset.scss 清除了,body background 也被 theme.scss 染成了粉紅色。

Export assets

scss 可以 export,其它類型的 file 也可以 export,比如圖片,雖然圖片不常會被封裝進 Library。

添加 assets folder 到 Library

裏面有一張圖片。

在 ng-package.json 裏再添加多一個 assets 配置

意思是我們要 export 所有 assets 裏的 files。

build library

ng build stooges --watch

效果

圖片被打包出來了。

connect library

到 angular.json 添加 assets 配置

這樣 application 就鏈接上了 dist library 的 assets files。

test run application

app.component.html

path starts with /stg-assets/**/* (使用絕對路徑)

run

ng serve --open

效果

use assets inside library

假設,我們沒有 export assets,但是我們有 assets,我們只是在 library 中使用它。

這種情況的話,假如圖片用於 scss url('....') 那它會被自動 convert to base64,我們可以不需要做 export。

假如圖片被用於 <img src="..." >,這樣不行,它不會自動 convert to base64,我們一定要 export assets 纔行。

另外,有 export 的必須使用絕對路徑,如果 url('...') 使用相對路徑那它會 convert to base64,如果使用絕對路徑則不會 convert to base64 (使用絕對路徑,我們就要確保有 export 圖片哦,不然就空白了)。

總結

它其實就是幾個東西在玩。

首先是 library folder 結構

然後是 library 要 export 的配置

接着 build to dist

然後 application 要 connect to dist library 或者 souce library

ts, scss, assets 三個的 export 和 connect 配置都不太一樣。

大概就是這些,建議大家自己動手玩一玩。

 

Publish Library

publish 很簡單,因爲我們已經 build to dist 了,把整個 dist folder 發佈到 npm 就可以了。

cd dist/stooges
npm publish

publish 好了後就可以下載了

yarn add stooges

接着需要把 connect to dist 換成 connect to node_modules。

首先,root tsconfig 不需要 connect to source library 了,因爲 node_modules 裏的 ts 是自動 connect 的。

同樣,application 的 tsconfig 也不需要 connect to dist library 了

ts 不需要配置,但是 scss 和 assets 需要。

去 angular.json 把 connect to dist 換成 connect to node_modules

搞定!

 

關於 peerDependencies

Library 或許會依賴其它的 Library,通常這些依賴不會寫在 package.json 的 dependencies,而會寫在 peerDependencies。

它們的區別是,peerDependencies 要求使用 Library 的人在外部去 yarn add 這些 Library 依賴,好處是不會 duplicated,因爲 Application 和 Library 或許有相同的依賴,總不能 2 邊分開加載,是吧。

 

目錄

上一篇 Angular 17+ 高級教程 – EventManagerPlugin & Hammer.js Gesture

下一篇 Angular 17+ 高級教程 – Prettier, ESLint, Stylelint

想查看目錄,請移步 Angular 17+ 高級教程 – 目錄

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章