Angular第三方庫(kù)開(kāi)發(fā)實(shí)踐

從接觸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)用如下改變:

  1. 在主應(yīng)用A下創(chuàng)建 projects/libName 目錄贞让,并將Lib的相關(guān)文件放于此;

  2. 在 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舅桩。

  3. 在 package.json 文件中添加 ng-packagr 依賴;

  4. 在 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)備工作:

  1. npm上注冊(cè)賬號(hào)挨决。
  2. 在命令行下執(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>

  1. 權(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

  2. 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
                    },
                },
            }
        }
      }
    },
    
  3. 若libName定義了自己的route,需要在主應(yīng)用中注入RouterModule庙洼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末顿痪,一起剝皮案震驚了整個(gè)濱河市镊辕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蚁袭,老刑警劉巖征懈,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異揩悄,居然都是意外死亡卖哎,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)删性,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)亏娜,“玉大人,你說(shuō)我怎么就攤上這事蹬挺∥兀” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵巴帮,是天一觀的道長(zhǎng)溯泣。 經(jīng)常有香客問(wèn)我,道長(zhǎng)榕茧,這世上最難降的妖魔是什么垃沦? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮用押,結(jié)果婚禮上肢簿,老公的妹妹穿的比我還像新娘。我一直安慰自己蜻拨,他們只是感情好池充,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著官觅,像睡著了一般纵菌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上休涤,一...
    開(kāi)封第一講書(shū)人閱讀 52,785評(píng)論 1 314
  • 那天咱圆,我揣著相機(jī)與錄音,去河邊找鬼功氨。 笑死序苏,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的捷凄。 我是一名探鬼主播忱详,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼跺涤!你這毒婦竟也來(lái)了匈睁?” 一聲冷哼從身側(cè)響起监透,我...
    開(kāi)封第一講書(shū)人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎航唆,沒(méi)想到半個(gè)月后胀蛮,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡糯钙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年粪狼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片任岸。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡再榄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出享潜,到底是詐尸還是另有隱情困鸥,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布剑按,位于F島的核電站窝革,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏吕座。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一瘪板、第九天 我趴在偏房一處隱蔽的房頂上張望吴趴。 院中可真熱鬧,春花似錦侮攀、人聲如沸锣枝。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)撇叁。三九已至,卻和暖如春畦贸,著一層夾襖步出監(jiān)牢的瞬間陨闹,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工薄坏, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留趋厉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓胶坠,卻偏偏與公主長(zhǎng)得像君账,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子沈善,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361