开发工具选型
- 开发前端使用的包,主要的逻辑代码只包含js,所以选用rollup做打包工具。
- webpack适合开发项目,项目中会包含图片/视频/css、vue等多种资源,更适合使用webpack。
开发流程
- 初始化项目,创建合理的目录结构
- 设置基于编辑器的代码统一规范 .editorconfig vscode的配置
- 配置 eslint 和 pretter 统一代码风格
- 配置 babel,处理新语法兼容型
- 配置 git 提交的校验钩子
- 规范化提交代码到 git 仓库
- 设置开发和打包脚本
- 添加单元测试jest,编写测试示例
- 完善 package.json 必要字段
- 配置合适的 npm script
- 本地测试开发的 npm 包,使用yalc
- 发布包到 npm
初始化项目
npm init -y
{"name": "sumfunctionmethod","version": "1.0.0","description": "发布npm包,整套流程开发demo","main": "src/index.js","scripts": {"test": "npm run dev"},"author": "shenshuai89","license": "ISC"}
创建目录结构
├── README.md // npm包说明,安装以及使用方法├── examples // 使用测试的案例├── package.json // 项目结构说明├── scripts // 用于存在开发或打包的脚本文件└── src // 存放项目文件└── index.js
配置rollup开发环境
- 根据开发环境区分不同的配置
- 设置对应的 npm script
- 输出不同规范的产物:umd、umd.min、cjs、esm、iife(global)
在scripts目录下创建rollup配置文件
├── rollup.config.base.js // 基础文件├── rollup.config.dev.js // 开发环境的配置└── rollup.config.prod.js // 生产环境的配置
rollup.config.base.js
// 安装以下 npm 包// npm install -D @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-alias @rollup/plugin-replace @rollup/plugin-eslint @rollup/plugin-babel rollup-plugin-terser rollup-plugin-clear @rollup/plugin-jsonimport { nodeResolve } from '@rollup/plugin-node-resolve' // 解析 node_modules 中的模块import commonjs from '@rollup/plugin-commonjs' // cjs => esmimport alias from '@rollup/plugin-alias' // alias 和 reslove 功能import replace from '@rollup/plugin-replace'import eslint from '@rollup/plugin-eslint'import { babel } from '@rollup/plugin-babel'import { terser } from 'rollup-plugin-terser'import clear from 'rollup-plugin-clear'import json from '@rollup/plugin-json' // 支持在源码中直接引入json文件,不影响下面的import { name, version, author } from '../package.json'const pkgName = 'sumfunctionmethods'// 打包处理的文件,添加的备注信息const banner ='/*!\n' +` * ${name} v${version}\n` +` * (c) 2022-${new Date().getFullYear()} ${author}\n` +' * Released under the MIT License.\n' +' */'export default {input: 'src/index.js',// 同时打包多种规范的产物output: [{file: `dist/${pkgName}.umd.js`,format: 'umd',name: pkgName,banner},{file: `dist/${pkgName}.umd.min.js`,format: 'umd',name: pkgName,banner,plugins: [terser()]},{file: `dist/${pkgName}.cjs.js`,format: 'cjs',name: pkgName,banner,plugins: [terser()]},{file: `dist/${pkgName}.esm.js`,format: 'es',name: pkgName,banner,plugins: [terser()]},{file: `dist/${pkgName}.js`,format: 'iife',name: pkgName,banner,plugins: [terser()]}],// 注意 plugin 的使用顺序plugins: [json(),clear({targets: ['dist']}),alias(),replace({'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),preventAssignment: true}),nodeResolve(),commonjs({include: 'node_modules/**'}),eslint({throwOnError: true, // 抛出异常并阻止打包include: ['src/**'],exclude: ['node_modules/**']}),babel({ babelHelpers: 'bundled' })]}
rollup.config.dev.js
// npm install -D rollup-plugin-serve rollup-plugin-livereloadimport baseConfig from './rollup.config.base'import serve from 'rollup-plugin-serve'import livereload from 'rollup-plugin-livereload'export default {...baseConfig,plugins: [...baseConfig.plugins,serve({port: 8080,contentBase: ['dist', 'examples/brower'],openPage: 'index.html',}),livereload({watch: 'examples/brower',})]}
rollup.config.prod.js
// npm install -D rollup-plugin-filesizeimport baseConfig from './rollup.config.base'import filesize from 'rollup-plugin-filesize'export default {...baseConfig,plugins: [...baseConfig.plugins,filesize()]}
配置 babel 解析兼容
安装依赖 npm i -D @babel/core @babel/preset-env
添加文件.babelrc.js
module.exports = {presets: [['@babel/preset-env', {// rollupjs 会处理模块,所以设置成 falsemodules: false}]],plugins: []}
设置eslint和pretter统一代码风格
eslint验证代码是否符合定义的规范
- eslint-plugin-vue:vue.js的Eslint插件(查找vue语法错误,发现错误指令,查找违规风格指南)
- eslint-plugin-prettier:运行更漂亮的Eslint,使prettier规则优先级更高,Eslint优先级低
- eslint-config-prettier:让所有可能与prettier规则存在冲突的Eslint rules失效,并使用prettier进行代码检查
- @babel/eslint-parser:该解析器允许使用Eslint校验所有babel code,仅支持最新的最终ECMAScript标准,不支持实验性语法,该编译器会将code解析为Eslint能懂的EsTree(ES2021语法等等)
npm i -D eslint// 生成配置文件,.eslintrc.jsnpx eslint --init// 使用 standard 规范npm install --save-dev eslint-plugin-import eslint-plugin-node eslint-plugin-prettier eslint-config-prettier @babel/eslint-parser// .eslintrc.js 配置module.exports = {root: true,env: {browser: true,es2021: true,node: true,jest: true,},extends: ['eslint:recommended', // eslint'plugin:prettier/recommended', // plugin-prettier'plugin:vue/vue3-recommended', // plugin-vue],parserOptions: {parser: '@babel/eslint-parser', // 解析器ecmaVersion: 'latest',sourceType: 'module',},// rules: { //也可设置一个prettier验证规则// 'prettier/prettier': 'error', // Runs Prettier as an ESLint rule and reports differences// },rules: {'space-before-function-paren': ['error', 'never'],semi: 0, // 结尾不要分号},}// .eslintignore 配置, 防止校验打包的产物distnode_modules
之后可以在package.json 中添加运行脚本
"scripts": {"lint": "eslint src","fix": "eslint src --fix",}
prettier格式化代码符合定义的规范
安装prettier包
npm install -D eslint-plugin-prettier prettier eslint-config-prettier
添加配置文件
{"singleQuote": true,"semi": false,"bracketSpacing": true,"htmlWhitespaceSensitivity": "ignore","endOfLine": "auto","trailingComma": "all","tabWidth": 2}
使用lint-staged
对提交到暂存区的代码做校验,lint-staged 是一个在git暂存文件上运行linter的工具。可以设置对某些类型文件做特殊处理如eslint和prettier
安装和配置代码质量工具lint-staged
// 安装依赖yarn add -D lint-staged
// 在package.json中添加脚本,以及配置"scripts": {"lint-staged": "lint-staged",},"lint-staged": {// 匹配暂存区所有的js文件,并执行命令"src/*.{js}": ["prettier --write","eslint --cache --fix","git add"]}
配置 git 提交的校验钩子
- husky: git提交时触发hooks
- commitlint: 对提交的内容做规范校验
husky,主要对pre-commit和commit-msg钩子做校验。
// 安装huskyyarn add husky -Dnpx husky-init // 初始化husky配置,在根目录新增.husky配置文件。初始化配置pre-commitnpx husky add .husky/commit-msg // 另外新增一个hooks,commit-msg
- pre-commit中添加 npm run lint-staged
- commit-msg中添加 npm run commitlint
安装commitlint
// 添加依赖文件yarn add @commitlint/config-conventional @commitlint/cli -D// 添加配置文件commitlint.config.jsmodule.exports = { extends: ['@commitlint/config-conventional'] }; //基本设置
给commitlint.config.js自定义校验规则
module.exports = {extends: ['@commitlint/config-conventional'],// 校验规则rules: {'type-enum': [2,'always',['feat', //新功能(feature)'fix', //修补bug'docs', //文档(documentation)'style', //格式(不影响代码运行的变动)'refactor', //重构(即不是新增功能,也不是修改bug的代码变动)'perf', //性能提升(提高性能的代码改动)'test', //测试'chore', // 不修改src或测试文件的其他更改'revert', //撤退之前的commit'build' //构建过程或辅助工具的变动(webpack等)]],'type-case': [0],'type-empty': [0],'scope-empty': [0],'scope-case': [0],'subject-full-stop': [0, 'never'],'subject-case': [0, 'never'],'header-max-length': [0, 'always', 72]}}
使用 commitizen 做git规范化提交
由于添加了commitlint验证,对于不熟悉提交规范的新手同学会有一定影响,可以添加 commitizen 工具,手动生成规范化commit。
Commitizen是一个格式化commit message的工具。介绍
// 工具安装yarn add -D commitizen
配置命令
"script": {"commit": "git-cz"}
安装规则包
npx commitizen init cz-conventional-changelog --yarn --dev --exact
使用 cz-conventional-changelog 做提交规则
可以在package中定义
"config": {"commitizen": {"path": "cz-conventional-changelog"}}
单独创建.czrc文件
{"path": "cz-conventional-changelog"}
以后进行commit提交时,可以采用npm run commit也就是使用了 git-cz 中的规则。
自定义 commitizen 规则
- 第一种方法可以直接修改package中的config
"config": {"commitizen": {"path": "cz-conventional-changelog","type": {"test": {"description": "测试自定义 commitizen 规则","title": "测试自定义 commitizen"}}}}
使用 cz-customizable 工具
安装依赖
yarn add cz-customizable -D
在package.json 中添加自定义commitizen,使用git-cz执行git commit命令
"config": {"commitizen": {"path": "./node_modules/cz-customizable"}}
在根目录创建的.cz-config.js, 自定义commit提示内容
module.exports = {types: [{ value: 'feat', name: 'feat: 新功能' },{ value: 'fix', name: 'fix: 修复' },{ value: 'docs', name: 'docs: 文档变更' },{ value: 'style', name: 'style: 代码格式(不影响代码运行的变动)' },{value: 'refactor',name: 'refactor: 重构(既不是增加feature,也不是修复bug)'},{ value: 'perf', name: 'perf: 性能优化' },{ value: 'test', name: 'test: 增加测试' },{ value: 'chore', name: 'chore: 构建过程或辅助工具的变动' },{ value: 'revert', name: 'revert: 回退' },{ value: 'build', name: 'build: 打包' }],// 消息步骤messages: {type: '请选择提交类型:',// scope: '请输入文件修改范围(可选):',// used if allowCustomScopes is truecustomScope: '请输入修改范围(可选):',subject: '请简要描述提交(必填):',body: '请输入详细描述(可选,待优化去除,跳过即可):',// breaking: 'List any BREAKING CHANGES (optional):\n',footer: '请输入要关闭的issue(待优化去除,跳过即可):',confirmCommit: '确认使用以上信息提交?(y/n/e/h)'},allowCustomScopes: true,// allowBreakingChanges: ['feat', 'fix'],skipQuestions: ['body', 'footer'],// limit subject length, commitlint默认是72subjectLimit: 72}
添加jest测试工具
- 选用 jest 做单元测试
- 配置 eslint 的 jest 环境
- 解决 jest 不支持 es module 的问题
- 在test 目录下创建 [name].test.js(name 和 源码中的文件名保持一致)
// 安装jest依赖npm i -D jest// 使得支持 `es module`npm i -D rollup-jest
在package.json中设置
"scripts":{"test": "jest","test:c": "jest --coverage",},"jest": {"preset": "rollup-jest"}
执行 npm run test 进行测试
执行 npm run test:c 查看测试覆盖率
完善 package.json 必要字段
- version: 版本好
- main: 主入口
- module: cjs入口
- exports: 配置多种类型的入口
- unpkg: cdn地址
- jsdelivr: cdn地址
- files: 发布库时包含的文件
- keywords: 关键测
- homepage: github的readme
- repository: 仓库地址
- bugs: bug提交
- dependencies: 库依赖文件
- devDependencies: 开发时依赖的库
main module exports的区别
main 是npm包的主要入口文件,当导入一个包时,实际上就是使用的main指向的地址文件。
main是遵循commonjs规范的,使用module.exports 。
module是ESM规范,是前端使用比较多的规范,使用import/export。
如果使用import导入库,最开始匹配module的文件,找不到则使用main指向的文件。
rollup打包工具提供了多种打包格式,可以在output中进行设置。
// rollup.config.jsexport default {...,output: {file: 'bundle.js',format: 'iife', // 可以是amd、cjs、esm、iife、umd、systemname: 'MyBundle'}};
- amd – 异步模块定义,用于像RequireJS这样的模块加载器
- cjs – CommonJS,适用于 Node 和 Browserify/Webpack
- esm – 将软件包保存为 ES 模块文件,在现代浏览器中可以通过
