搭建规范化的 npm 包

一、初始化项目

1. 初始化

运行命令 npm init -y 生成一个 package.json 文件。

json 复制代码
{
  "name": "vivace-utils",
  "version": "1.0.0",
  "description": "发布npm包,整套流程开发demo",
  "main": "src/index.js",
  "scripts": {
    "test": "npm run dev"
  },
  "author": "xiumubai",
  "license": "MIT"
}

2. 创建目录结构

md 复制代码
├── README.md // npm包说明,安装以及使用方法
├── examples // 使用测试的案例
├── package.json // 项目结构说明
├── scripts // 用于存在开发或打包的脚本文件
└── src // 存放项目文件
    └── index.js 

二、配置

1. 配置 rollup 构建环境

1.1 开发和生产环境

根据开发环境区分不同的配置,设置对应的 npm script,最终输出不同规范的产物:umd、umd.min、cjs、esm、iife(global)。在 scripts 目录下创建 rollup 配置文件:

md 复制代码
├── rollup.config.base.js // 基础文件
├── rollup.config.dev.js // 开发环境的配置
└── rollup.config.prod.js // 生产环境的配置
1.2 rollup 配置文件
shell 复制代码
npm install --save-dev rollup rollup-plugin-node-resolve rollup-plugin-commonjs rollup-plugin-terser rollup-plugin-babel

● rollup:模块打包工具,支持 Tree Shaking,生成多种模块格式(如 UMD、ESM、CJS 等)。、

● @rollup/plugin-node-resolve:从 node_modules 解析第三方依赖。

● @rollup/plugin-commonjs:CommonJS 转为 ES Module。

● @rollup/plugin-terser:压缩输出代码,减小体积。

● @rollup/plugin-babel:转译代码,确保兼容性和现代化。

在项目根目录下创建 rollup.config.js 文件,并进行配置:

js 复制代码
// 安装 npm 依赖包(部分后续需要)
// npm install -D rollup @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-json
import json from '@rollup/plugin-json'; // 允许在源码中直接引入 JSON 文件
import { terser } from 'rollup-plugin-terser'; // 用于压缩代码的插件
import { name, version, author } from '../package.json'; // 从 package.json 读取包信息

// 定义包名
const pkgName = 'tool-methods';

// 打包处理的文件,添加的备注信息
const banner = `/*!
 * ${name} v${version}
 * (c) 2024-${new Date().getFullYear()} ${author}
 * Released under the MIT License.
 */`;

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()] }, // 压缩版 UMD
    { file: `dist/${pkgName}.cjs.js`, format: 'cjs', banner }, // CommonJS 模块
    { file: `dist/${pkgName}.esm.js`, format: 'es', banner }, // ES 模块
    { file: `dist/${pkgName}.iife.js`, format: 'iife', name: pkgName, banner }, // 浏览器立即执行模块
  ],
  plugins: [
    json(), // 处理 JSON 文件的插件
    clear({ targets: ['dist'] }), // 每次打包前清空 dist 目录
    replace({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'), // 替换环境变量
      preventAssignment: true,
    }),
    nodeResolve(), // 解析第三方模块路径
    commonjs({ include: 'node_modules/**' }), // 转换 CommonJS 模块为 ES 模块
    eslint({
      throwOnError: true, // 如果有 ESLint 错误,抛出异常并终止打包
      include: ['src/**'], // 需要检查的文件
    }),
    babel({ babelHelpers: 'bundled' }), // 使用 Babel 转译
  ],
};
  1. 开发环境:启用开发服务器(serve) 和热更新(livereload) 功能,便于实时调试。
js 复制代码
import 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/browser'],
      openPage: 'index.html', // 打开默认页面
    }),
    livereload({
      watch: 'examples/browser', // 监听的目录或文件,当变化时自动刷新
    }),
  ],
};
  1. 生产环境:文件大小分析 (filesize),检查产物体积,确保最终产物的质量。
js 复制代码
import baseConfig from './rollup.config.base';
import filesize from 'rollup-plugin-filesize';

