搭建规范化的 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 仓库页面中查看已发布的包和版本信息。

相关推荐
范文杰1 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪1 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪1 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy2 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom3 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom3 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom3 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom3 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom3 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试
LaoZhangAI4 小时前
2025最全GPT-4o图像生成API指南:官方接口配置+15个实用提示词【保姆级教程】
前端