手把手教你使用Rollup打包並發布自己的工具庫


DevUI是一支兼具設計視角和工程視角的團隊,服務於華為雲DevCloud平台和華為內部數個中后台系統,服務於設計師和前端工程師。
官方網站:devui.design
Ng組件庫:ng-devui(歡迎Star)
官方交流:添加DevUI小助手(devui-official)
DevUIHelper插件:DevUIHelper-LSP(歡迎Star)

前言

隨着前端生態的繁榮,工具庫幾乎是高效開發的必需品,lodash/dayjs/numberal等實用的工具庫相信大家都用過。

我近期在開發Calendar Graph Github提交日歷組件時,發現有很多需要處理顏色的場景,比如判斷一個字符串是否是一個有效的顏色值、hex顏色值和rgb顏色值的互轉等,但沒有找到一個能很好滿足我全部需求的開源庫,所以決定自己造一個輪子。

這就是做ktools工具庫的原因,本文將介紹如何使用Rollup這個輕量的下一代模塊打包器打造自己的TypeScript工具庫。

通過閱讀本文,你將學到:

  1. 如何初始化一個Rollup工程項目
  2. 如何配置Rollup和TypeScript
  3. 如何編寫腳本,構建並發布自己的工具庫到npm倉庫

1 創建並初始化Github項目

做一個開源庫的第一步是創建一個Github(或Gitlab等)代碼倉庫,並進行簡單的初始化,主要包括:

  1. 創建Git提交忽略配置 .gitignore
  2. 創建開源協議聲明 LICENSE
  3. 初始化package.json
  4. 配置TypeScript tsconfig.json
  5. 配置Rollup rollup.config.js

1.1 Git提交忽略配置

為了防止node_modules等自動生成的目錄/文件提交到遠程代碼倉庫,提交忽略是首先要考慮的事情,前期可以簡單配置下即可。

先創建一個.gitignore文件

1 touch .gitignore

 

在新創建的.gitignore文件中增加以下內容:

1 # dependencies
2 /node_modules
3 
4 # compiled output
5 /dist

 

詳細的配置可以參考Github官方文檔: https://docs.github.com/en/free-pro-team@latest/github/using-git/ignoring-files

1.2 創建開源協議聲明 LICENSE

開源協議可以在創建Github倉庫時選擇,也可以創建倉庫之后再加,一般選擇MIT協議。

這里介紹一個創建倉庫之后補加協議的小技巧。主要分成以下幾個步驟:

  1. 在Github倉庫增加一個文件
  2. 輸入LICENSE(注意必須全部大寫)
  3. 選擇協議
  4. 提交

Step 1: 在Github倉庫增加一個文件

在代碼倉庫的目錄結構右上方,有一個Add file下拉框,選擇其中的Create new file選項,進入創建新文件的頁面。

Step 2: 輸入"LICENSE"

在文件名中輸入全大些的LICENSE,這時輸入框右邊會多出來一個按鈕Choose a license template

Step 3: 選擇協議

點擊Choose a license template按鈕,進入選擇協議模板的頁面。

我們在左側目錄選擇MIT License,然后在右側邊欄輸入年份和作者名字,可以看到中間的Copyright (c)后面的年份和作者會相應變化,點擊Review and submit按鈕,即可返回創建文件的頁面,並自動用剛剛選擇的協議內容填充到LICENSE文件中。

Step 4: 提交

點擊創建文件頁面下方的Commit new file即可提交LICENSE文件到代碼倉庫。

提交之后會自動跳轉到LICENSE頁面,效果如下:

1.3 初始化package.json

添加.gitignore/LICENSE這兩個基本的文件之后,下一步就是初始化package.json文件,這是管理依賴包及其版本的包配置文件,前端項目必備。

我們可以使用以下命令創建一個默認的package.json:

1 npm init -y

 

增加-y參數是不想一直按Enter😄

創建好的package.json文件如下:

 1 {
 2   "name": "ktools",
 3   "version": "1.0.0",
 4   "description": "",
 5   "main": "index.js",
 6   "scripts": {
 7     "test": "echo \"Error: no test specified\" && exit 1"
 8   },
 9   "repository": {
10     "type": "git",
11     "url": "git+https://github.com/kagol/ktools.git"
12   },
13   "keywords": [],
14   "author": "",
15   "license": "MIT"
16 }

 

我們可以簡單地修改和完善下。

nameversion分別是包名和版本號,均可后續發布時通過腳本動態修改,不用管。

description描述可以加下:

1 "description": "前端工具庫"

 

main/scripts這些后續在構建部署腳本的章節會細講。

keywords/author可以加下:

1 "keywords": [
2   "toolkit",
3   "rollup",
4   "typescript"
5 ],
6 "author": "Kagol",

 

配置好package.json,后續安裝依賴包時會自動更新該文件,可以非常方便地進行依賴管理。

1.4 配置TypeScript tsconfig.json

TypeScript這種強類型的語言,是對JavaScript很好的補充和增強,目前來看前景很好,必須用起來。

安裝tsc

我們可以使用tsc命令行工具快速創建TypeScript默認配置文件。

先確認下是否安裝tsc,輸入命令:

1 tsc -v

 

出現以下命令說明未安裝:

1 -bash: /usr/local/bin/tsc: No such file or directory

 

可以通過以下命令全局安裝:

1 npm i -g typescript

 

成功安裝之后,再查看下tsc版本:

1 $ tsc -v
2 Version 4.1.2

 

生成tsconfig.json配置文件

可以使用以下快速生成默認的tsconfig.json配置:

1 tsc --init

 

生成的tsconfig.json文件如下(已刪除注釋代碼):

 1 {
 2   "compilerOptions": {
 3     /* Visit https://aka.ms/tsconfig.json to read more about this file */
 4 
 5     /* Basic Options */
 6     "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
 7     "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
 8 
 9     /* Strict Type-Checking Options */
10     "strict": true,                           /* Enable all strict type-checking options. */
11 
12     /* Module Resolution Options */
13     "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
14 
15     /* Advanced Options */
16     "skipLibCheck": true,                     /* Skip type checking of declaration files. */
17     "forceConsistentCasingInFileNames": true  /* Disallow inconsistently-cased references to the same file. */
18   }
19 }

 

默認的配置其實已經夠用,我們不做修改,后續可以根據需要刪減配置。

1.5 配置Rollup rollup.config.js

初始化工程的最后一步就是配置Rollup,先創建一個Rollup配置文件,沒有Rollup CLI工具不支持初始化配置文件,只能手動創建:

1 touch rollup.config.js

 

然后在rollup.config.js中增加以下內容:

 1 import resolve from 'rollup-plugin-node-resolve';
 2 import commonjs from 'rollup-plugin-commonjs';
 3 import typescript from 'rollup-plugin-typescript';
 4 import pkg from './package.json';
 5 
 6 export default {
 7   input: 'src/index.ts', // 打包入口
 8   output: { // 打包出口
 9     file: pkg.browser, // 最終打包出來的文件路徑和文件名,這里是在package.json的browser: 'dist/index.js'字段中配置的
10     format: 'umd', // umd是兼容amd/cjs/iife的通用打包格式,適合瀏覽器
11   },
12   plugins: [ // 打包插件
13     resolve(), // 查找和打包node_modules中的第三方模塊
14     commonjs(), // 將 CommonJS 轉換成 ES2015 模塊供 Rollup 處理
15     typescript() // 解析TypeScript
16   ]
17 };

 

package.json中配置browser字段:

1 "browser": "dist/index.ts",

 

安裝Rollup和TypeScript相關依賴:

1 npm i -D rollup typescript tslib rollup-plugin-node-resolve rollup-plugin-commonjs rollup-plugin-typescript

 

 

注意tslib這個依賴庫也是必需的,因為rollup-plugin-typescript插件依賴了該庫。

Rollup配置文件每個配置項的具體含義可以參考:https://www.rollupjs.com/guide/big-list-of-options

Rollup可用插件列表可以參考:https://github.com/rollup/plugins

2 編寫工具庫源碼

有了以上的初始工程,就可以正式開始寫工具方法源碼。

2.1 走通流程

先寫一個demo,跑通編寫源碼構建打包引入使用的流程。

編寫源碼

咱們的入口文件配置在了src/index.ts中,所以需要先創建該文件:

1 mkdir src
2 touch src/index.ts

 

然后在該文件中編寫一些代碼測試下打包是否正常:

1 console.log('hello ktools!');

 

構建打包

在命令行中輸入以下命令對項目進行打包:

1 rollup -c

 

執行完之后會在dist目錄生成打包文件index.js,內容如下:

1 (function (factory) {
2     typeof define === 'function' && define.amd ? define(factory) :
3     factory();
4 }((function () { 'use strict';
5 
6     console.log('hello ktools!');
7 
8 })));

 

引入使用

這時我們可以隨便在一個Vue/React/Angular項目下引入這個空殼工具庫,看下是否正常:

比如在 Vue CLI 工程的src/main.js中增加以下代碼

 1 import Vue from 'vue';
 2 import App from './App.vue';
 3 import router from './router';
 4 import store from './store';
 5 
 6 import ktools from '../index'; // 新增加的代碼,將在瀏覽器控制台輸出"hello ktools!"
 7 
 8 Vue.config.productionTip = false;
 9 