export default {
  ...baseConfig,
  plugins: [
    ...baseConfig.plugins,
    filesize(),
  ],
};
1.3 文件输出结构
md 复制代码
dist/
├── methods-tool.umd.js         # UMD 格式
├── methods-tool.umd.min.js     # 压缩版 UMD
├── methods-tool.cjs.js         # CommonJS 格式
├── methods-tool.esm.js         # ES Module 格式
├── methods-tool.iife.js        # 浏览器 IIFE 格式

2. 配置 babel 解析兼容

安装依赖 npm i -D @babel/core @babel/preset-env,添加配置在 .babelrc.js 文件。

js 复制代码
module.exports = {
  presets: [
    ['@babel/preset-env',
      {
        modules: false// rollupjs 会处理模块,所以设置成 false
      }
    ]
  ],
  plugins: []
}

● @babel/core:babel 的核心模块。

● @babel/preset-env:根据目标环境自动转译 JavaScript。

3. 配置 script

在 package.json 中,scripts 是一个对象,包含多个命令:

json 复制代码
{
	"scripts": {
  	"dev": "rollup -w --environment NODE_ENV:development -c scripts/rollup.config.dev.js",
    "build": "rollup --environment NODE_ENV:development -c scripts/rollup.config.prod.js",
  },
}

三、设置 eslint 和 pretter 实现代码规范化

● ESLint:检查代码语法和风格是否符合规范;

● Prettier:格式化代码,确保代码风格一致。

1. 安装依赖

shell 复制代码
npm install -D eslint eslint-plugin-vue eslint-plugin-prettier prettier eslint-config-prettier @babel/eslint-parser

● eslint-plugin-vue:检测 Vue.js 文件的语法和风格问题。

● eslint-plugin-prettier:整合 Prettier 规则到 ESLint,优先应用 Prettier 格式化。

● eslint-config-prettier:禁用与 Prettier 冲突的 ESLint 规则。

● @babel/eslint-parser:支持检查 Babel 编译后的现代 JS 代码。

2. 配置文件

js 复制代码
// .eslintrc.js
module.exports = {
  root: true,
  env: { browser: true, es2021: true, node: true, jest: true },
  extends: [
    'eslint:recommended',
    'plugin:prettier/recommended',
    'plugin:vue/vue3-recommended',
  ],
  parserOptions: { parser: '@babel/eslint-parser', ecmaVersion: 'latest', sourceType: 'module' },
  rules: {
    'space-before-function-paren': ['error', 'never'],
    semi: 0, // 禁用分号
  },
};
js 复制代码
// .eslintignore 配置, 防止校验打包的产物

dist          # 忽略打包目录
node_modules  # 忽略依赖目录

在 .prettierrc.json 文件下,添加如下规则:

json 复制代码
{
  "singleQuote": true,            // 使用单引号
  "semi": false,                  // 禁止结尾使用分号
  "bracketSpacing": true,         // 在括号和内容之间加空格
  "htmlWhitespaceSensitivity": "ignore", // 忽略 HTML 的空格敏感度
  "endOfLine": "auto",            // 自动检测换行符
  "trailingComma": "all",         // 在多行对象或数组末尾添加逗号
  "tabWidth": 2                   // 使用两个空格作为缩进
}

3. 配置运行脚本

在 package.json 中添加 ESLint 脚本:

json 复制代码
"scripts": {
  "lint": "eslint src",       // 检查代码
  "fix": "eslint src --fix"   // 自动修复问题
}

此外,通过 vscode 中下载 ESlint 插件,然后用 shift+cmd+p,打开搜索命令框,输入settings,选择后配置系统文件,如下:

json 复制代码
// 开启自动修复
"editor.codeActionsOnSave": {
  "source.fixAll": false,
  "source.fixAll.eslint": true
}

四、设置提交规范与代码检查

在 npm 包工具库 中设置 lint-staged、husky 和 commitlint,可自动化代码检查和提交规范,保证代码质量和规范性。

  1. husky:管理 Git hooks。
  2. lint-staged:仅检查变更的代码文件,提升效率。
  3. commitlint:规范化提交信息,确保版本记录整洁。

1.安装依赖

shell 复制代码
npm install -D husky lint-staged @commitlint/config-conventional @commitlint/cli

