向 NPM 发布软件包本身并不是一个特别困难的挑战。但是,配置你的 TypeScript 项目以取得成功可能是一个挑战。你的软件包能在大多数项目上运行吗?用户能否使用类型提示和自动完成功能?它能与 ES Modules (ESM) 和 CommonJS (CJS) 风格的导入一起使用吗?
阅读完本篇文章后,你将了解如何使你的 TypeScript 包在任何(或大多数)JavaScript 和 TypeScript 项目中更易于访问和使用,包括浏览器支持!
创建 TypeScript 项目
如果你正在阅读本文,那么你很可能已经建立了一个 TypeScript 项目。如果这样做,你可能想跳到后续步骤或留下来检查是否存在差异。
让我们首先创建基本 Node.js 项目并添加 TypeScript 作为开发依赖项:
shell
npm init -y
npm install typescript --save-dev
你可能希望在 src
文件夹中构建代码。因此,让我们在其中创建包的入口点:
shell
mkdir src
touch src/index.ts
现在,Node.js 和浏览器不理解 TypeScript,因此我们需要设置 tsc (TypeScript 编译器)将 TypeScript 代码编译为 JavaScript。让我们通过运行以下命令将 tsconfig.json
文件添加到我们的项目中:
shell
npx tsc --init
如果我们现在运行 npx tsc
,它会扫描我们的文件夹并在与 .ts
文件相同的目录中创建 .js
文件(这是不可取的)。让我们在运行之前添加更好的配置,以免造成混乱。
将以下行添加到 tsconfig.json
:
js
{
"compilerOptions": {
// ... Other options
"rootDir": "./src", // Where to look for our code
"outDir": "./dist", // Where to place the compiled JavaScript
}
我们还向 package.json
添加一个"build"脚本:
js
{
"scripts": {
"build": "tsc"
}
}
如果我们现在运行 npm run build
,一个新的 dist
文件夹将出现,其中包含已编译的 JavaScript。如果你使用的是 Git,请确保将 dist 文件夹添加到 .gitignore
中。
设置 tsc 以获得最佳开发者体验
我们已经可以将 TypeScript 编译为 JavaScript。但是,如果你按原样将其发布到 npm,则只能在其他 JavaScript 项目中无缝使用它。此外,默认目标配置是"es2016",而现代浏览器最多仅支持"es2015"。那么让我们解决这个问题吧!
首先,让我们将目标(target)更改为 es2015
(或 es6
,因为它们是相同的)。 esModuleInterop 默认为 true
。让我们保持原样,因为它通过允许 ESM 样式导入来提高兼容性。
我们使用 TypeScript 都有一个原因:类型!但是,如果你现在就构建并发布你的软件包,那么它将不会发布任何类型。让我们通过将 declaration 设置为 true
来解决这个问题。这将与 .js
文件一起生成声明文件(.d.ts
)。仅凭这一点,你的软件包就能在 TypeScript 项目中使用,甚至在 JavaScript 项目中也能提供类型提示。
声明文件在改善支持和开发人员体验方面已经发挥了很大作用。然而,我们可以通过添加 declarationMap 来更进一步。这样,将生成源映射 (.d.ts.map
),以将我们的声明文件 (.d.ts
) 映射到我们的原始 TypeScript 源代码 (.ts
)。这意味着代码编辑器在使用"转到定义"时可以转到原始 TypeScript 代码,而不是编译后的 JavaScript 文件。
当我们这样做时,sourceMap 将添加源映射文件 (.js.map
),这些文件允许调试器和其他工具在实际处理发出的 JavaScript 文件时显示原始 TypeScript 源代码。
使用 declarationMap 或 sourceMap 意味着我们还需要将源代码与软件包一起发布到 npm。
综上所述,这是我们最终的 tsconfig.json
文件:
js
{
"compilerOptions": {
"target": "es2015",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"rootDir": "./src",
"outDir": "./dist",
"sourceMap": true,
"declaration": true,
"declarationMap": true,
}
}
package.json
这里的事情要简单得多。当用户导入包时,我们需要指定包的入口点。因此,让我们将 main
设置为 dist/index.js
。
除了入口点之外,我们还需要指定主要类型声明文件。在这种情况下,这将是 dist/index.d.ts
。
我们还需要指定随包一起提供哪些文件。当然,我们需要发送构建的 JavaScript 文件,但由于我们使用的是 sourceMap
和 declarationMap
,所以我们还需要发送 src
。
这是包含所有内容的参考 package.json
:
json
{
"name": "the-greatest-sdk", // Your package name
"version": "1.0.3", // Your package version
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc"
},
"keywords": [], // Add related keywords
"author": "liblab", // Add yourself here
"license": "ISC",
"files": ["dist", "src"],
"devDependencies": {
"ts-node": "^10.9.1",
"typescript": "^5.0.4"
}
}
发布到 NPM
发布到 NPM 并不困难。我强烈建议你查看官方说明,但以下是一般步骤:
- 确保你的
package.json
设置正确。 - 构建项目(如果你遵循指南,则使用
npm run build
)。 - 如果你还没有登录,请使用
npm login
向 npm 进行身份验证(你需要一个 npm 帐户)。 - 运行
npm publish
。
请记住,如果你更新软件包,则需要在再次发布之前增加 package.json
中的 version
选项。
有更复杂的(和推荐的)方法来进行发布,例如使用 GitHub Action 和 releases,特别是对于开源包,但这超出了本文的范围。