从零创建并发布一个 Npm 包

前言

React 项目中经常使用 classnames 包,用来将样式类名连接一起,看了源码使用的是 ES5 的写法,于是使用 typescript 重写了一版。

仓库: mixnames

创建项目

使用 father 创建项目

father 是一款 NPM 包研发工具,能够帮助开发者更高效、高质量地研发 NPM 包、生成构建产物、再完成发布。

sh 复制代码
npx create-father mixnames

代码编写

仿照 classnames 的写法,将 arguments 替换成剩余参数,将不定数量的参数表示为一个数组,类型是 Union Types

ts 复制代码
const mixnames = (...args: (string | number | Object | Array<any>)[]): string => {
  /// ...
}

详细查看源码

添加测试

代码写完后使用 vitest 进行测试

Vitest 旨在将自己定位为 Vite 项目的首选测试框架,即使对于不使用 Vite 的项目也是一个可靠的替代方案。

sh 复制代码
pnpm add -D vitest

在项目根目录新建 test 文件夹;在 package.json 添加 test 脚本

代码测试

新建 test/mixnames.test.ts,编写测试代码,覆盖全部传参情况

ts 复制代码
import { expect, test } from 'vitest'
import mixnames from "../src/index";

test("joins arrays of class names and ignore falsy values", () => {
  expect(mixnames("a", 0, null, undefined, true, 1, "b")).toBe("a 1 b");
});

/// ...

mixnames.test.ts

组件测试

添加组件测试依赖,参考 vitest/examples/react

sh 复制代码
pnpm add jsdom react react-test-renderer jsdom -D

新建 tes/basic.test.tsx,编写 react 组件的测试代码

tsx 复制代码
import React from 'react'
import renderer from 'react-test-renderer'
import mx from '../src/index'

function toJson(component: renderer.ReactTestRenderer) {
  const result = component.toJSON()
  expect(result).toBeDefined()
  expect(result).not.toBeInstanceOf(Array)
  return result as renderer.ReactTestRendererJSON
}

test('expect same classname', () => {
  const button1 = renderer.create(
    <button className={mx("foo", "bar", "baz")}>Confirm</button>,
  )
  const button1Json = toJson(button1)

  expect(button1Json).toMatchSnapshot()
 }
 
 /// ...

basic.test.tsx

通过全部测试用例后就可以发包了

发布

使用 npm version 命令,给项目打上 tag,然后执行 npm publish 将包发布到 npm

sh 复制代码
# major 主版本
# minor 功能版本
# patch 修复版本
npm version minor
复制代码
npm publish

发布成功后就可以在 npm 查看

mixnames

至此这个包就可以提供给别人安装使用了

sh 复制代码
pnpm add mixnames

yarn add mixnames

npm install mixnames

自动发布

每次手动发布新版本到 npm 比较麻烦,使用 Github Workflow 可以实现当版本有变化时,自动发包到 npm。

在项目根目录添加 .github/workflows/npm-publish.yml 文件,配置发包的工作流。

yml 复制代码
name: Node.js Package

on:
  push:
    tags:
      - 'v*'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 16
          cache: 'npm'
      - run: npm i
      - run: npm test

  publish-npm:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: 16
          cache: 'npm'
          registry-url: https://registry.npmjs.org/
      - run: npm i
      - run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}

先执行测试流程,测试通过之后执行发布流程,需要在项目 secrets 中添加 NPM_TOKEN 环境变量

这个变量需要在 npmjs.com 生成

总结

本文通过一个例子说明了如何开发,测试和发布一个 npm 包,感谢阅读 🌹

相关推荐
学如逆水,不进则退2 小时前
在线免费音频剪辑:NBTools 可视化波形裁剪 MP3/WAV,本地处理免上传
前端·音视频
Mh2 小时前
虚拟滚动真的比普通滚动性能更好吗?
前端·javascript·性能优化
pe7er2 小时前
React + Ant Design 中的 IME (输入法合成)安全输入组件
前端
Super 含3 小时前
Android 启动优化(二):TTID、TTFD 与 Macrobenchmark 启动性能测量
前端
Python私教3 小时前
别急着加 llms.txt:企业官网面向 AI 搜索的工程清单
前端·人工智能·seo
东方小月3 小时前
从零开发一个 Coding Agent(十三):实现安全的 read 文件读取工具
前端·人工智能·全栈
东方小月3 小时前
从零开发一个 Coding Agent(十二):实现版本化 JSONL 与真实 CLI 入口
前端·设计模式·前端框架
FL16238631294 小时前
室内易燃物识别易燃评估室内易燃程度识别分割数据集labelme格式1015张85类别
java·服务器·前端
用户059540174464 小时前
把 AI 长期记忆去重测试从 20 分钟压到 40 秒,重复率从 18% 干到 1.5%
前端·css
kyriewen5 小时前
我把 AI 写的并发请求控制器手写了一遍——3 个语义我当时根本讲不清
前端·javascript·面试