2. 配置 husky

husky 用于在 Git 提交时触发钩子(hooks),如 pre-commit 和 commit-msg,以保证每次提交符合规范。

shell 复制代码
npx husky-init  # 初始化 husky 配置
npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1" 

# 或者
npx husky install
npx husky add .husky/pre-commit "npx lint-staged"
npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1" 

初始化后,.husky 目录会生成,并包含 pre-commit 钩子。在 commit-msg 文件中添加添加命令: npx --no-install commitlint --edit $1。

3. 配置 lint-staged

在 package.json 添加以下配置:

json 复制代码
"scripts": {
  "lint-staged": "lint-staged"
},
"lint-staged": {
  "src/*.{js}": [
    "eslint --fix",
    "prettier --write",
    "git add"
  ]
}

此配置会在提交前,对 src 文件下的 .js 文件运行 eslint 和 prettier。

● prettier 格式化代码;

● eslint 修复代码并检查代码风格;

4. 配置 commitlint

commitlint 用于检查提交消息是否符合指定的规范,主要对 pre-commit 和 commit-msg 钩子做校验。在项目根目录创建 commitlint.config.js:

js 复制代码
module.exports = {
  extends: ['@commitlint/config-conventional'], // 引入标准提交规范
  rules: {
    'type-enum': [
      2, 'always', [
        'feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'chore', 'revert', 'build',
      ],
    ],
    '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], // 最大字符数72
  },
}

在 package.json 添加以下配置:

json 复制代码
{
  "scripts": {
    "commitlint": "commitlint --config commitlint.config.js -e -V"
  },
}

5. 配置 commitizen 生成规范化提交信息

commitizen 是一个生成符合规范的提交信息的工具。通过配置 cz-customizable 自定义提交信息的提示内容。

  1. 配置 commitizen:
    npm install -D commitizen cz-customizable
  2. 在 package.json 中添加配置:
json 复制代码
"config": {
  "commitizen": {
    "path": "./node_modules/cz-customizable"
  }
}
  1. 创建 .cz-config.js 文件,并自定义提交信息的选项:
js 复制代码
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:    打包' },
    { value: 'ci', name: '👷CI:   related changes' }
  ],
  messages: {
    type: '请选择提交类型(必选):',
    customScope: '请输入修改范围(可选):',
    subject: '请简要描述提交(必填):',
    footer: '请输入要关闭的issue(待优化去除,跳过即可):',
    confirmCommit: '确认使用以上信息提交?(y/n/e/h)'
  },
  allowCustomScopes: true,
  skipQuestions: ['body', 'footer'],
  subjectLimit: 72
};
  1. 提交代码
shell 复制代码
git add .
npm run commit  # 按提示输入提交信息

6. 目录结构

项目结构应包含以下内容:

md 复制代码
├── .husky/
│   ├── commit-msg  # 校验提交消息
│   └── pre-commit  # 校验提交前的代码
├── .cz-config.js  # 自定义提交信息规则
├── package.json  # 配置依赖和脚本
└── commitlint.config.js  # 配置提交信息规范

五、添加 jest 测试工具

使用 jest 进行单元测试、生成覆盖率报告,有助于提高代码质量。

1. 安装依赖

npm install -D jest rollup-jest

2. 添加脚本

在 package.json 中,添加如下配置:

json 复制代码
"scripts": {
  "test": "jest",           // 运行测试
  "test:c": "jest --coverage" // 生成代码覆盖率报告
},
"jest": {
  "preset": "rollup-jest"  // 使用 rollup-jest 作为预设配置
}

3. 编写测试文件

tests 文件夹中创建测试文件,例如 sum.test.js:

js 复制代码
const sum = require('../src/sum')

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3)
})

4. 修改源代码

在 src/index.js 中实现 sum 函数,并使用 ES Module 导出:

js 复制代码
function sum() {
  let args = Array.from(arguments);
  return args.reduce((start, result) => {
    return start + result;
  }, 0);
}

export { sum };

5. 运行测试

在终端中运行以下命令来执行测试:

