Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >如何发布一个 TypeScript 编写的 npm 包

如何发布一个 TypeScript 编写的 npm 包

作者头像
chuckQu
发布于 2023-02-13 04:02:16
发布于 2023-02-13 04:02:16
2K00
代码可运行
举报
文章被收录于专栏:前端F2E前端F2E
运行总次数:0
代码可运行

前言

在这篇文章中,我们将使用TypeScript和Jest从头开始构建和发布一个NPM包。

我们将初始化一个项目,设置TypeScript,用Jest编写测试,并将其发布到NPM。

项目

我们的库称为digx。它允许从嵌套对象中根据路径找出值,类似于lodash中的get函数。

比如说:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const source = { my: { nested: [1, 2, 3] } }
digx(source, "my.nested[1]") //=> 2

就本文而言,只要它是简洁的和可测试的,它做什么并不那么重要。

npm包可以在这里[1]找到。GitHub仓库地址在这里[2]。

初始化项目

让我们从创建空目录并初始化它开始。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mkdir digx
cd digx
npm init --yes

npm init --yes命令将为你创建package.json文件,并填充一些默认值。

让我们也在同一文件夹中设置一个git仓库。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
git init
echo "node_modules" >> .gitignore
echo "dist" >> .gitignore
git add .
git commit -m "initial"

构建库

这里会用到TypeScript,我们来安装它。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm i -D typescript

使用下面的配置创建tsconfig.json文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "files": ["src/index.ts"],
  "compilerOptions": {
    "target": "es2015",
    "module": "es2015",
    "declaration": true,
    "outDir": "./dist",
    "noEmit": false,
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictBindCallApply": true,
    "strictPropertyInitialization": true,
    "noImplicitThis": true,
    "alwaysStrict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "noPropertyAccessFromIndexSignature": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": true
  }
}

最重要的设置是这些:

  1. 库的主文件会位于src文件夹下,因此需要这么设置"files": ["src/index.ts"]
  2. "target": "es2015" 确保我们的库支持现代平台,并且不会携带不必要的垫片。
  3. "module": "es2015"。我们的模块将是一个标准的ES模块(默认是CommonJS)。ES模式在现代浏览器下没有任何问题;甚至Node从13版本开始就支持ES模式。
  4. "declaration": true - 因为我们想要自动生成d.ts声明文件。我们的TypeScript用户将需要这些声明文件。

其他大部分选项只是各种可选的TypeScript检查,我更喜欢开启这些检查。

打开package.json,更新scripts的内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
"scripts": {
  "build": "tsc"
}

现在我们可以用npm run build来运行构建...这样会失败的,因为我们还没有任何可以构建的代码。

我们从另一端开始。

添加测试

作为一名负责任的开发,我们将从测试开始。我们将使用jest,因为它简单且好用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm i -D jest @types/jest ts-jest

ts-jest包是Jest理解TypeScript所需要的。另一个选择是使用babel,这将需要更多的配置和额外的模块。我们就保持简洁,采用ts-jest

使用如下命令初始化jest配置文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
./node_modules/.bin/jest --init

一路狂按回车键就行,默认值就很好。

这会使用一些默认选项创建jest.config.js文件,并添加"test": "jest"脚本到package.json中。

打开jest.config.js,找到以preset开始的行,并更新为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  // ...
  preset: "ts-jest",
  // ...
}

最后,创建src目录,以及测试文件src/digx.test.ts,填入如下代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import dg from "./index";

test("works with a shallow object", () => {
  expect(dg({ param: 1 }, "param")).toBe(1);
});

test("works with a shallow array", () => {
  expect(dg([1, 2, 3], "[2]")).toBe(3);
});

test("works with a shallow array when shouldThrow is true", () => {
  expect(dg([1, 2, 3], "[2]", true)).toBe(3);
});

test("works with a nested object", () => {
  const source = { param: [{}, { test: "A" }] };
  expect(dg(source, "param[1].test")).toBe("A");
});

test("returns undefined when source is null", () => {
  expect(dg(null, "param[1].test")).toBeUndefined();
});