10 new Vue({
11   router,
12   store,
13   render: h => h(App),
14 }).$mount('#app');

 

或者在 Angular CLI 工程中的src/main.ts文件中增加:

 1 import { enableProdMode } from '@angular/core';
 2 import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
 3 
 4 import { AppModule } from './app/app.module';
 5 import { environment } from './environments/environment';
 6 
 7 import ktools from '../index';
 8 console.log('ktools:', ktools); // 必須加這個才能輸出"hello ktools!",因為沒有導出任何東西,所以打印出來的ktools是一個空對象
 9 
10 if (environment.production) {
11   enableProdMode();
12 }
13 
14 platformBrowserDynamic().bootstrapModule(AppModule)
15   .catch(err => console.error(err));

 

2.2 編寫工具方法

流程走通之后,就可以正式編寫工具方法。

我們編寫一個判斷一個字符串是否是一個有效的hex十六進制顏色值的工具方法:isColor。

先創建src/is-color.ts文件:

1 touch src/is-color.ts

 

增加以下內容:

/**
 * 判斷字符串是否是十六進制的顏色值
 * @param value 
 */
const isColor = function(value: string): boolean {
  return /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.test(value);
}

export default isColor;

 

然后在index.ts入口文件中增加引入is-color.ts文件的代碼:

1 import isColor from './is-color';
2 
3 export {
4   isColor,
5 };

 

重新執行rollup -c進行構建,生成的dist/index.js如下:

 1 (function (global, factory) {
 2   typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
 3   typeof define === 'function' && define.amd ? define(['exports'], factory) :
 4   (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ktools = {}));
 5 }(this, (function (exports) { 'use strict';
 6 
 7   /**
 8    * 判斷字符串是否是十六進制的顏色值
 9    * @param value
10    */
11   var isColor = function (value) {
12       return /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.test(value);
13   };
14 
15   exports.isColor = isColor;
16 
17   Object.defineProperty(exports, '__esModule', { value: true });
18 
19 })));

 

再到項目中引入:

1 import { isColor } from '../index';
2 console.log('isColor #c6e48b:', isColor('#c6e48b')); // isColor #c6e48b: true
3 console.log('isColor #c6e48:', isColor('#c6e48')); // isColor #c6e48: false

 

一切正常!

3 增加構建發布腳本

到這里其實我們的工具庫ktools已經完成了90%,還差最后一步,就是發布到npm倉庫,可以手工發布。

3.1 手工發布

將package.json文件拷貝到dist目錄,修改version為本次發布的版本號,比如0.0.1,然后進入該目錄:

1 cd dist

 

執行以下命令即可將我們的ktools工具庫發布到npm倉庫:

1 npm publish

 

帶着歡呼雀躍的心情等待發布成功,結果報錯,以下是報錯信息:

 1 $ npm publish
 2 npm notice
 3 npm notice 📦  ktools@0.0.1
 4 npm notice === Tarball Contents ===
 5 npm notice 315B index.html
 6 npm notice 634B index.js
 7 npm notice 691B package.json
 8 npm notice === Tarball Details ===
 9 npm notice name:          ktools
10 npm notice version:       0.0.1
11 npm notice package size:  1.1 kB
12 npm notice unpacked size: 1.6 kB
13 npm notice shasum:        35c3501906443ff46be51c2747c07e73136bf85c
14 npm notice integrity:     sha512-SZTM0msux0+Pt[...]IWmV6Gx5Tz41w==
15 npm notice total files:   3
16 npm notice
17 npm ERR! code E403
18 npm ERR! 403 403 Forbidden - PUT http://registry.npmjs.org/ktools - Package name too similar to existing packages; try renaming your package to '@kagol/ktools' and publishing with 'npm publish --access=public' instead
19 npm ERR! 403 In most cases, you or one of your dependencies are requesting
20 npm ERR! 403 a package version that is forbidden by your security policy.
21 
22 npm ERR! A complete log of this run can be found in:
23 npm ERR!     /Users/kagol/.npm/_logs/2020-12-05T05_42_31_632Z-debug.log

 

看提示似乎是包名重復[捂臉][苦澀],提示里還很友好地建議先重命名包名為@kagol/ktools,然后再發布。

那我們就按照提示嘗試下改個名字吧,加個scope:

1 "name": "ktools"
2 
3 ->
4 
5 "name": "@kagol/ktools",

 

