【npm publish package】發佈流程

以前在和小夥伴作一些項目學習的時候常常會寫一些重複的代碼,而後複製粘貼到下一個項目中使用,好比以前寫了 localStoragesessionStorage 等 API 的函數封裝實現。假設項目須要使用這些封裝好的 API 就要本身再複製粘貼一份,假設若是發現其中有可改進或者修改的地方,那麼就須要本身再將這些修改後的文件覆蓋到每個使用過的項目中。node

這樣的方式實在是太費時費力了,還很差管理。後來就想着常用的 npm package 是否是也能夠將本身封裝好包的也放在上面進行管理呢?並且還有版本號能夠選擇不一樣的版本,也解決了須要使用不一樣實現方式版本的問題,若是有修復更新還能夠同步……git

優勢不少我就不一一描述場景了。github

缺點?也有。若是考慮面向大衆,那麼就要開始長期維護代碼。若是不考慮只是本身使用(也不在公司項目中使用)那麼就沒什麼缺點。web

好的,廢話很少說了,下面就開始介紹流程。typescript

01 - 註冊一個 npmjs 帳號

若是要使用 npm publish package 的服務就須要先擁有一個 npmjs 帳號。shell

註冊地址:www.npmjs.comnpm

這個簡單,也很少說了,只要記得帳號密碼就行。json

02 - 初始化包項目

首先創建一個文件夾用於存放包項目,進入該文件夾,npm 命令以當前路徑爲基準。gulp

初始化改文件夾,即 npm package 配置babel

npm init // 初始化 npm 配置
// 過程是以問答式 CLI 方式進行
// Q1:package name: (文件夾名字) | 默認會以文件夾名字命名,固然也能夠自定義包名,但須要遵照 npm 命名規範
// Q2:version: (1.0.0) | 版本號,默認是 1.0.0,具體版本號規則,可參考《語義化版本 2.0.0》
// Q3:description: | 包描述,用於描述這個包的主要功能以及用途
// Q4:entry point: (index.js) | 入口文件,即從那個文件開始執行
// Q5:test command: | 測試命令,用於包測試的命令,能夠後續補充關於測試包的編寫
// Q6:git repository: | 項目的 git 存儲庫地址
// Q7:keywords: | 描述包的關鍵字,用於在 npmjs 上查詢關鍵字
// Q8:author: | 做者名字,可使用 npmjs 名稱、npmjs 註冊郵箱、github 註冊郵箱
// Q9:license: (ISC) | 開源協議,默認 ISC
// Q10:輸出 package.js 內容並詢問 Is this OK? (yes) 默認爲 yes,回車後生成文件
複製代碼

至此,初始化 npm 配置步驟完成,可是並不是爲最終 package.js 文件內容。

03 - 編寫代碼

我在參考了一些開源項目的源碼以及 npm module 裏的信息後。

發現至少須要三個文件夾:dist | src | types

  • dist 包編譯後最終產出文件
  • src 源碼文件
  • types 類型支持文件

入口問題

在開發階段 package.js 中的 main 配置是指向包的執行文件 (index.js) 。而我在開源項目的源碼以及 npm module 裏發現 main 的配置並不是指向 src/index.js 而是指向 dist/index.js

04 - package.js 改造

若是要將包變得與衆多開源 npm module 同樣的話,那麼就須要對 package.js 進行改造了。

package.js 中須要更改/添加如下配置信息

  • main 變動以 dist/ 爲入口的 index.js 文件
  • module 以 dist/ 爲入口的功能模塊文件
  • unpkg 以 dist/ 爲入口的 index.js 文件,非官方字段用於 cdn 服務
  • jsdelivr 與 unpkg 配置相同,非官方字段用於 cdn 服務
  • typings 類型支持文件 types/index.d.ts(大部分 npm 包使用 TypeScript 開發)
  • files 配置所需文件列表 [ "src/*.js", "dist/*.js", "types/*.d.ts" ] 若是須要進行測試運行代碼的話就須要編寫代碼經過配置 test command 來進行代碼的運行和測試了。

05 - 模塊化標準

目前我看到的使用模塊化標準的主要分爲2個流派,一個是 ES6 一個是 TypeScript。構建使用的模塊化打包工具中 rollup 是使用最多的,一部分使用了 gulp