test("returns undefined when path is wrong", () => {
  expect(dg({ param: [] }, "param[1].test")).toBeUndefined();
});

test("throws an exception when path is wrong and shouldThrow is true", () => {
  expect(() => dg({ param: [] }, "param[1].test", true)).toThrow();
});

test("works tranparently with Sets and Maps", () => {
  const source = new Map([
    ["param", new Set()],
    ["innerSet", new Set([new Map(), new Map([["innerKey", "value"]])])],
  ]);
  expect(dg(source, "innerSet[1].innerKey")).toBe("value");
});

这些单元测试让我们对正在构建的东西有一个直观的了解。

我们的模块导出一个单一函数,digx。它接收任意对象,字符串参数path,以及可选参数shouldThrow,该参数使得提供的路径在源对象的嵌套结构中不被允许时,抛出一个异常。

嵌套结构可以是对象和数组,也可以是Map和Set。

使用npm t运行测试,当然,不出意外会失败。

现在打开src/index.ts文件,并写入下面内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
export default dig;

/**
 * A dig function that takes any object with a nested structure and a path,
 * and returns the value under that path or undefined when no value is found.
 *
 * @param {any}     source - A nested objects.
 * @param {string}  path - A path string, for example `my[1].test.field`
 * @param {boolean} [shouldThrow=false] - Optionally throw an exception when nothing found
 *
 */
function dig(source: any, path: string, shouldThrow: boolean = false) {
  if (source === null || source === undefined) {
    return undefined;
  }

  // split path: "param[3].test" => ["param", 3, "test"]
  const parts = splitPath(path);

  return parts.reduce((acc, el) => {
    if (acc === undefined) {
      if (shouldThrow) {
        throw new Error(`Could not dig the value using path: ${path}`);
      } else {
        return undefined;
      }
    }

    if (isNum(el)) {
      // array getter [3]
      const arrIndex = parseInt(el);
      if (acc instanceof Set) {
        return Array.from(acc)[arrIndex];
      } else {
        return acc[arrIndex];
      }
    } else {
      // object getter
      if (acc instanceof Map) {
        return acc.get(el);
      } else {
        return acc[el];
      }
    }
  }, source);
}

const ALL_DIGITS_REGEX = /^\d+$/;

function isNum(str: string) {
  return str.match(ALL_DIGITS_REGEX);
}

const PATH_SPLIT_REGEX = /\.|\]|\[/;

function splitPath(str: string) {
  return (
    str
      .split(PATH_SPLIT_REGEX)
      // remove empty strings
      .filter((x) => !!x)
  );
}

这个实现可以更好,但对我们来说重要的是,现在测试通过了。自己用npm t试试吧。

现在,如果运行npm run build,可以看到dist目录下会有两个文件,index.jsindex.d.ts

接下来就来发布吧。

发布

如果你还没有在npm上注册,就先注册[3]。

注册成功后,通过你的终端用npm login登录。

我们离发布我们的新包只有一步之遥。不过,还有几件事情需要处理。

首先,确保我们的package.json中拥有正确的元数据。

  1. 确保main属性设置为打包的文件"main": "dist/index.js"
  2. 为TypeScript用户添加"types": "dist/index.d.ts"
  3. 因为我们的库会作为ES Module被使用,因此需要指定"type": "module"
  4. namedescription也应填写。

接着,我们应该处理好我们希望发布的文件。我不觉得要发布任何配置文件,也不觉得要发布源文件和测试文件。

我们可以做的一件事是使用.npmignore,列出所有我们不想发布的文件。我更希望有一个"白名单",所以让我们使用package.json中的files字段来指定我们想要包含的文件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  // ...
  "files": ["dist", "LICENSE", "README.md", "package.json"],
  // ...
}

终于,我们已经准备好发包了。

运行以下命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm publish --dry-run

并确保只包括所需的文件。当一切准备就绪时,就可以运行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm publish

测试一下

让我们创建一个全新的项目并安装我们的模块。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm install --save digx

现在,让我们写一个简单的程序来测试它。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import dg from "digx"

console.log(dg({ test: [1, 2, 3] }, "test[0]"))

