1. 简介
这是基于typescript和rollup打包工具搭建的前端库开发框架,单元测试使用jest,文档插件使用typedoc, 还集成了commit提交规范,版本发布和版本号自动提升,changelog自动生成等。基于github的action,使用.github/workflows 自动构建文档。
2. 环境准备
- node环境
- git
3. 框架搭建
1. 新建空的代码仓库
2. clone这个仓库到本地
3.初始化node项目,得到packages
npm init
4.添加依赖
(1) 添加rollup 打包依赖
npm install @rollup/plugin-typescript rollup rollup-plugin-dts rollup-plugin-terser --save-dev
(2) 添加typescript依赖
npm install @types/node typescript tslib --save-dev
(3) 添加jest单元测试依赖
npm install jest @types/jest jest-config ts-jest --save-dev
(4) 添加代码格式化约束插件依赖
npm install @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-config-airbnb-base eslint-config-prettier eslint-plugin-import eslint-plugin-prettier lint-staged prettier --save-dev
(5) 添加文档插件依赖
npm install typedoc --save-dev
(6) 添加提交规范插件和生成changelog插件
npm install @commitlint/cli @commitlint/config-conventional commitizen husky --save-dev
(6) 添加版本发布插件
npm install standard-version --save-dev
(7) 其他工具包省略~~~
(8) 完整依赖如下
"devDependencies": {
"@commitlint/cli": "^17.0.3",
"@commitlint/config-conventional": "^17.0.3",
"@rollup/plugin-typescript": "^8.3.4",
"@types/inquirer": "^9.0.1",
"@types/jest": "^28.1.7",
"@types/node": "^18.7.8",
"@typescript-eslint/eslint-plugin": "^5.33.1",
"@typescript-eslint/parser": "^5.33.1",
"chalk": "^5.0.1",
"commitizen": "^4.2.5",
"cross-env": "^7.0.3",
"eslint": "^8.22.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1",
"esno": "^0.16.3",
"husky": "^8.0.1",
"inquirer": "^9.1.0",
"jest": "^28.1.3",
"jest-config": "^28.1.3",
"lint-staged": "^13.0.3",
"prettier": "^2.7.1",
"rollup": "^2.78.1",
"rollup-plugin-dts": "^4.2.2",
"rollup-plugin-terser": "^7.0.2",
"standard-version": "^9.5.0",
"ts-jest": "^28.0.8",
"tslib": "^2.4.0",
"typedoc": "^0.23.10",
"typescript": "^4.7.4"
},
5. 插件配置
(1) 新建rollup.config.ts文件
import typescript from "@rollup/plugin-typescript";
import dts from "rollup-plugin-dts";
import { terser } from "rollup-plugin-terser";
const currentNodeEnv = process.env.NODE_ENV;
const isCompressLibrary =
currentNodeEnv === "prod" ? terser({ module: true, toplevel: true }) : null;
const pkg = require("./package.json");
const libraryName = "ol-plugins";
export default [
{
input: "./src/index.ts",
output: [
{
file: pkg.main,
name: libraryName,
format: "umd",
sourcemap: true,
},
{ file: pkg.module, format: "es", sourcemap: true },
],
plugins: [
typescript({ compilerOptions: { lib: ["esnext"] } }),
isCompressLibrary,
],
watch: {
include: "src/**",
exclude: "node_modules/**",
},
},
{
input: "./src/index.ts",
output: [{ file: `dist/${libraryName}.d.ts`, format: "esm" }],
plugins: [dts()],
},
];
(2) 新建.prettierrc文件
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": false,
"trailingComma": "es5",
"bracketSpacing": true,
"arrowParens": "always",
"htmlWhitespaceSensitivity": "css",
"endOfLine": "lf"
}
(3) 新建.editorconfig文件
root = true
[*]
indent_style = space
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 120
indent_size = 2
[*.md]
trim_trailing_whitespace = false
(3) 新建.eslintrc.js文件
module.exports = {
env: {
browser: true,
es2021: true
},
extends: ['airbnb-base', 'plugin:prettier/recommended'],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
},
plugins: ['@typescript-eslint'],
rules: {
'import/no-extraneous-dependencies': 'off',
'no-underscore-dangle': 'arrow'
}
}
(4) 新建commitlint.config.js文件
module.exports = { extends: ['@commitlint/config-conventional'] }
(5) 新建tsconfig.json文件
{
"compilerOptions": {
"moduleResolution": "node",
"target": "es5",
"module": "es2015",
"lib": ["es2015", "es2016", "es2017", "dom"],
"strict": true,
"sourceMap": true,
"declaration": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"declarationDir": "dist/types",
"outDir": "dist/lib",
"typeRoots": ["node_modules/@types"]
},
"include": ["src"],
"typedocOptions": {
"entryPoints": ["src/index.ts"],
"out": "docs"
}
}
(6) 新建typedoc.json文件
{
"entryPoints": [
"./src/index.ts"
],
"includes": [
"src/*.ts"
],
"out": "docs",
"readme": "none",
"includeVersion": true,
"disableSources": false
}
(7) 配置lint-staged。在packages 里面添加如下
"devDependencies":{},
...
"lint-staged": {
"src/**/*.{js,ts}": [
"prettier --write",
"git add"
]
},
(8) 配置commitizen。在packages 里面添加如下
"devDependencies":{},
...
"config": {
"commitizen": {
"path": "cz-conventional-changelog"
}
},
(9) 配置husky。在packages 里面添加如下
"devDependencies":{},
...
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
(10) 配置jest。在packages 里面添加如下
"devDependencies":{},
...
"jest": {
"transform": {
".(ts|tsx)": "ts-jest"
},
"testEnvironment": "node",
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
"moduleFileExtensions": [
"ts",
"tsx",
"js"
],
"coveragePathIgnorePatterns": [
"/node_modules/",
"/test/"
],
"coverageThreshold": {
"global": {
"branches": 90,
"functions": 95,
"lines": 95,
"statements": 95
}
},
"collectCoverageFrom": [
"src/*.{js,ts}"
]
},
6. 打包脚本编写。
(1) toolkit/release.ts
import { execSync } from "child_process";
import chalk from "chalk";
import { inquireVersion } from "./inquirer";
// NPM 发包流程文件
// 0. 执行 npm run test 确保所有测试用例通过
// 1. 询问发什么版本的包 major:大版本 minor: 小版本 patch: 补丁,新特性,bug修复版本
async function initRelease() {
execSync("jest --coverage --watch", { stdio: "inherit" });
console.log(chalk.blueBright("所有测试用例通过!"));
const version = await inquireVersion(); // 自动提升版本
execSync(`standard-version --release-as ${version}`, { stdio: "inherit" });
console.log(chalk.blueBright("版本更新完成!"));
execSync("npm publish --access public", { stdio: "inherit" });
console.log(chalk.blueBright("NPM发布完成!"));
execSync("git push origin main", { stdio: "inherit" });
execSync("git push origin --tags", { stdio: "inherit" });
console.log(chalk.blueBright("代码提交到远程仓库中!"));
}
initRelease();
(2) toolkit/inquirer.ts
import inquirer from "inquirer";
export const inquireVersion = async () => {
const { version } = await inquirer.prompt({
type: "list",
name: "version",
message: "Please select the release version from list",
default: "patch",
choices: ["major", "minor", "patch"],
});
return version;
};
7. 脚本命令配置之
"scripts": {
"dev": "npm run build:entry && cross-env NODE_ENV=dev rollup --config rollup.config.ts --watch",
"build": "npm run build:entry && cross-env NODE_ENV=prod rollup --config rollup.config.ts",
"test": "jest --coverage",
"test:watch": "jest --coverage --watch",
"test:prod": "npm run lint && npm run test -- --no-cache",
"doc": "typedoc --options typedoc.json",
"release": "esno ./toolkit/release.ts",
"commit": "git cz"
},
...
"devDependencies":{},
...
4. 文档发布
1. 在跟目录新建目录 ./github/workflows
2. 新建文件 eploy-docs.yml, dp监听了main分支的变化,会自动构建文档,新建或覆盖推送到gh-pages 分支。
name: Build and Deploy Docs
# 监听 main 分支的推送
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
# job 名
build-and-deploy:
# 运行环境
runs-on: ubuntu-latest
# 运行步骤
steps:
# 获取源码
- name: Checkout
uses: actions/checkout@v2.3.1
# 下载依赖
- name: Install dependencies
run: npm install
# Docs 安装依赖
- name: Build Docs
run: npm run doc
# 发布
# 发布在 gh-pages 分支,会自动创建
# 将打包后的 dist 目录放到 gh-pages 分支
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs
3. 使用github page 显示自己的文档。
(1) 新建仓库,命名为自己的github账号名+'github.io',例如:# little-qiu.github.io。
(2) 进入本仓库,如下图:点击save 保存。
(3) 等待1分钟即可,此时就可以用自己的github page 访问自己的文档。
@little_q/ol_plugins - v1.0.0 (little-qiu.github.io)