前言
最近在寫一個前端工具庫,剛開始用webpack搭建,但是偶然間發(fā)現(xiàn)rollup的介紹,發(fā)現(xiàn)rollop更滿足我的需求。這篇文章介紹了用rollup搭建一個簡單版的js工具庫。
需求
代碼層面
1.編寫:支持ES6語法(支持異步) 對傳參有要求
2.提交:提交代碼有規(guī)范
3.測試:代碼測試-單元測試
4.注釋:生成相應(yīng)的文檔說明
功能層面:
1.使用:主流瀏覽器使用;eg:chrome,firefox
2.js方法
3.引用:會引用了其它的庫
顯然,在打包時,我們第一時間會想到的就是webpack,但是我在實(shí)際中發(fā)現(xiàn)有更適合我的需求的打包框架,就是rollup。下面我們來看看他們的區(qū)別。
webpack VS Rollup
1.入口文件
webpack和rollup都需要一個配置文件,來指定入口,輸出,插件等
| webpack | rollup | |
|---|---|---|
| 相對路徑 | 不支持,使用path.resolve | 支持 |
這只是其中一個簡單的區(qū)別,我們再來看看以下幾個區(qū)別
2.死代碼消除(tree-shaking)
當(dāng)我們打開一個網(wǎng)頁,如圖,只有頁面加載完相關(guān)資源(eg:js,圖片)頁面才會顯示出來。如果我們需要加載的資源體積越小,當(dāng)然我們打開頁面的時間就會縮短。如何縮小我們需要資源的大小呢,tree-shaking就是其中一種方法,通過它減少在項(xiàng)目里沒有使用的代碼,來減少我們打開頁面的時間。