结果非常棒!

digx_autocomplete.png

然后运行node index.js,你会看到屏幕上打印1

总结

我们从头开始创建并发布了一个简单的npm包。

我们的库提供了一个ESM模块,TypeScript的类型,使用jest覆盖测试用例。

你可能会认为,这其实一点都不难,的确如此。

以上就是本文的所有内容,如果对你有所帮助,欢迎收藏、点赞、转发~

  • 本文译自:https://www.strictmode.io/articles/build-test-and-publish-npm-package-2022
  • 作者:strictmode.io

参考资料

[1]

这里: https://www.npmjs.com/package/digx

[2]

这里: https://github.com/hiquest/digx

[3]

注册: https://www.npmjs.com/signup

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-11-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端F2E 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
如何发布一个 TypeScript 编写的 npm 包
在这篇文章中,我们将使用TypeScript和Jest从头开始构建和发布一个NPM包。
用户5941943
2022/12/01
1.5K0
在2018年如何优雅的开发一个typescript语言的npm包?
很多时候,我们可能想要用 typescript 语言来创建一些模块,并提交到 npm 供别人使用,
小明plus
2018/11/08
4.2K1
在2018年如何优雅的开发一个typescript语言的npm包?
可能是目前最详细从零开始配置 TypeScript 项目的教程
本文出自于掘金的子弈[1],原文链接 从零开始配置 TypeScript 项目[2]。
桃翁
2020/08/10
5.2K0
可能是目前最详细从零开始配置 TypeScript 项目的教程
NPM 包开发与优化全面指南
package.json文件是 NPM 包的中央配置,定义了包的各个方面,从基本元数据到复杂的发布配置。
沉浸式趣谈
2024/10/28
1680
NPM 包开发与优化全面指南
NPM 包开发与优化全面指南
package.json文件是 NPM 包的中央配置,定义了包的各个方面,从基本元数据到复杂的发布配置。
沉浸式趣谈
2024/10/28
1500
NPM 包开发与优化全面指南
基于Typescript和Jest刷题环境搭建与使用
前几个月在公司用vue3 https://v3.vuejs.org/和ts写项目,想巩固一下基础,于是我想起了去年基于JavaScript和Jest搭建的刷题环境https://zhengjiangtao.cn/coding,不如,给它搞个加强版,结合Typescript和Jest https://jestjs.io/搞一个刷题环境https://zhengjiangtao.cn/coding-ts/,下面是我的一些使用心得,分享给大家。
江涛学编程
2022/01/25
1.2K0
基于Typescript和Jest刷题环境搭建与使用
使用typescript开发angular模块(发布npm包)
创建模块 初始化package.json文件 执行命名 npm init -y 会自动生成package.json文件如下,name默认为文件夹名称 { "name": "MZC-Ng-Api", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords"
易兒善
2018/08/21
1.3K0
使用typescript开发angular模块(发布npm包)
Jest 单元测试快速上手指南
执行 yarn jest 或者 yarn jest test/plus.spec.js 运行测试用例
木子星兮
2020/08/25
3.4K0
Jest 单元测试快速上手指南
如何在gitlab上发布npm包
大家好,我是「柒八九」。一个「专注于前端开发技术/Rust及AI应用知识分享」的Coder。
前端柒八九
2024/02/29
5910
如何在gitlab上发布npm包
【总结】超全面的前端工程化配置指南!
上图标红就是相关的工程化配置,有 Linter、Tests,Github Actions 等,覆盖开发、测试、发布的整个流程。
前端老道
2023/09/15
7590
【总结】超全面的前端工程化配置指南!
教你 30 秒发布一个 TypeScript 包到 NPM
文章读译自 The 30 second guide to publishing a typescript package to npm,部分内容有修改哈。
savokiss
2019/11/06
1.9K0
一杯茶的时间,上手 Jest 测试框架
现在让我们正式开始,茶和图雀社区精心准备的甜品更搭哦。 在项目根目录下新建src目录,存放我们的功能代码。然后创建src/dessert.js。
一只图雀
2020/04/13
1.9K0
如何做前端单元测试
对于现在的前端工程,一个标准完整的项目,通常情况单元测试是非常必要的。但很多时候我们只是完成了项目而忽略了项目测试。我认为其中一个很大的原因是很多人对单元测试认知不够,因此我写了这边文章,一方面期望通过这篇文章让你对单元测试有一个初步认识。另一个方面希望通过代码示例,让你掌握写单元测试实践能力。
政采云前端团队
2021/12/09
3.4K0
如何做前端单元测试
【架构师(第三十六篇)】 业务组件库开发之发布到 NPM
结果发现这一行 Ts 报错了,原因是 vue 的版本不一致,真实的场景下不会出现这个问题,因为真实情况下组件库用的是上级的依赖。
一尾流莺
2022/12/10
8230
【架构师(第三十六篇)】 业务组件库开发之发布到 NPM
【干货分享】微信小程序单元测试攻略
导语 本文作者是腾讯社交增值产品部高级前端工程师林毅雄,对前端开发领域颇有研究。接下来,本文将从测试框架、实战、覆盖率、踩坑等方面分享一下微信小程序的单元测试经验,希望能帮到大家。 01 写作初衷 大家先看看A公司与B公司的数据对比: 从上图可以看出,B公司的单元测试做的比较好,每百行error数也比A公司的项目低。 总体来说,单元测试有以下一些好处: 1,及早发现代码错误,提高代码质量和可维护性。 2,代码变更时可以快速进行检查。 然而要做好测试也有一定的困难: 1,花费时间长。 2,被测代码
WeTest质量开放平台团队
2021/12/17
2.9K0
纯手写实现 Vue3 & 原理解析:setup环境 & reactive函数 & effect函数(一)
本篇解析参阅 vue3源码、崔大的mini-vue、霍春阳大佬的《Vuejs设计与实现》尽可能记录我的Vue3源码阅读学习过程。我会结合自己的思考,提出问题,找到答案,附在每一篇的底部。希望大家能在我的文章中也能一起学习,一起进步,有 get 到东西的可以给作者一个小小的赞作为鼓励吗?谢谢大家!
前端达人
2022/04/18
1.8K0
使用 Rollup + TypeScript 编写库
其中,dist 目录一般是通过 Rollup 等打包器打包后的入口文件,一般具有多种格式,以不同后缀命令,如: index.cjs.js index.esm.js。lib 和 esm 目录可以是 TypeScript 编译后生成的文件,目录下的结构基本和原项目结构相同,只是后缀变为 js,lib 一般为 CommonJS 格式,esm 为 ESModule 格式。而这些是一个库最基本的需要发布的文件。
Innei
2021/12/28
2.5K0
从 0 开始手把手带你搭建一套规范的 Vue3.x 工程化项目
Vue3 跟 Vite 正式版发布有很长一段时间了,生态圈也渐渐丰富起来,作者已在多个项目中使用,总结一下:就是快!也不用担心稳定性问题,开发体验真不是一般好!还没尝试的同学可以从本文开始学习,从 0 开始手把手带你搭建一套基于 Vite + Vue3 + TypeScript 规范的前端工程化项目环境。
XPoet
2021/04/26
6.6K0
从 0 开始手把手带你搭建一套规范的 Vue3.x 工程化项目
TypeScript学习笔记(三)—— 编译选项、声明文件
compilerOptions ⽀持很多选项,常⻅的有 baseUrl 、 target 、 moduleResolution 和 lib 等。 compilerOptions 每个选项的详细说明如下:
张果
2022/10/04
2.6K0
TypeScript学习笔记(三)—— 编译选项、声明文件
TypeScript+webpack开发js库
由于近期需要开发一个比较复杂的组件,所以决定采用typescript进行开发。之前有用过typescript进行开发,用tsc打包后,再用脚本将所有js进行合并,然后再用uglyjs压缩js,但是最终报错了,原因就是合并js的顺序问题,后来用脚本指定合并js的顺序。
陨石坠灭
2020/05/22
2.1K0
推荐阅读
相关推荐
如何发布一个 TypeScript 编写的 npm 包
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验