從接觸Angular到如今帖烘,做了不少Angular項(xiàng)目,使用了不少第三方庫(kù),但是卻沒(méi)有勇氣觸碰第三方庫(kù)的開(kāi)發(fā)庶溶,一是沒(méi)有太多的積累煮纵,二是沒(méi)有找到合適的“Hello world”的文檔。
最近有機(jī)會(huì)要把項(xiàng)目中常用的Component做成第三方庫(kù)偏螺,方便更多的項(xiàng)目使用行疏。根據(jù)網(wǎng)上找到的各種資料,加上走的各種彎路套像,終于摸清楚了開(kāi)發(fā)第三方庫(kù)的流程酿联。
搭建項(xiàng)目框架
為了方便第三方庫(kù)的開(kāi)發(fā),我們首先要?jiǎng)?chuàng)建一個(gè)主應(yīng)用A:
ng new projectnameA //創(chuàng)建主應(yīng)用
主應(yīng)用A創(chuàng)建好之后夺巩,創(chuàng)建Lib:
cd projectnameA
ng g library libName --prefix prefixName //--prefix是Lib使用的前綴
上述命令會(huì)對(duì)主應(yīng)用如下改變:
在主應(yīng)用A下創(chuàng)建 projects/libName 目錄贞让,并將Lib的相關(guān)文件放于此;
-
在 angular.json 文件中添加 libName 項(xiàng)目柳譬;
"libName": { "root": "projects/libName", "sourceRoot": "projects/libName/src", "projectType": "library", "prefix": "dteam-top", "architect": { "build": { "builder": "@angular-devkit/build-ng-packagr:build", "options": { "tsConfig": "projects/libName/tsconfig.lib.json", "project": "projects/libName/ng-package.json" }, "configurations": { "production": { "project": "projects/libName/ng-package.prod.json" } } }, "test": {...}, "lint": {...} } }
其中:
root為L(zhǎng)ib的根目錄喳张;
sourceRoot為L(zhǎng)ib的源代碼目錄;
projectType為項(xiàng)目的類型美澳;
prefix為組件使用的前綴销部;
architect為Angular的構(gòu)建配置,可設(shè)置 build制跟、test 和 lint舅桩。 在 package.json 文件中添加 ng-packagr 依賴;
-
在 tsconfig.json 文件中添加 libName 庫(kù)的引用凫岖;
{ ... "paths": { "libName": [ "dist/libName" ] } ... }
這樣項(xiàng)目框架就搭建好了江咳,可以開(kāi)始寫(xiě)Lib的代碼了。
Lib開(kāi)發(fā)
在Lib中需要注意一個(gè)文件:public_api.ts哥放,這個(gè)文件是Lib的入口文件歼指,取代了之前使用的index.ts文件,其中定義了Export的內(nèi)容:
````
export * from './app/libName.component';
export * from './app/libName.module';
````
主應(yīng)用A要使用Lib甥雕,在app.module.ts文件中直接引用:
import { LibNameModule } from '../../../../projects/libName/src/app/libName.module'
imports: [
...
LibNameModule,
...
]
對(duì)于Lib中使用的其他組件踩身,可在主應(yīng)用A下通過(guò)npm安裝,這里提醒下社露,這里是安裝到主應(yīng)用A的目錄下挟阻,修改的是主應(yīng)用A的package.json和package.lock.json文件。
這樣附鸽,就可以開(kāi)發(fā)自己的Lib了。
測(cè)試Lib的安裝
Lib開(kāi)發(fā)好之后瞒瘸,需要先在本地試安裝坷备。這時(shí)有疑問(wèn)了,Lib中用到的其他組件的引入都是在主應(yīng)用A的package.json中聲明的情臭,這對(duì)于Lib是不對(duì)滴省撑。
細(xì)心的開(kāi)發(fā)者會(huì)發(fā)現(xiàn)赌蔑,在Lib的目錄下也有一個(gè)package.json文件,其缺省內(nèi)容為:
{
"name": "libName",
"version": "0.0.1",
"peerDependencies": {
"@angular/common": "7.0.2",
"@angular/core": "7.0.2",
}
}
我們需要把這個(gè)文件補(bǔ)充完整竟秫,將Lib中用到的其他第三方組件在peerDependencies中引入娃惯,并將Lib的其他屬性也加入。例如:
{
"name": "ligName",
"version": "0.0.1",
"keywords": ["keyword1","keyword2"],
"license": "MIT",
"author": "authorName",
"description": "description",
"peerDependencies": {
"@angular/common": "7.0.2",
"@angular/core": "7.0.2",
"@angular/forms": "7.0.2",
"@angular/router": "7.0.2",
"@angular/cdk": "7.0.2",
"@angular/material": "7.0.2",
"ngx-spinner": "7.0.0",
"ngx-clipboard": "12.0.0",
"ethers": "4.0.27",
"rxjs": "6.3.3"
}
}
同時(shí)肥败,還可以添加一個(gè)README.md文件趾浅,介紹Lib的使用方法。
準(zhǔn)備工作做好之后拙吉,將Lib編譯成產(chǎn)品:
ng build libName --prod
編譯后的文件會(huì)放置在主應(yīng)用A的dist/libName目錄下潮孽。另外創(chuàng)建一個(gè)Angular應(yīng)用B,在此應(yīng)用下執(zhí)行:
npm install 主應(yīng)用A/dist/libName
安裝時(shí)會(huì)對(duì)libName使用的其他第三方庫(kù)給出類似如下的提示:
npm WARN libName@0.0.1 requires a peer of @angular/core@^7.2.0 but none is installed. You must install peer dependencies yourself.
根據(jù)提示筷黔,自行安裝缺少的組件即可。
在應(yīng)用B的package.json中會(huì)看到對(duì)libName的引入:
"libName": "file:../projectnameA/dist/
在應(yīng)用B的package-lock.json文件中加入如下內(nèi)容:
"libName": {
"version": "file:../projectnameA/dist/libName",
"requires": {
"tslib": "^1.9.0"
},
"dependencies": {
"tslib": {
"version": "1.9.3",
"bundled": true
}
}
}
在應(yīng)用B的app.module.ts文件中引入libName:
import { LibNameModule } from 'libName';
...
imports: [
...
LibNameModule,
...
],
...
在應(yīng)用B中可以測(cè)試libName能否正常使用仗颈。
Lib發(fā)布
上述過(guò)程結(jié)束后佛舱,就可以將應(yīng)用發(fā)布到npm上。準(zhǔn)備工作:
- 在npm上注冊(cè)賬號(hào)挨决。
- 在命令行下執(zhí)行:npm adduser请祖,將賬號(hào)添加到本地。
好了脖祈,可以發(fā)布libName了肆捕。進(jìn)入到projectnameA/dist/libName目錄下執(zhí)行:
npm publish
看到了發(fā)布成功提示,還有點(diǎn)小激動(dòng)盖高。進(jìn)入到npm中慎陵,可以看到已經(jīng)發(fā)布成功的libName。
如果想刪除這個(gè)libName喻奥,可以使用如下命令:
npm unpublish libNamet@0.0.1 --force
這里需要特別注意的是:刪除后的libName席纽,在24小時(shí)內(nèi)不能再發(fā)布了,見(jiàn)如下提示:
npm ERR! libName cannot be republished until 24 hours have passed.
總結(jié)
npm為第三方庫(kù)的開(kāi)發(fā)還提供了一些便利的方法撞蚕,如npm link命令润梯。這些都有待我們?cè)诮窈蟮拈_(kāi)發(fā)中摸索和體驗(yàn),以便更好的打磨精品組件甥厦。
附錄
在開(kāi)發(fā)過(guò)程中遇到了幾個(gè)錯(cuò)誤纺铭,現(xiàn)匯總?cè)缦拢?/p>
-
權(quán)限錯(cuò)誤:
npm ERR! publish Failed PUT 403 npm ERR! code E403 npm ERR! You do not have permission to publish "libName". Are you logged in as the correct user? : libName
解決辦法,執(zhí)行: npm adduser
-
libName若注入了其第三方的服務(wù)刀疙,主應(yīng)用調(diào)用時(shí)出現(xiàn)如下錯(cuò)誤:
Error: inject() must be called from an injection context
解決方法舶赔,在主應(yīng)用的angular.json文件中添加:
"projects": { "projectName": { "architect": { "build": { "options": { "preserveSymlinks":true }, }, } } } },
若libName定義了自己的route,需要在主應(yīng)用中注入RouterModule庙洼。