angular第三方包開發(fā)整理(小結(jié))
近日筆者維護自己的幾個無名小repo時,發(fā)覺想要創(chuàng)作一個第三方angular包,著實有一些不難但易亂的小問題,故作此文總結(jié)。本文將完成以下內(nèi)容:
- 從空白開始搭建一個基于angular的第三方包
- 在本地測試待發(fā)布的包
- 在npm或yarn發(fā)布包中指定內(nèi)容
- 在普通angular應(yīng)用中引入并使用發(fā)布的包
基本項目搭建
一般的angular app使用angular-cli創(chuàng)建,直接ng new name搞定,生成的項目把webpack、AOT、dev server等細節(jié)都隱藏了,還支持各種參數(shù)來配置測試和sass等,使用起來直接npm run start、npm run build,可以說是非常傻瓜了,跳過了學(xué)習(xí)webpack等的許多大坑。
不過,如果是要搭建angular第三方包,預(yù)編譯樣式和打包部署這些一般就用不著了,取而代之的要熟悉npm(yarn)、tsconfig。
初始化
項目搭建命令如下:
mkdir my-ng-lib cd my-ng-lib yarn init
一路回車(實際情況中還是要編輯好包的基本信息)最終得到一個package.json,然后vscode打開:
初始化npm包
依賴
作為angular的第三方包,首先需要安裝如下依賴:
依賴安裝
其中typescript指定了版本是為了和當前angular-cli使用的版本保持一致,實際可能不必要這么做。
現(xiàn)在安裝了開發(fā)時要用到的包,但這些包并不用在發(fā)布以后,實際上發(fā)布的時候我們想要的只是發(fā)布自己寫的代碼,而不是依賴的代碼,這需要在package.json中配置peerDependencies作為前置依賴,但包本身不會實際安裝這些依賴,實際的包應(yīng)該由應(yīng)用項目來安裝?,F(xiàn)在把peerDependencies添加進package.json:
"peerDependencies": { "@angular/common": ">=5.0.0", "@angular/core": ">=5.0.0", "rxjs": ">=5.0.0" }
項目編寫
基本項目搭建好后,我們應(yīng)該只有package.json、node_modules和一個lock文件在項目中,現(xiàn)在要加上真正的項目代碼了。
無論這個包是用來實現(xiàn)什么目的的,作為一個第三方包,都應(yīng)該要導(dǎo)出自己的功能以讓其他項目引入使用,所以在項目根目錄首先要有一個index.js文件,而我們要開發(fā)的是基于angular的TypeScript包,使用的自然是index.ts了,內(nèi)容就是各種export導(dǎo)出類型、接口、方法等。作為示例這里只導(dǎo)出一個常量:
export const myNgLib: string = 'Hello, thie is my angular 3rd part lib';
為了支持TypeScript我們還需要一個tsconfig.json:
{ "compilerOptions": { "baseUrl": ".", // 基于哪個目錄編譯ts "declaration": true, // 是否生成聲明文件即*.d.ts文件,有了它才有TS的代碼提示 "experimentalDecorators": true, // 用于支持TS裝飾器如angular中的 @NgModule({}) 之類 "emitDecoratorMetadata": true, // 用于支持TS裝飾器如angular中的 @NgModule({}) 之類 "module": "commonjs", // 模塊化形式 "moduleResolution": "node", // 模塊化形式 "rootDir": ".", // 以哪個目錄為根 "lib": ["es2015", "dom"], // 支持編譯的內(nèi)置庫 "skipDefaultLibCheck": true, // 是否跳過內(nèi)置庫檢查 "skipLibCheck": true, // 跳過庫檢查 "target": "es5", // 編譯目標版本 "suppressImplicitAnyIndexErrors": true, // 幾個檢查代碼的規(guī)則 "strictNullChecks": true, // 幾個檢查代碼的規(guī)則 "noImplicitAny": true, // 幾個檢查代碼的規(guī)則 "sourceMap": true, // 是否生成 .js.map "removeComments": true, // 移除注釋 "noFallthroughCasesInSwitch": true // 幾個檢查代碼的規(guī)則 }, "exclude": [ // 編譯時排除以下內(nèi)容 "node_modules", "*.d.ts", "**/*.d.ts" ] }
其中的規(guī)則各有各效果,有些為了確定編譯路徑,有些為了語法檢查,有些為了輸出聲明,還有排除規(guī)則等,現(xiàn)在可以tsc看看效果了,不過要先把tsc添加到package.json的scripts中:
"scripts": { "tsc": "tsc" }
編譯得到.js、js.map、.d.ts
發(fā)布
完美,這么厲害的包,接下來趕緊發(fā)布它。發(fā)布命令是
yarn publish
不過在此之前,要準備幾件事:
npm賬號
發(fā)布之前自然得先有npm賬號,添加了就可以,最后用npm whoami確認身份。
包的基本信息
也就是要完善package.json,讓全網(wǎng)知道這么厲害的包是我們開發(fā)的,包括開源許可、包名、作者、版本號等,最重要直接影響發(fā)布的是版本號。
選擇性發(fā)布
基于angular的第三方包區(qū)別與普通的js包最大的地方就在于,不能直接把整個包都發(fā)布到npm,這樣會導(dǎo)致奇怪錯誤,原因在于.ts文件,實際上需要發(fā)布的只是.js、.js.map、.d.ts這三種類型的文件就夠了。
因為在其他項目中不一定會使用TypeScript,即使用了也不會刻意包含node_modules目錄,也就是說其他項目只管使用,編譯的活由我們得包自己來做,相反要是我們還發(fā)布多余的.ts文件,只會導(dǎo)致錯誤。
為了做到選擇性發(fā)布,需要一個.npmignore文件,和.gitignore配合用來忽略上傳的文件,一般這些編譯輸出我們會添加在.gitignore中,若項目不存在.npmignore,發(fā)布到npm時也會使用.gitignore,這不是我們想要的,所以需要再創(chuàng)建這個.npmignore來忽略.ts文件而包含編譯輸出:
node_modules yarn-error.log tsconfig.json .gitignore .npmignore yarn.lock *.ts !*.d.ts
現(xiàn)在我們的項目看起來是這樣的:
待發(fā)布項目
使用yarn pack命令得到本地打包看看效果如何:
本地打包
看起來非常完美,該有的都有了,不該有的都忽略了,那就可以發(fā)布了,不過這里就不發(fā)布這個沒什么用處的包了 : )
打包至此完成,現(xiàn)在看看用起來怎么樣。
本地測試
angular的第三方包要做本地測試的話,與普通的包比有一點不足,就是用不了npm link,這會導(dǎo)致錯誤,特別是在第三方包使用到依賴注入的情況下,原因是運行時實際是在兩個angular環(huán)境下,再進一步說是因為第三方包依賴的是自己的node_modules,解決辦法也很粗暴,刪掉第三方包的node_modules即可,不過這代價顯然有點大。找遍GitHub發(fā)現(xiàn)的另一個辦法是配合--preserve-symlinks參數(shù),不過可能是筆者使用姿勢不對一直沒效果。
最后筆者自己的曲線救國辦法是手動寫package.json的scripts,本地測試步驟是:
- 執(zhí)行 yarn pack得到本地打包
- 解壓到測試項目的node_modules中假裝是安裝的項目
- 測試項目中像使用普通安裝包一樣使用這個直接復(fù)制進來的包
參考腳本如下:
"scripts": { "prepublish": "npm run clean && tsc", // 清理并編譯 "clean": "rimraf index.js index.js.map index.d.ts src/**/*.js src/**/*.js.map src/**/*.d.ts linktest.tgz", // 清理編譯文件 "link": "npm run pack && tar -zxf linktest.tgz && rimraf ../lib-test-app/node_modules/my-ng-lib && mv package ../lib-test-app/node_modules/my-ng-lib", // 打包后解壓并移動到測試項目node_modules中 "pack": "npm run prepublish && yarn pack --filename linktest.tgz" // 執(zhí)行編譯并打包 }
總結(jié)
- 發(fā)布基于angular的第三方包的兩個難點:一是如何處理好TypeScript的編譯,二是如何處理好angular運行上下文。
- 本文的命令均使用yarn完成,npm版本命令大同小異均有其對應(yīng)命令,且發(fā)布的包都是在npm托管。
- 另外本文僅涉及發(fā)布最基本的基于angular的第三方包,包的實際功能方面沒有做深入。其實對于不同功能的第三方包,仍有需要學(xué)習(xí)的內(nèi)容。
參考資料:
How to create an Angular component library, and how to consume it using SystemJs or Webpack
stories linked library
npm link doesn't work with 1.5.4 version
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解在Angular4中使用ng2-baidu-map的方法
這篇文章主要介紹了在Angular4中使用ng2-baidu-map的方法,本文分步驟給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-06-06Angular 13+開發(fā)模式慢的原因及構(gòu)建性能優(yōu)化解析
這篇文章主要為大家介紹了Angular 13+開發(fā)模式慢的原因及構(gòu)建性能優(yōu)化解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12Angular搜索 過濾 批量刪除 添加 表單驗證功能集錦(實例代碼)
這篇文章主要介紹了Angular搜索 過濾 批量刪除 添加 表單驗證功能集錦(實例代碼),需要的朋友可以參考下2017-10-10Angular設(shè)置title信息解決SEO方面存在問題
爬蟲在檢索seo信息的時候會讀不了js給其賦的值,導(dǎo)致搜索引擎收錄不了或者收錄了無效的信息,下面本文給大家介紹Angular設(shè)置title信息解決SEO方面存在問題,需要的朋友可以參考下2016-08-08使用JavaScript的AngularJS庫編寫hello world的方法
這篇文章主要介紹了使用JavaScript的AngularJS庫編寫hello world的方法,AngularJS是一款高人氣的JavaScript庫,需要的朋友可以參考下2015-06-06AngularJS使用攔截器實現(xiàn)的loading功能完整實例
這篇文章主要介紹了AngularJS使用攔截器實現(xiàn)的loading功能,結(jié)合完整實例形式分析了AngularJS攔截器的設(shè)置、調(diào)用及l(fā)oading功能實現(xiàn)技巧,需要的朋友可以參考下2017-05-05AngularJS實現(xiàn)的省市二級聯(lián)動功能示例【可對選項實現(xiàn)增刪】
這篇文章主要介紹了AngularJS實現(xiàn)的省市二級聯(lián)動功能,涉及事件監(jiān)聽、響應(yīng)及頁面元素動態(tài)操作相關(guān)技巧,此外還具備對選項進行增刪的功能,需要的朋友可以參考下2017-10-10