這裏我也是選擇了使用 TypeScript 來進行編寫,因此會以 TypeScript + rollup 爲例。

Rollup 所需包

  • rollup rollup 核心功能
  • @rollup/plugin-buble Convert ES2015 with buble. 將 ES6+ 代碼編譯成 ES2015 標準
  • @rollup/plugin-replace 編譯過程當中動態替換代碼中的內容
  • @rollup/plugin-commonjs commonjs 模塊標準支持
  • @rollup/plugin-node-resolve 編譯過程當中幫助 rollup 查找外部的模塊並支持合併
  • rollup-plugin-flow-no-whitespace 編譯過程當中 將 flow 靜態類型檢查進行忽略
  • rollup-plugin-typescript2 將 TypeScript 轉換成爲 ES6+ 標準

再也不維護的包

  • rollup-plugin-buble
  • rollup-plugin-replace
  • rollup-plugin-commonjs
  • rollup-plugin-node-resolve

額外使用的包

  • @babel/core // babel 的核心包
  • @babel/plugin-syntax-dynamic-import // babel 異步動態 import
  • terser // 代碼的壓縮混淆
  • typescript // 若是使用了 TypeScript

Rollup 的使用

Rollup 的 options

{
  input: { // 輸入配置
    input: resolve('src/index.js'),
    plugins: [] // 使用的插件列表
  },
  output: { // 輸出配置
    file: resolve('dist/web-storage.js'), // 構建文件生成路徑
    format: 'umd', // 構建模塊標準
    name: 'WebStorage', // 導出命名
    env: 'development' || 'production', // 根據控制檯命令環境判斷,如無需則不寫
    transpile: false || true, // 透明的?目前沒看到文檔解釋 <- X | 自定義字段,用於判斷是否須要 buble 插件參與編譯構建
  }
}
複製代碼

Rollup 使用了 Promise 封裝了調用流程,後續操做都很方便的經過 then 的回調函數進行處理。

rollup
.rollup(input) // 輸入配置 input
.then(bundle => bundle.generate(output)) // 輸出配置 output,經過 generate 函數來生成源碼的規格:cjs es min 等
.then(bundle => { console.dir(bundle) }) // generate 函數生成的源碼字符串結果
複製代碼

在拿到生成的源碼字符串後使用 nodejs 的 fs.writeFile 函數來進行寫入生成文件。

06 - 將包 publish 至 npm 上

要將包發佈先要登陸 npm

npm login // 登陸命令
Username: // 輸入註冊時候的用戶名
Password: // 密碼
Email: (this IS public) // 註冊時的郵箱
複製代碼

登陸完成後便可使用 publish 將 package 上傳至 npm 了。

npm publish // publish 時會以 package.js 裏 name 屬性爲包名
// 稍等一段時間,就能夠經過 install 進行安裝使用了。
npm i 包名
複製代碼

若是包有更新代碼,那麼須要更新版本號,不然沒法進行發佈。

07 - 將包從 npm 上刪除

// 須要先登陸
npm unpublish 包名 // 便可將 npm 上的包刪除
複製代碼

error: cannot be republished until 24 hours have passed.

刪除已在 npm 發佈的同名包,須要在24小時後才能從新發布

最後

以上就是在從開發到配置再到發佈的一系列流程了,其實在剛入手嘗試的過程當中仍是踩了很多的坑,好比把一些再也不維護的包和可替換的包都整理出來了。這個過程當中使用了 TypeScript 來實現,也算是實戰了一把,不過代碼仍是有可優化的地方。

目前也在不斷的學習以及使用 TypeScript,難度卻是不算太大,主要仍是習慣和熟練度的問題以及設計/解決思路的問題。

我本身封裝好的 Web Storage API 已經發布到 npm publish 上了。

npm:cat-web-storage

github:cat-web-storage

目前還只是支持 Vue 項目。

  • 計劃支持非 Vue 的普通 web 項目也可使用(開發進行中)。
  • 計劃把 indexedDB API 也集成封裝進去(開發進行中)。
  • ReactJs、AngularJs 有很好的 npm 包了,暫時不考慮支持。
  • npm 包名:cat-web-storage
相關文章
相關標籤/搜索