共计 7283 个字符,预计需要花费 19 分钟才能阅读完成。
在日常开发中,常常会遇到一些通用的逻辑,导致每次都须要复制粘贴。而咱们作为 coder,能够将一些罕用业务逻辑封装成通用的函数库,并公布到 npm 中。
这样,每次遇到新的我的项目时,只须要 install 一下即可
这里咱们曾经有了一个 fe-utils 前端日常开发工具库,也是本文最初的产物,并且后续也会继续更新。如果你有一个开源的心,然而没信念去为大的我的项目提 pr,无妨从这个封装日常通用逻辑的我的项目做起,咱们一起提高!!!
接下来咱们就尝试本人入手实现一个工具库
创立我的项目
首先在本人的 github 上创立一个我的项目,而后拉取。进入到该仓库中,执行yarn init
。一路 enter 上来。
次要目录构造
- .github
- workflows
- xx.yml
- .husky
- src
- __test__
- index.ts
- sum.ts
- .editorconfig
- .gitignore
- .npmignore
- commitlint.config.js
- jest.config.mjs
- package.json
- rollup.config.js
- tsconfig.json
配置我的项目
1. 装置 rollup 和 ts
yarn add rollup typescript -D
2. 配置 typescript 配置文件
yarn tsc --init
生成一个默认的配置文件,而后依据咱们的我的项目,改成如下:
{
"compilerOptions": {
"target": "es5" /* 编译指标 */,
"module": "commonjs" /* 我的项目模块类型 */,
"lib": ["ES2018", "DOM"],
"allowJs": true /* 是否容许 js 代码 */,
"checkJs": true /* 查看 js 代码谬误 */,
"declaration": true /* 主动创立申明文件(.d.ts) */,
"declarationDir": "./lib" /* 申明文件目录 */,
"sourceMap": true /* 主动生成 sourcemap 文件 */,
"outDir": "lib" /* 编译输入目录 */,
"rootDir": "./src" /* 我的项目源码根目录,用来管制编译输入的目录构造 */,
"strict": true /* 启用严格模式 */
},
"include": ["src/index.ts"],
"exclude": ["node_modules", "lib"]
}
3. 配置 rollup.config.js
在配置之前,咱们须要装置几个 rollup 插件yarn add @rollup/plugin-node-resolve @rollup/plugin-typescript @rollup/plugin-commonjs rollup-plugin-terser -D
这几个别离是如下作用
- @rollup/plugin-node-resolve 解决门路
- @rollup/plugin-typescript 反对 ts
- @rollup/plugin-commonjs 解决 commonjs
- rollup-plugin-terser 压缩 umd 标准的输入文件
const resolve = require('@rollup/plugin-node-resolve');
const typescript = require('@rollup/plugin-typescript');
const commonjs = require('@rollup/plugin-commonjs');
const {terser} = require('rollup-plugin-terser')
module.exports = [
{
input: './src/index.ts',
output: [
{
dir: 'lib',
format: 'cjs',
entryFileNames: '[name].cjs.js',
sourcemap: false, // 是否输入 sourcemap
},
{
dir: 'lib',
format: 'esm',
entryFileNames: '[name].esm.js',
sourcemap: false, // 是否输入 sourcemap
},
{
dir: 'lib',
format: 'umd',
entryFileNames: '[name].umd.js',
name: 'FE_utils', // umd 模块名称,相当于一个命名空间,会主动挂载到 window 上面
sourcemap: false,
plugins: [terser()],
},
],
plugins: [resolve(), commonjs(), typescript({ module: "ESNext"})],
}
]
4. 批改 package.json
咱们间接看残缺的 package.json
{
"name": "@lxnxbnq/utils",
"version": "0.0.2-alpha",
"main": "lib/index.cjs.js",
"module": "lib/index.esm.js",
"jsnext:main": "lib/index.esm.js",
"browser": "lib/index.umd.js",
"types": "lib/index.d.ts",
"files": ["lib"],
"repository": {
"type": "git",
"url": "git+https://github.com/SaebaRyoo/fe-utils.git"
},
"author": "SaebaRyoo <yuanddmail@163.com>",
"license": "MIT",
"scripts": {
"build": "rollup -c",
"test": "jest"
},
"devDependencies": {
"@rollup/plugin-babel": "^6.0.3",
"@rollup/plugin-commonjs": "^23.0.4",
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-typescript": "^10.0.1",
"@types/jest": "^29.2.4",
"jest": "^29.3.1",
"rollup": "^3.7.2",
"rollup-plugin-terser": "^7.0.2",
"ts-jest": "^29.0.3",
"tslib": "^2.4.1",
"typescript": "^4.9.4"
},
"description": "前端业务代码工具库",
"bugs": {"url": "https://github.com/SaebaRyoo/fe-utils/issues"},
"homepage": "https://github.com/SaebaRyoo/fe-utils#readme",
"dependencies": {}}
其中须要留神的有如下几个字段
告知使用者不同的标准援用哪个文件
- “main”: “lib/index.cjs.js”, // 当应用 commonjs 标准时会应用这个包
- “module”: “lib/index.esm.js”, // 应用 esm 时,会应用这个包
- “jsnext:main”: “lib/index.esm.js”, // 这个同上,不过这个是社区标准,下面是官网标准
- “browser”: “lib/index.umd.js”, // umd 标准,当间接在浏览器中开发时,能够间接下载 release 包并在浏览器中应用 script 导入
ts 类型文件
- “types”: “lib/index.d.ts”,
应用 yarn run build
打包我的项目
- “scripts”: {
“build”: “rollup -c”,
},
files 字段是用于约定在发包的时候 NPM 会公布蕴含的文件和文件夹。
“files”: [
"lib"
],
5. 装置 jest + lint + prettier + husky + commit-msg 对代码的品质进行束缚
首先是装置装置测试框架 jest,因为我的项目时基于 ts 写的,所以须要配置 jest 来反对 tsyarn add -D jest ts-jest @types/jest
- 创立配置文件
yarn jest --init
- 批改配置文件, 残缺如下
jest 的默认环境是 node,然而咱们这个工具库是面向前端的,必定须要操作 dom,所以须要装置 yarn add jest-environment-jsdom -D
来反对 DOM 和 BOM 操作
而后就是在应用到 DOM 或者 BOM 对象的测试文件的顶部加上这一行正文即可运行
/**
* @jest-environment jsdom
*/
或者在配置文件中批改运行环境为testEnvironment: 'jsdom'
/*
* For a detailed explanation regarding each configuration property, visit:
* https://jestjs.io/docs/configuration
*/
export default {
clearMocks: true,
collectCoverage: true,
coverageDirectory: 'coverage',
coverageProvider: 'v8',
preset: 'ts-jest',
testEnvironment: 'jsdom', // 反对测试环境拜访 dom
// 配置测试环境 ua
testEnvironmentOptions: {
userAgent:
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
},
};
-
在 package.json 的 script 中增加 cli 命令
{ "scripts": { "test": "jest", "coveralls": "jest --coverage", } }
- 最初依照这篇文章的步骤来配置标准代码的文件
开发
咱们先在 src 的目录下写一个简略的 sum 办法以及一个单元测试
src/sum.ts
export function sum(...args: number[]): number {return args.reduce((prev, total) => total + prev, 0);
}
在入口中导入并导出
src/index.ts
export {sum} from './sum';
写一个 sum 的单元测试
src/__test__/sum.test.ts
import {sum} from '../index'
describe('sum', () => {it('should work', () => {expect(sum()).toEqual(0)
})
})
到这,基本上一个最简略的 npm 包就开发完了,接下来就是须要公布
npm 包公布
1. 手动公布
首先须要筹备一个账号,而后进行登录,输出你的 npm 账号、明码、邮箱npm login
能够用 npm logout
退出以后账号
npm who am i
查问以后登录的账号
登录胜利就能够通过 npm publish
将包推送到服务器上
如果某版本的包有问题,能够应用 npm unpublish [pkg]@[version]
将其撤回
留神:如果应用 @[scope]/package
的命名模式,[scope]肯定要写你的账号名,不然公布的时候会提醒 404
2. 应用 github action 公布 npm、创立 release 以及解决一些工作流程
如果不理解 github action 的话, 倡议先学习一下 github actions 的一些概念
在根目录下创立.github/workflows/node.js.yml
CI 配置文件(这里也能够在仓库上的 tab 栏中找到 Actions 生成)
留神:如果你须要不同的 actions,能够在 Marketplace 中查找须要的 action
指标
- 主动公布 npm 包
- 创立 release 并上传对应 asset
- 跑单元测试,生成测试覆盖率提交到 coveralls
筹备工作
- 在 npm 中生成 token
- 而后复制 token 到 github 对应仓库的秘钥中
- 设置一个变量名,咱们这里设置的是
NPM_ACCESS_TOKEN
,前面能够在 CI 中通过secrets.NPM_ACCESS_TOKEN
获取到
整体代码
有了以上的思路来看上面的整体代码
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs
name: Node.js CI
on:
push:
branches: ["main"]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{matrix.node-version}}
uses: actions/setup-node@v3
with:
node-version: ${{matrix.node-version}}
cache: 'yarn'
- run: yarn
# 测试,并生成测试覆盖率文件
- run: yarn run coveralls
- run: yarn run build
# 上报
- name: Coveralls
uses: coverallsapp/github-action@master
with:
github-token: ${{secrets.GITHUB_TOKEN}}
# publish-npm 工作
publish-npm:
# 在 ubuntu 最新版本的虚拟机执行
runs-on: ubuntu-latest
# 设置变量
strategy:
matrix:
node-version: [18.x]
steps:
# 查看并切换到 main 分支
- name: 查看 main 分支
# 应用 actions/checkout 插件
uses: actions/checkout@v3
# 初始化缓存
- name: 缓存
uses: actions/cache@v3
id: cache-dependencies
with:
path: node_modules
key: ${{runner.OS}}-${{hashFiles('**/yarn.lock')}}
# 装置 node
- name: 设置 Node.js
# 应用 actions/setup-node 插件
uses: actions/setup-node@v3
with:
# node 版本
node-version: ${{matrix.node-version}}
- run: yarn
- run: yarn run build
# 读取以后版本号
- name: 读取以后版本号
id: version
uses: notiz-dev/github-action-json-property@release
with:
# 读取版本号
path: './package.json'
prop_path: 'version'
- run: echo ${{steps.version.outputs.prop}}
# 创立 Release
- name: release
# 本来应用的 actions/create-release@latest 来发版,actions/upload-release-asset@v1 上传 release-asset
# 不过这两个 action 官网曾经进行保护了,所以换成如下
uses: softprops/action-gh-release@v1
with:
files: ./lib/index.umd.js
name: v${{steps.version.outputs.prop}}
tag_name: v${{steps.version.outputs.prop}}
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
# 公布 NPM 包
- name: 公布 NPM 包
# 执行公布代码
run: |
npm config set //registry.npmjs.org/:_authToken=$NPM_TOKEN
npm publish
env:
# 配置 npm access token 环境变量
NPM_TOKEN: ${{secrets.NPM_ACCESS_TOKEN}}
# 刷新缓存
- name: 刷新缓存
run: |
curl https://purge.jsdelivr.net/npm/iemotion-pic@latest/lib/name.json
为 readme 增加 badge(徽章)
咱们会发现在一个开源我的项目中,readme 通常都会写的很好,而且还有很多的 badge, 如 ant-design 的 readme
那么这一切都是怎么实现的呢?一些简略的 badge 能够间接在 shields 中输出仓库名即可生成。
比方:
workflow 工作流状态:
npm 包版本:
license:
咱们也能够依据本人须要来创立不同的 badge
不过要增加测试覆盖率的 badge 会稍稍有些麻烦。
- 首先进入 coveralls 官网,进去后须要通过 github 的受权
- 受权后点击左侧侧边栏的 ADD REPOS 会进入如下页面
而后咱们将须要生成 badge 徽章的库设置为 on 即可
- 前面的流程就是在 CI 中执行测试脚本并生成测试覆盖率的文件而后上传到 coveralls 就能够了