我們再來看看對于相同的代碼webpack和rollup打包的結(jié)果
| 相同的代碼 | webpack | rollup |
|---|---|---|
| 執(zhí)行時間 | 71ms | 17ms |
| 文件大小 | 389KB | 262KB |
主要原因就是rollup使用了tree-shaking,利用了es6模塊特性,促使了mudle進(jìn)行靜態(tài)分析,在uglify階段刪除了無用代碼。
至于什么是es6規(guī)范呢,如下:
- 只能作為模塊頂層的語句出現(xiàn)(import和export語句只能出現(xiàn)在代碼頂層)
- import的模塊只能是字符串變量,不能使用字符串和變量
- 引入模塊不能再進(jìn)行修改
// 情況1
let str = '只能作為模塊頂層的語句出現(xiàn)';
import { sum} from 'util' ;
// 情況2
import { 's'+'um'} from 'util';
//情況3
import {sum} from 'util'
sum=1;// Syntax Error : 'a' is read-only;
3.實(shí)時加載
webpack:使用webpack-dev-server插件
rollup:rollup-plugin-serve+rollup-plugin-livereload 。
webpack實(shí)時加載的定制型更強(qiáng),比如添加中間件,指定運(yùn)行使用的文件。
更多的比較可去查看。
總結(jié)一下:
webpack
生態(tài)圈豐富 (文檔更完整,插件庫豐富)
拆分代碼,按需加載 利用插件支持tree-shaking(webpack 2以上)
webpack會產(chǎn)生很多額外的代碼,
打包文件較大 執(zhí)行較慢 可讀性弱
適用涉及到css html 靜態(tài)資源處理 復(fù)雜的代碼拆分合并或者 應(yīng)用
rollup
插件生態(tài)相對較弱 把所有資源放在同一個地方,一次性加載 利用tree-shaking縮小包體積
一般不會產(chǎn)生額外的代碼,執(zhí)行更快,可讀性更強(qiáng)
rollup多適用于基礎(chǔ)庫
我們再來梳理一下我們的需求:
1.只需要實(shí)現(xiàn)js常用方法 --rollup
2.語法:支持類型 --TypeScript
3.規(guī)范:編碼規(guī)范 --ESLint&Prettier
4.提交:提交有要求 --Husky&commitlint
5.質(zhì)量:測試用例 --jest
下面開始我們的項(xiàng)目搭建啦
初始化項(xiàng)目
a.創(chuàng)建文件夾 rollup-demo
b.npm init -y 初始化
c.安裝 rollup和每次打包清除dist目錄插件 npm i rollup rollup-plugin-clear -D
d.創(chuàng)建入口文件src/main.js
function fun1(){
function fun2(){
return 'no'
}
return 'yes'
}
fun1()
console.log(fun1())
function Useless(){
console.log(1111)
}
e.在根目錄下創(chuàng)建rollup.config.js
'use strict';
import clear from 'rollup-plugin-clear';
export default {
input: 'src/main.ts',
output: {
file: 'dist/bundle.js',
format: 'umd', //打包文件格式
},
plugins: [
clear({targets: ['dist']}), //清除dist目錄
],
};
f.在package下添加命令
"build": "rollup -c rollup.config.js",
執(zhí)行npm run build
一個簡單的rollup打包項(xiàng)目完成了。
使用ts
為什么使用ts呢,ts是靜態(tài)類型,js是動態(tài)類型;靜態(tài)類型對閱讀代碼是友好的;同時IDE提供的大量便捷支持和TS本身的語法檢查和代碼提示自動補(bǔ)全讓開發(fā)者提高效率,方便重構(gòu)等。當(dāng)然,TypeScript 只是為 JavaScript 中本身就存在的使用方式提供了對應(yīng)的類型標(biāo)注,所有在 TypeScript 中能夠使用的開發(fā)模式,在 JavaScript 中一定是本身就存在的。
a. 安裝依賴庫
typescript:編譯 typescript 語法的基礎(chǔ)庫
rollup-plugin-typescript2:結(jié)合 rollup 編譯 typescript 的 plugins
npm i rollup-plugin-typescript2 typescript -D
b. rollup.config.js配置
rollup.config.js
import ts from "rollup-plugin-typescript2";
export default {
input: "./src/main.ts",
plugins: [
ts({
useTsconfigDeclarationDir: true
}),
]
}
useTsconfigDeclarationDir:指定生成聲明文件存放目錄。
c.配置 tsconfig.json
{
"compilerOptions": {
"target": "es5",// 編譯目標(biāo)
"module":"es2015",// 模塊類型
"lib": ["es2015", "es2016", "es2017"],// 導(dǎo)入庫類型定義
"strict": true,// 嚴(yán)格模式
"sourceMap": true,// 生成定義sourceMap
"strictNullChecks": true, // 不允許把null、undefined賦值給其他類型的變量
"declaration": true,// 生成定義文件
"declarationDir": "dist/types",//類型聲明文件位置 自動創(chuàng)建聲明文件(.d.ts)
"noUnusedLocals": true, // 未使用變量報錯
"outDir": "./dist", // 編譯輸出目錄
"typeRoots": [ //typeRoots 用來指定默認(rèn)的類型聲明文件查找路徑,默認(rèn)為 node_modules/@types
"node_modules/@types"
]
}
}
** ESLint & Prettier**
ESLint 對應(yīng)的是代碼語法質(zhì)量規(guī)則,Prettier 對應(yīng)的是格式化規(guī)則。**
ESLint 是一個插件化的 javascript 代碼檢測工具,它可以用于檢查常見的 JavaScript 代碼錯誤,也可以進(jìn)行代碼風(fēng)格檢查,這樣我們就可以根據(jù)自己的喜好指定一套 ESLint 配置,然后應(yīng)用到所編寫的項(xiàng)目上,從而實(shí)現(xiàn)輔助編碼規(guī)范的執(zhí)行,有效控制項(xiàng)目代碼的質(zhì)量。
prettier 是代碼格式化工具。它通過解析代碼并使用自己的規(guī)則重新打印它,并考慮最大行長來強(qiáng)制執(zhí)行一致的樣式,并在必要時包裝代碼。支持 JavaScript、 Flow、 TypeScript、 CSS、 SCSS、 Less、 JSX、 Vue、 GraphQL、 JSON、 Markdown 等語言,可以結(jié)合 ESLint 和 Prettier,檢測代碼中潛在問題的同時,還能統(tǒng)一團(tuán)隊代碼風(fēng)格,從而促使寫出高質(zhì)量代碼,來提升工作效率。
a.安裝依賴
- eslint:eslint 核心庫,負(fù)責(zé)整個 eslint 的調(diào)度工作
- @typescript-eslint/parser:ESLint的解析器,用于解析typescript,從而檢查和規(guī)范Typescript代碼
- @typescript-eslint/eslint-plugin:ESLint插件,包含了各類定義好的檢測 typescript 代碼的規(guī)范
- prettier:prettier 核心庫
- eslint-config-prettier:解決 ESLint 中的樣式規(guī)范和 prettier 中樣式規(guī)范的沖突,以 prettier 的樣式規(guī)范為準(zhǔn),使 ESLint 中的樣式規(guī)范自動失效
- eslint-plugin-prettier:將 prettier 的規(guī)范作為 ESLint 規(guī)范來使用
npm i eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin prettier eslint-config-prettier eslint-plugin-prettier -D
b.創(chuàng)建 .eslintrc.js
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2019,
sourceType: 'module',
},
extends: [
'plugin:@typescript-eslint/recommended',
'prettier/@typescript-eslint',
'plugin:prettier/recommended',
],
env: {
es6: true,
node: true,
},
rules: {
"no-undef": "error",
"eqeqeq": "error",
"no-console": "error"
},
};
c.創(chuàng)建.prettierrc.js
module.exports = {
arrowParens: 'avoid',
bracketSpacing: false,
endOfLine: 'lf',
jsxBracketSameLine: false,
jsxSingleQuote: false,
printWidth: 100,
proseWrap: 'preserve',
semi: true,
singleQuote: true,
// tabWidth: 4,
useTabs: false,
trailingComma: 'es5',
};
提交代碼規(guī)范 Husky & lint-staged & Commitlint
**Husky **是一個 git hook 輔助工具,能夠在 git 文件狀態(tài)變更時,執(zhí)行一些操作。husky能夠防止不規(guī)范代碼被commit、push、merge等等
**lint-staged **能監(jiān)測到所有提交變動的文件,對其執(zhí)行一系列命令,如 prettier 對不符合規(guī)范的代碼進(jìn)行 fix。
**commitlint **顧名思義就是進(jìn)行提交代碼 git commit -m 'xxxxx' 時,檢查提交記錄 message 的,commitlint 能夠抵擋住不符合規(guī)范的 message 記錄,如 git commit -m 'add eslint' 這就是一個不符合規(guī)范的 commit ,因?yàn)樗麤]有加上對應(yīng)的 commit type 類別,add eslint 對應(yīng)的類別應(yīng)該是 chore (構(gòu)建過程或輔助工具的變動)
**a.安裝依賴 **
- husky:git hook 輔助工具
- lint-staged:監(jiān)測變動文件并執(zhí)行命令
- @commitlint/cli:commitlint 核心工具庫
- @commitlint/config-conventional:一些 commitlint 規(guī)則預(yù)設(shè)
npm i husky lint-staged -D
npm i @commitlint/cli @commitlint/config-conventional -D
b.創(chuàng)建huskyrc.js
module.exports = {
hooks: {
'commit-msg': 'commitlint -e $HUSKY_GIT_PARAMS',
'pre-commit': 'lint-staged',// 在 pre-commit commit 前的階段,執(zhí)行 lint-staged 中的命令。
},
};
c.創(chuàng)建 lint-staged.config.js
module.exports = {
'{src,test}/**/*.ts': [
'npm run lint',
'git add'
]
};
d.創(chuàng)建commitlint.config.js
module.exports = {
extends: [
"@commitlint/config-conventional"
],
rules: {// 自定義配置
'subject-case': [2, 'always', ['upper-case']]
}
};
**jest測試
**Jest 是用來創(chuàng)建、執(zhí)行和構(gòu)建測試用例的一個 JavaScript 測試 庫??梢栽谌魏雾?xiàng)目中安裝使用它,如 Vue/React/Angular/Node/TypeScript 等。
簡單總結(jié)一下,Jest 具有以下優(yōu)點(diǎn):
- 測試用例并行執(zhí)行,更高效
- 強(qiáng)大的 Mock 功能
- 內(nèi)置的代碼覆蓋率檢查,不需要在引入額外的工具
- 集成 JSDOM,可以直接進(jìn)行 DOM 相關(guān)的測試
- 開箱即用,幾乎不需要額外配置
- 可以直接對 ES Module Import 的代碼測試
- 有快照測試功能,可對 React 等框架進(jìn)行 UI 測試
a.安裝依賴
- jest:集成測試框架
- @types/jest: jest 的類型定義包,在 typescript 環(huán)境下使用 jest 需要用到
- ts-jest:測試 typescript 代碼的轉(zhuǎn)換工具
npm i jest @types/jest ts-jest -D
b.創(chuàng)建 jest.config.js
module.exports = {
// 測試目錄
roots: ['<rootDir>/test'],
// 對 ts tsx 文件使用 ts-jest 進(jìn)行運(yùn)行測試
transform: {
'.(ts|tsx)': 'ts-jest',
},
// 測試環(huán)境
testEnvironment: 'node',
// 測試文件匹配
testRegex: '(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$',
collectCoverage: true,
// 不計入覆蓋率中
coveragePathIgnorePatterns: ['/node_modules/', '/test/'],
// 覆蓋率達(dá)標(biāo)閾值,不達(dá)標(biāo)即測試失敗,拋出 error
coverageThreshold: {
global: {
branches: 90,
functions: 95,
lines: 95,
statements: 95,
},
},
};
c.在根目錄下創(chuàng)建 test/main.test.ts
import Sum from '../src/main'
test('sum is right', () => {
expect(Sum(1, 2)).toBe(10);
});
**d.package.json 加上新的 script 指令 "test": "jest" **
**
總結(jié)
本篇文章講解了webpack和rollup的區(qū)別,用rollup搭建了一個簡單版js庫,也使用了TS,ESLint和Prettier 規(guī)范代碼規(guī)范和提交代碼的規(guī)范和使用jest來保障代碼的質(zhì)量。代碼已上傳到github。https://github.com/turning1998/baselib