使用 Vite 打包工具库并使用 GitHub Actions 自动化发布npm流程

devtools/2024/10/18 18:21:03/

使用 Vite 打包一个 TypeScript 编写的 utils 工具库,并在发布到 npm 之前使用 Vitest 进行测试,同时利用 GitHub Actions 自动化发布流程

前言

我们在日常开发中经常会使用 npm install 安装别人的包,使用别人的插件。

当你在前端开发有一段时间之后你也会知道,那些npm包实际上就是别人写好的一些代码来供你调用。

开发久了难免就想自己造轮子了,当然现在轮子这么多,不一定要自己造了,你可以不做,但不能不会。

那么今天就来讲讲如何通过Vite + TypeScript + Vitest + GitHub Actions 自动化发布流程来发布一个属于自己的npm包。

步骤

  • 安装必要的依赖
  • 创建项目
  • 项目配置
  • 编写代码
  • 单元测试
  • 编写 README.md
  • 构建和发布命令配置
  • 手动发布到 npm
  • 自动发布到 npm
  • 测试 npm

一、安装必要的依赖

  • 安装 Vite: npm install vite --save-dev
  • 安装 TypeScript: npm install typescript --save-dev
  • 安装 vite-plugin-dts 插件以支持 npm install vite-plugin-dts --save-dev
  • 安装 Vitest: npm install vitest --save-dev
  • 安装 @types/node 以便支持 Node.js 环境下的类型定义: npm install @types/node --save-dev

二、创建项目

使用 Vite 快速创建一个原生 TypeScript 开发的项目非常简单。按照以下步骤进行操作:

  • 确保你已经安装了最新版本的 Node.js(建议使用 LTS 版本)。
  • 打开终端,并进入你想创建项目的目录。
  • 运行以下命令来创建一个新的 Vite 项目:
pnpm create vite utils --template vanilla-ts

这将创建一个名为 utils 的文件夹,并使用 vanilla-ts 模板来初始化一个原生 TypeScript 项目。
--template vanilla-ts 是在使用 Vite 创建项目时的一个选项参数。它指定了所使用的项目模板为 “vanilla-ts”。

  • 进入项目目录:
cd utils
  • 安装项目的依赖:
pnpm install
  • 运行以下命令来启动开发服务器:
pnpm run dev

这将启动 Vite 的开发服务器,并在浏览器中打开项目。

现在,你就可以开始在 src 目录下编写你的原生 TypeScript 代码了。Vite 会自动监听你的代码变化,并实时更新你的应用程序。
你可以根据你的需求修改和扩展项目,例如添加其他依赖、配置构建选项等。
请注意,原生 TypeScript 项目使用 Vite 不需要额外的配置,因为 Vite 默认支持 TypeScript。如果你想更深入地定制项目的配置,可以查阅 Vite 的官方文档或社区资源。

请添加图片描述

运行后的截图,点击count会++。项目结构和counter.js文件。

三、项目配置

1、Vite 配置

在项目根目录下创建 vite.config.ts 文件 :

