ts-demo-npm-cjs.gitignore.npmignorepackage.jsondependencies 与 devDependenciespackage.json 的更多信息tsconfig.jsonindex.tsindex_test.ts本章介绍如何使用 TypeScript 为 npm 包管理器创建基于 CommonJS 模块格式的包。
GitHub 仓库:
ts-demo-npm-cjs
在本章中,我们将探索 代码仓库 ts-demo-npm-cjs,它可以在 GitHub 上下载。(我特意没有将其作为包发布到 npm。)
您应该大致熟悉
CommonJS 模块 – 一种起源于服务器端 JavaScript 并为其设计的模块格式。它因服务器端 JavaScript 平台 Node.js 而流行。CommonJS 模块先于 JavaScript 内置的 ECMAScript 模块,并且仍然被工具(IDE、构建工具等)广泛使用和支持。
TypeScript 的模块 – 其语法基于 ECMAScript 模块。但是,它们通常被编译为 CommonJS 模块。
npm 包 – 通过 npm 包管理器安装的包含文件的目录。它们可以包含 CommonJS 模块、ECMAScript 模块和各种其他文件。
在本章中,我们使用 TypeScript 当前最支持的内容
.js 的 CommonJS 模块。特别是在 Node.js 上,TypeScript 当前并不真正支持 ECMAScript 模块和 .js 以外的文件扩展名。
ts-demo-npm-cjs这就是代码仓库 ts-demo-npm-cjs 的结构
ts-demo-npm-cjs/
.gitignore
.npmignore
dist/ (created on demand)
package.json
ts/
src/
index.ts
test/
index_test.ts
tsconfig.json
除了包的 package.json 之外,该仓库还包含
ts/src/index.ts:包的实际代码ts/test/index_test.ts:index.ts 的测试tsconfig.json:TypeScript 编译器的配置数据package.json 包含用于编译的脚本
ts/(TypeScript 代码)dist/(CommonJS 模块;该目录在代码仓库中尚不存在)这是放置两个 TypeScript 文件的编译结果的地方
ts/src/index.ts --> dist/src/index.js
ts/test/index_test.ts --> dist/test/index_test.js
.gitignore此文件列出了我们不想提交到 git 的目录
node_modules/
dist/
说明
node_modules/ 是通过 npm install 设置的。dist/ 中的文件是由 TypeScript 编译器创建的(稍后会详细介绍)。.npmignore当涉及到哪些文件应该和不应该上传到 npm 注册表时,我们与 git 的需求不同。因此,除了 .gitignore 之外,我们还需要文件 .npmignore
ts/
这两个区别是
dist/)。ts/)。请注意,npm 默认忽略目录 node_modules/。
package.jsonpackage.json 如下所示
{
···
"type": "commonjs",
"main": "./dist/src/index.js",
"types": "./dist/src/index.d.ts",
"scripts": {
"clean": "shx rm -rf dist/*",
"build": "tsc",
"watch": "tsc --watch",
"test": "mocha --ui qunit",
"testall": "mocha --ui qunit dist/test",
"prepack": "npm run clean && npm run build"
},
"// devDependencies": {
"@types/node": "Needed for unit test assertions (assert.equal() etc.)",
"shx": "Needed for development-time package.json scripts"
},
"devDependencies": {
"@types/lodash": "···",
"@types/mocha": "···",
"@types/node": "···",
"mocha": "···",
"shx": "···"
},
"dependencies": {
"lodash": "···"
}
}让我们来看看这些属性
type:值 "commonjs" 表示 .js 文件被解释为 CommonJS 模块。main:如果有所谓的*裸导入*,只提及当前包的名称,那么这就是将要导入的模块。types 指向一个包含当前包所有类型定义的声明文件。接下来的两个小节涵盖了其余的属性。
属性 scripts 定义了可以通过 npm run 调用的各种命令。例如,脚本 clean 通过 npm run clean 调用。之前的 package.json 包含以下脚本
clean 使用 跨平台包 shx 通过其实现 Unix shell 命令 rm 来删除编译结果。shx 支持各种 shell 命令,其优点是不需要为我们可能要使用的每个命令都安装一个单独的包。
build 和 watch 使用 TypeScript 编译器 tsc 根据 tsconfig.json 编译 TypeScript 文件。tsc 必须全局或本地(在当前包内)安装,通常通过 npm 包 typescript 安装。
test 和 testall 使用 单元测试框架 Mocha 来运行一个测试或所有测试。
prepack:此脚本在打包 tarball 之前运行(由于 npm pack、npm publish 或从 git 安装)。
请注意,当我们使用 IDE 时,我们不需要脚本 build 和 watch,因为我们可以让 IDE 构建工件。但是脚本 prepack 需要它们。
dependencies 与 devDependenciesdependencies 应该只包含导入包时需要的包。这排除了用于运行测试等的包。
名称以 @types/ 开头的包为没有类型定义的包提供 TypeScript 类型定义。没有前者,我们就不能使用后者。这些是正常的依赖项还是开发依赖项?这取决于
如果我们包的类型定义引用了另一个包中的类型定义,那么该包就是一个正常的依赖项。
否则,该包只在开发期间需要,是一个开发依赖项。
package.json 的更多信息package.json 的 npm 文档 解释了该文件的各种属性。scripts 的 npm 文档 解释了 package.json 属性 scripts。tsconfig.json{
"compilerOptions": {
"rootDir": "ts",
"outDir": "dist",
"target": "es2019",
"lib": [
"es2019"
],
"module": "commonjs",
"esModuleInterop": true,
"strict": true,
"declaration": true,
"sourceMap": true
}
}rootDir:我们的 TypeScript 文件在哪里?
outDir:编译结果应该放在哪里?
target:目标 ECMAScript 版本是什么?如果 TypeScript 代码使用了目标版本不支持的特性,那么它将被编译成只使用支持特性的等效代码。
lib:TypeScript 应该知道哪些平台特性?可能性包括 ECMAScript 标准库和浏览器的 DOM。Node.js API 的支持方式不同,通过包 @types/node 支持。
module:指定编译输出的格式。
其余选项由 tsconfig.json 的官方文档 解释。
index.ts此文件提供了包的实际功能
import endsWith from 'lodash/endsWith';
export function removeSuffix(str: string, suffix: string) {
if (!endsWith(str, suffix)) {
throw new Error(JSON.stringify(suffix)} + ' is not a suffix of ' +
JSON.stringify(str));
}
return str.slice(0, -suffix.length);
}它使用 库 Lodash 的函数 endsWith()。这就是为什么 Lodash 是一个正常的依赖项——它在运行时是必需的。
index_test.ts此文件包含 index.ts 的单元测试
import { strict as assert } from 'assert';
import { removeSuffix } from '../src/index';
test('removeSuffix()', () => {
assert.equal(
removeSuffix('myfile.txt', '.txt'),
'myfile');
assert.throws(() => removeSuffix('myfile.txt', 'abc'));
});我们可以像这样运行测试
npm t dist/test/index_test.js
t 是 npm 命令 test 的缩写。test 是 run test 的缩写(它运行 package.json 中的脚本 test)。如您所见,我们正在运行测试的编译版本(在目录 dist/ 中),而不是 TypeScript 代码。
有关单元测试框架 Mocha 的更多信息,请参阅 其主页。