shell 复制代码
npm run test      # 运行测试
npm run test:c    # 运行并生成覆盖率报告

六、完善 package.json 文件

● main:UMD 格式入口文件,支持 CommonJS/AMD(例如,Node.js 环境使用)。

● module:ES Modules 格式入口文件(例如,前端打包工具如 Webpack 或 Rollup 会使用)。

● unpkg: 浏览器友好的构建版本,用于 CDN。

● files: 指定发布库时包含的文件,这里仅包含 dist 目录。

● dependencies:运行依赖库

● devDependencies:开发依赖库

json 复制代码
{
  "name": "tool-methods",
  "version": "1.1.0",
  "description": "开发工具库",
  "main": "dist/index.umd.min.js",
  "module": "dist/index.esm.js",
  "unpkg": "dist/index.js",
  "scripts": {
    
  },
  "files": [
    "dist"
  ],
  "devDependencies": { ... },
  "dependencies": { ... }
}

七、添加 changelog 自动生成

1. 安装依赖

npm install -g conventional-changelog-cli

2. 配置 package.json

在 scripts 中添加以下命令:

json 复制代码
"scripts": {
  "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
  "createlog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0"
}

● changelog: 生成本次版本的日志,不覆盖以往内容。

● createlog: 从零开始生成完整的 CHANGELOG.md,覆盖已有文件。

3. 运行命令

md 复制代码
npm run createlog // 首次生成完整日志
npm run changelog // 更新本次版本日志

八、发布包

1. 登录 npm

发布前登录 npm:

shell 复制代码
npm login

如果登录不上,可能是因为使用了淘宝镜像。解决方法:安装并切换 NPM 源管理工具 nrm。

shell 复制代码
npm install -g nrm
nrm use npm

2. 发布 npm 包

运行下面命令:

shell 复制代码
npm publish --access=public

3. 配置发布脚本

在 package.json 中添加 scripts:

json 复制代码
"scripts": {
  "major": "npm version major -m 'build: update major'", // 更新大版本
  "minor": "npm version minor -m 'build: update minor'", // 更新中版本
  "patch": "npm version patch -m 'build: update patch'", // 更新小版本
  "pub": "npm run build && npm publish --access=public", // 构建并发布
  "pub:major": "npm run major && npm publish --access=public", // 更新大版本后发布
  "pub:minor": "npm run minor && npm publish --access=public", // 更新中版本后发布
  "pub:patch": "npm run patch && npm publish --access=public"  // 更新小版本后发布
}

上述可以看到,通过 npm version 命令更新版本号。

4. 运行命令

shell 复制代码
npm run pub // 首次发布

// 后续发布
npm run pub:patch  # 更新小版本后发布
npm run pub:minor  # 更新中版本后发布
npm run pub:major  # 更新大版本后发布

5. 查看发布结果

发布成功后,可在自己的 NPM 仓库页面中查看已发布的包和版本信息。

相关推荐
即将头秃的程序媛6 分钟前
vue 项目实现阻止浏览器记住密码
前端·javascript·vue.js
Williamoses7 分钟前
elementui table滚动分页加载
前端·vue.js·elementui
时光匆匆岁月荏苒,转眼我们已不是当年8 分钟前
【VUE小型网站开发】优化通用配置 二
前端·javascript·vue.js
Serenity_Qin9 分钟前
vue3 + ts 使用 el-tree
前端·vue.js·typescript·vue3·element-plus
fury_1231 小时前
当大的div中有六个小的div,上面三个下面三个,当外层div高变大的时候我希望里面的小的div的高也变大
前端·javascript·html
大鸡腿最好吃1 小时前
为啥react要用jsx
前端·javascript·react.js
小黄编程快乐屋1 小时前
前端小练习——大雪纷飞(JS没有上限!!!)
开发语言·前端·javascript
程序猿阿伟1 小时前
《平衡之策:C++应对人工智能不平衡训练数据的数据增强方法》
前端·javascript·c++
STUPID MAN1 小时前
vue3使用后端传递的文件流进行文件预览
前端·javascript·vue.js·文件预览
-代号95272 小时前
【React】二、状态变量useState
前端·javascript·react.js