import { defineConfig } from 'vite';export default defineConfig({build: {lib: {entry: './src/index.ts', // 工具库入口name: 'Utils', // 工具库名称fileName: (format) => `index.${format}.js`, // 工具库名称// formats: ['es', 'umd', 'cjs'], // 打包模式,默认是es和umd}},// outDir: "lib", // 自定义构建输出目录 默认为 dist
});

2、类型声明文件 配置

vite-plugin-dts 是一个 Vite 插件,用于自动生成 TypeScript 类型声明文件(.d.ts)。

在使用 Vite 构建 TypeScript 项目时,通常需要手动编写类型声明文件来描述项目中的模块、组件和函数的类型。这个过程可能会比较繁琐和容易出错。vite-plugin-dts 的目的就是简化这个过程,它会基于项目中的源代码自动生成类型声明文件,减少手动编写的工作量。

然后,在 Vite 的配置文件 vite.config.js 中将插件引入:

import { defineConfig } from 'vite';
import dts from 'vite-plugin-dts'export default defineConfig({plugins: [dts()], // 启用插件 vite-plugin-dts//...
});

当你启动 Vite 构建项目时,vite-plugin-dts 将会自动扫描你的源代码并生成对应的类型声明文件。这些文件将会保存在 dist 目录下的 types 文件夹中。

vite-plugin-dts 还提供了一些配置选项,可以根据你的需要进行自定义。例如,你可以指定生成类型声明文件的输出路径、忽略某些文件或文件夹、自定义类型声明的文件名等。

运行 npm run build 命令的时候 dist 文件夹中就会自动生成 index.d.ts 文件,发布之后别人下载使用时就会有类型提示了。

在这里插入图片描述

3、Vitest 配置

  • package.json 中添加测试脚本:
"scripts": {"test": "vitest","test:run": "vitest run"
}

4、package.json 配置

package.json 文件里面有很多字段要填写,否则不能正确发布。最重要的是以下几个字段:

  • name: 包名,该名字是唯一的。可在 npm 官网搜索名字,如果存在则需换个名字。
  • version: 版本号,不能和历史版本号相同,每次发布都要增大才能发布成功。
  • files: 需要上传的文件,一般是 dist 目录下的文件,也可根据需要配置需要发布的文件。
  • main: commonJs的包路径,入口文件,默认为 index.js,这里改为 dist/index.umd.js。
  • module: ESModule的包路径,模块入口,这里改为 dist/index.es.js。
  • types: ts类型文件路径,类型声明文件入口,这里改为 dist/index.d.ts。
  • private: 是否为私有包, 需要更改为 false 才能发布到 npm
  • type: 文件的默认加载方式,若不填则默认为commonJs。但是无论package.json中的type字段为何值,.mjs的文件都按照es模块来处理,.cjs的文件都按照commonJs模块来处理

到这里就是一个基础的配置,了解这些就能解决首次发布的基本问题。

description,repository,bugs,keywords这些属性看需要配置,如果你是想做一个便利大家使用的开源,建议越完善越好

完整的 package.json 如下:

{"name": "i6i8-utils","private": false,"version": "1.0.0","type": "module","main": "/dist/index.umd.js","module": "/dist/index.es.js","types": "/dist/index.d.ts","description": "工具库","files": ["dist/*"],"keywords": ["utils","typescript"],"author": {"name": "quanda li","email": "864910436@qq.com"},"repository": {"type": "git","url": "git+https://github.com/China-quanda/i6i8-utils.git"},"bugs": {"url": "https://github.com/China-quanda/i6i8-utils/issues","email": "864910436@qq.com"},"license": "MIT","scripts": {"dev": "vite","build": "tsc && vite build","prepublishOnly": "npm run build && npm run test:run","preview": "vite preview","test": "vitest","test:run": "vitest run"},"devDependencies": {"@types/node": "^22.5.0","typescript": "^5.5.3","vite": "^5.4.1","vite-plugin-dts": "^4.0.3","vitest": "^2.0.5"}
}

这里简单提下打包名称里有 esumd 是什么意思 ?

Javascript 的模块化从前后端区分的话有两大类:

1、commonJS 也就是服务端 node 的模块化标准 (require / module.export)

2、客户端的标准则有 amd / umd / es Module 等

  • amd 使用(require / define)
  • umd 是一种同时兼容node和浏览器的标准
  • es Module 是ES6 的模块化标准(export / import)

四、编写代码

  • 在 src 目录下编写您的工具库代码,例如 index.ts:
export function add(a: number, b: number): number {return a + b;
}

五、单元测试

对于一个工具函数来说,单元测试非常非常非常重要。不会单元测试的可以看一下《JavaScript测试驱动开发》这本书。

编写单元测试,确保你的代码能够正常工作并符合预期。

  • 在根目录下与src同级目录下创建 tests 目录并在其中编写测试文件,例如 add.test.ts:
import { expect, it, describe } from 'vitest'
import { add } from '../src/index';describe('对add函数进行测试', () => {it('should return 3 with 1+2', () => {expect(add(1, 2)).toBe(3)})it('should return 0 with 0+0', () => {expect(add(0, 0)).toBe(0)})it('should return 5 with 2+3', () => {expect(add(2, 3 as any)).toBe(5)})
})
  • 以下两种测试方法都可以测试,我们只需要在选择 vscode编辑器中的vitest插件 或者 shell命令行运行 其中一种测试即可。

  • 在 vscode 编辑器中搜索 vitest 插件安装。可以有更完美的配合

在这里插入图片描述

  • 使用 npm run test:run 进行测试,测试结果如下:
> @qd/utils-web@1.0.0 test:run /Users/quanda/Desktop/other_project/utils
> vitest runRUN  v2.0.5 /Users/quanda/Desktop/other_project/utils✓ tests/add.test.ts (3)✓ 对add函数进行测试 (3)✓ should return 3 with 1+2✓ should return 0 with 0+0✓ should return 5 with 2+3Test Files  1 passed (1)Tests  3 passed (3)Start at  15:16:11Duration  210ms (transform 21ms, setup 0ms, collect 15ms, tests 1ms, environment 0ms, prepare 44ms)
  • 可以看到都测试通过了,符合我们的预期用法。

六、编写 README.md

  • 在根目录下创建 README.md 文件,并添加一些关于工具库的描述和用法。
# i6i8-utils## 简介
工具库,包含一些常用的工具函数。## 安装pnpm add i6i8-utilsyarn add i6i8-utilsnpm install i6i8-utils## 使用
import { add } from 'i6i8-utils'
console.log(add(1, 2)) // 3

七、构建和发布命令配置

  • 添加构建脚本到 package.json:
"scripts": {"build": "vite build","prepublishOnly": "npm run build && npm run test:run"
}
  • 运行 npm run build 以构建库。

  • 运行 npm run test:run 以运行测试。

npm_313">八、手动发布到 npm

发布到npm上的包应该遵循一些最佳实践,如给包添加适当的版本号、提供清晰的文档和示例代码、确保代码质量等。这些都有助于提高你的包的可用性和可维护性,吸引更多的用户和贡献者。

  • 这边是默认已经拥有了npm账号的,如果没有的话移步 npm官网 注册并创建 npm 账号。

npm__registry__320">1、先查看 npm 的 registry 如果显示的不是官方源,就要改回来

npm config get registry
  • 设置 npm 的 registry 为官方源
npm config set registry https://registry.npmjs.org

npm____331">2、登录到 npm: ( 如果已登陆可以忽略这一步 )

  • 检查是否已经登录,如果已经登录,会提示用户名
npm whoami

登录命令

npm login
  • 登录成功后提示:
quanda@192 utils % npm login
npm notice Log in on https://registry.npmjs.org/
Login at:
https://www.npmjs.com/login?next=/login/cli/41cc7ed3-5815-4a7e-b1d6-74b3621406ad
Press ENTER to open in the browser...Logged in on https://registry.npmjs.org/.

3、为项目打 tag

  • 可打可不打,打 tag 可以方便管理版本,方便回滚。
  • 使用 npm version 命令,给项目打上 tag 版本号,可根据自己需求修改
# major 主版本
# minor 功能版本
# patch 修复版本
npm version minor
  • 打tag后执行结果:
quanda@192 utils % npm version minor
v1.1.0

npm_publish__npm__373">4、执行 npm publish 将包发布到 npm 上。

通过运行npm publish命令将你的utils包发布到 npm。确保你已经登录到 npm账号,并且在项目文件夹的根目录下运行该命令。发布成功后,你的utils包将在 npm 上可供其他开发人员使用。

  • 执行 npm publish 发布包
quanda@192 utils % npm publish> i6i8-utils@1.0.0 prepublishOnly
> npm run build && npm run test:run> i6i8-utils@1.0.0 build
> tsc && vite buildvite v5.4.2 building for production...
✓ 1 modules transformed.[vite:dts] Start generate declaration files...
dist/index.es.js  0.06 kB │ gzip: 0.08 kB
[vite:dts] Declaration files built in 460ms.dist/index.umd.js  0.32 kB │ gzip: 0.24 kB
✓ built in 491ms> i6i8-utils@1.0.0 test:run
> vitest runRUN  v2.0.5 /Users/quanda/Desktop/other_project/utils✓ tests/add.test.ts (3)✓ 对add函数进行测试 (3)✓ should return 3 with 1+2✓ should return 0 with 0+0✓ should return 5 with 2+3Test Files  1 passed (1)Tests  3 passed (3)Start at  14:52:35Duration  213ms (transform 19ms, setup 0ms, collect 16ms, tests 2ms, environment 0ms, prepare 37ms)npm notice
npm notice 📦  i6i8-utils@1.0.0
npm notice Tarball Contents
npm notice 244B README.md
npm notice 72B dist/counter.d.ts
npm notice 59B dist/index.d.ts
npm notice 60B dist/index.es.js
npm notice 320B dist/index.umd.js
npm notice 0B dist/main.d.ts
npm notice 1.5kB dist/vite.svg
npm notice 990B package.json
npm notice Tarball Details
npm notice name: i6i8-utils
npm notice version: 1.0.0
npm notice filename: i6i8-utils-1.0.0.tgz
npm notice package size: 2.0 kB
npm notice unpacked size: 3.2 kB
npm notice shasum: 43ad7c509ab109add19fe358eaf62584b525abf6
npm notice integrity: sha512-yLzaScXCKUNxU[...]tmV9GuuJO+sXw==
npm notice total files: 8
npm notice
npm notice Publishing to https://registry.npmjs.org with tag latest and default access
+ i6i8-utils@1.0.0
quanda@192 utils % 
  • 发布成功后就可以在 npm 查看

在这里插入图片描述

最后的使用就和我们平时安装其他 npm 包一样了, npm install XX 后在项目中 import 就可以正常使用了。

更新命令 (第一次发布请跳过)

npm version patch

注意:npm version patch是在你原有的版本号,假设v1.0.0,他会在这个基础上加1,如果你的版本不是加1,你可以不用npm version patch,直接手动改package.json,然后再npm publish

npm_456">九、自动发布到 npm

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

1、获取 Npm Access Token

要想让 Github Action 能有权利发布指定的 npm 包, 需要获取 npm 的 通行证. 这个通行证就是 npm token, 所以我们需要登入 npm 官网, 生成一个 token,用它打通 GitHub 和 NPM。

  • 首先,进入 NPM 首页,登录后点击右上角的 头像 -> Access Tokens -> Generate New Token -> Classic Token

在这里插入图片描述

  • 接着,给 token 起个名字,并选择 publish 权限,最后点击 Generate Token 按钮。

在这里插入图片描述

  • 生成 token 后记得复制生成的 token保存,关闭页面后就再也看不到了。

在这里插入图片描述

2、设置 Github Secrets

  • 转到你的 GitHub 仓库。
  • 点击仓库页面顶部的 Settings(设置)。
  • 在左侧菜单中选择 Secrets and variables -> Actions。

在这里插入图片描述

  • 在 Name 字段输入NPM_TOKEN
  • 在 Secret 字段粘贴你刚才生成的 NPM token。
  • 点击 Add secret。

在这里插入图片描述

3、编写 workflows 工作流

  • 点击 Tab 栏上的 Actions ,我们要发布到 NPM,所以选择其中的 Punlish Node.js Package 。

在这里插入图片描述

  • 此时,会自动新建一个 npm-publish.yml 脚本,修改脚本后,点击右上角 Commit changes 保存并提交,在项目中就会生成对应的脚本文件。

在这里插入图片描述

  • 当然,你也可以直接在本地新建 .github/workflows/npm-publish.yml 文件,修改完后再上传。

我们这边才用的是自己在本地新建的方式哈

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

  • 在项目根目录下创建 .github/workflows/npm-publish.yml 文件:
name: NPM Publish
on:push:branches:- master
jobs:build:runs-on: ubuntu-lateststeps:- name: Checkoutuses: actions/checkout@v4- name: Setup pnpmuses: pnpm/action-setup@v3with:version: 9- name: Setup Node.jsuses: actions/setup-node@v4with:node-version: 20cache: pnpm- name: Install dependenciesrun: pnpm install- name: Run testsrun: pnpm run test:runpublish-npm:needs: buildruns-on: ubuntu-lateststeps:- uses: actions/checkout@v4- uses: actions/setup-node@v4with:node-version: 20registry-url: https://registry.npmjs.org/- run: npm install- run: npm publishenv:NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}- run: ls -a

注意:npm token 是用于发布 npm 包的,请不要将 token 泄露给其他人。:上传的npm包,在72小时后不可删除,如果是测试用的包,记得72小时内删除

  • npm token 存储为 GitHub Secret (NPM_TOKEN)。

  • 当代码推送到 GitHub 仓库的主分支时,GitHub Actions 将自动执行测试、构建和发布流程。
    这样,您就可以将自己编写的 TypeScript 工具库通过 Vite 打包,并使用 Vitest 测试,最后通过 GitHub Actions 自动化发布到 npm 上供其他人使用了。

  • 将本地仓库代码推送到 GitHub 仓库。

在推送代码到 GitHub 仓库之前,请确保package.json里的version字段版本号已经更新,之前我们手动推送前的版本号version 是1.0.0,我们现在将 version 改变成1.0.1

{"version": "1.0.1",
}
  • 使用 git 推送命令:
git push
  • git 推送完成状态:
quanda@192 utils % git push
枚举对象中: 20, 完成.
对象计数中: 100% (20/20), 完成.
使用 8 个线程进行压缩
压缩对象中: 100% (17/17), 完成.
写入对象中: 100% (20/20), 23.42 KiB | 7.80 MiB/s, 完成.
总共 20(差异 0),复用 0(差异 0),包复用 0(来自  0 个包)
To https://github.com/China-quanda/i6i8-utils.git* [new branch]      master -> master
分支 'master' 设置为跟踪 'github/master'。
quanda@192 utils % 
  • 等待 GitHub Actions 执行完毕后,您可以在 GitHub 仓库的 Actions 页面中查看工作流的运行结果。
    在这里插入图片描述

  • 执行完毕后就可以在 npm 查看了版本号已经更新了

在这里插入图片描述

npm_599">十、测试npm

发布之后,很快啊,我们就能下载这个npm包进行测试了。

pnpm add i6i8-utilsyarn add i6i8-utilsnpm install i6i8-utils
  • 我们先创建一个测试项目,然后安装i6i8-utils

  • 可以看到 add 函数计算的结果和 ts 的类型提示都有:

在这里插入图片描述

结语:

通过以上步骤,你可以成功地使用 Vite 打包 TypeScript 编写的工具库,并通过 GitHub Actions 自动化其发布过程。


http://www.ppmy.cn/devtools/117870.html

相关文章

python判断文件内容是否为空

获取文件大小,如果文件大小等于0就是空的,如下: import os size os.path.getsize(d:/abc.txt) if size 0:print(文件是空的) else:print(文件不是空的)

华为HarmonyOS灵活高效的消息推送服务(Push Kit) - 1 简介

Push Kit(推送服务)是华为提供的消息推送平台,建立了从云端到终端的消息推送通道。所有HarmonyOS应用可通过集成Push Kit,实现向应用实时推送消息,使消息易见,构筑良好的用户关系,提升用户的感知…

K8s Calico替换为Cilium,以及安装Cilium过程(鲁莽版)

迁移CNI插件的3种办法: 1、创建一个新的集群,通过Gitops的方式迁移负载,然而,这可能涉及大量的准备工作和潜在的中断。 2、另一种方法是重新配置/etc/cni/net.d/指向Cilium。但是,现有的pod仍将由旧的…

助力“20+8”新兴产业高质量创新发展科普活动-走进深算院

近日,在全国科普日暨深圳科普月活动启动之际,由深圳计算科学研究院承办的助力“208”新兴产业高质量创新发展科普活动成功举行。此次活动由深圳市科学技术协会指导,汇集了20余名政府、企业和高校代表,共同探讨了国产基础软件的创新…

Java数据结构--List介绍

前言: 数据结构可以说是一门思想,当我们在对数据处理、储存的时候需要用到。 前面我用C语言写过数据结构的相关内容,在Java阶段的数据结构思想是一样的,就是有些地方实现的方式是有区别的。 因此在Java阶段前期的数据结构&#xf…

mysql常用的日期函数以及查询昨天,今天,本周,上个月的数据

一 常用的日期函数 1. CURDATE() CURDATE() 是一个 MySQL 函数,用于返回当前的日期,格式为 YYYY-MM-DD。它不包含时间部分,仅显示日期。 SELECT CURDATE(); // 2024-09-20注意事项 CURDATE() 返回的日期格式与系统的日期格式设置有关&…

组合模式

组合模式 把一组相似的对象当作一个单一的对象。如&#xff1a;树形菜单 public class Menu {String name;List<Menu> child;public Menu(String name){this.name name;child new ArrayList<>();}public void addChild(Menu menu){child.add(menu);}public void …

C++(9.26)

1.什么是虚函数&#xff0c;什么是纯虚函数 虚函数是在基类中声明为virtual的函数&#xff0c;可以被重新定义来实现多态&#xff0c;纯虚函数则是以0结尾的虚函数&#xff0c;是没有实现的虚函数。 2.基类为什么需要虚构析函数 为了防止在后面delete释放空间时导致溢出 数据…