改完名字重新發布,成功啦!

 1 $ npm publish
 2 npm notice
 3 npm notice 📦  @kagol/ktools@0.0.1
 4 npm notice === Tarball Contents ===
 5 npm notice 22.0kB index.js
 6 npm notice 1.2kB  package.json
 7 npm notice 1.8kB  README.md
 8 npm notice === Tarball Details ===
 9 npm notice name:          @kagol/ktools
10 npm notice version:       0.0.1
11 npm notice package size:  6.9 kB
12 npm notice unpacked size: 25.0 kB
13 npm notice shasum:        d85994aecc86160862cef4f0033e5bfdaa136072
14 npm notice integrity:     sha512-UEDEJEsMSXcMg[...]yY4KsXp4mXIBA==
15 npm notice total files:   3
16 npm notice
17 + @kagol/ktools@0.0.1

 

這時可以在項目中正式安裝並引入使用。

先安裝:

1 npm i @kagol/ktools

 

使用方式和之前的一樣,只是需要把引入方式改了:

1 import { isColor } from '@kagol/ktools';
2 console.log('isColor #c6e48b:', isColor('#c6e48b')); // isColor #c6e48b: true
3 console.log('isColor #c6e48:', isColor('#c6e48')); // isColor #c6e48: false

 

3.2 通過腳本發布

每次發布還要將文件拷貝來拷貝去,又要修改包名,又要改版本號,很麻煩,可以編寫腳本將這個過程自動化。

主要分以下步驟:

  1. 拷貝文件
  2. 修改文件
  3. 發布

Step 1: 拷貝文件

在package.json的scripts中增加拷貝文件的腳本:

1 "copy": "cp package.json README.md dist",

 

Step 2: 修改文件

新建scripts/publish.js文件,增加以下內容:

 1 const path = require('path');
 2 const shelljs = require('shelljs');
 3 const program = require('commander');
 4 
 5 const targetFile = path.resolve(__dirname, '../dist/package.json');
 6 const packagejson = require(targetFile);
 7 const currentVersion = packagejson.version;
 8 const versionArr = currentVersion.split('.');
 9 const [mainVersion, subVersion, phaseVersion] = versionArr;
10 
11 // 默認版本號
12 const defaultVersion = `${mainVersion}.${subVersion}.${+phaseVersion+1}`;
13 
14 let newVersion = defaultVersion;
15 
16 // 從命令行參數中取版本號
17 program
18   .option('-v, --versions <type>', 'Add release version number', defaultVersion);
19 
20 program.parse(process.argv);
21 
22 if (program.versions) {
23   newVersion = program.versions;
24 }
25 
26 function publish() {
27   shelljs.sed('-i', '"name": "ktools"', '"name": "@kagol/ktools"', targetFile); // 修改包名
28   shelljs.sed('-i', `"version": "${currentVersion}"`, `"version": "${newVersion}"`, targetFile); // 修改版本號
29   shelljs.cd('dist');
30   shelljs.exec('npm publish'); // 發布
31 }
32 
33 publish();

 

這里最核心的兩步:

  1. 修改包名
  2. 獲取正確的版本號並修改

其中修改文件使用shelljs庫,獲取版本號參數使用了TJ大神的commander工具。

需要提前安裝這兩個依賴庫:

1 npm i -D shelljs commander

 

另外需要在package.json中增加構建的腳本命令:

1 "build": "rollup -c && npm run copy",

 

Step 3: 發布

發布的步驟比較簡單,已經放在publish.js腳本文件中。

每次發布只需要依次運行以下命令即可:

1 npm run build
2 npm run publish -- -v 0.0.2

 

后續可以考慮將其集成到流水線,實現完全的自動化部署,這里可以參考我之前寫的一片文章:大廠是如何用DevCloud流水線實現自動化部署Web應用的?

4 小結

本文詳細地介紹了使用Rollup+TypeScript打造一個開源工具庫的流程和步驟,並介紹如何配置Rollup和TypeScript,如何編寫部署腳本自動化發布工具庫到npm倉庫。希望大家喜歡,並歡迎給個Star🌟鼓勵,以下是ktools工具庫的源碼地址:

https://github.com/kagol/ktools

也歡迎點亮我們的DevUI組件庫的星星🌟

https://github.com/DevCloudFE/ng-devui

加入我們

我們是DevUI團隊,歡迎來這里和我們一起打造優雅高效的人機設計/研發體系。招聘郵箱:muyang2@huawei.com。

文/DevUI Kagol

往期文章推薦

《前端有了這兩樣神器,再也不用追着后台要接口啦》

《使用Git,10件你可能需要“反悔”的事》

《手把手教你使用Vue/React/Angular三大框架開發Pagination分頁組件》

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM