如何 compile/build 一个不使用 NodeJS API/Module 依赖项的 TypeScript 库来支持浏览器

How to compile/build a TypeScript library that uses no NodeJS API/Module dependency to support browser

我写了一些仅使用普通浏览器 Javascript API 的代码,并且可以 运行 在浏览器 HTML 中运行良好(由 IIS 服务器或 Chrome 扩展提供服务) .现在我想通过编写一个我在市场上还没有看到的库来为社区做出贡献。然而,看看当前的解决方案,我什至不知道项目是如何构建的(WebPack/Browserify 等)。旁注:我以前从未真正使用过 NodeJS/NPM。

例如,我有一个带有主文件 AwesomeClass.ts 的 TypeScript 项目,如下所示:

import { Helper1 } from "./Helper1.js";
import { Helper2 } from "./Helper2.js";

export class AwesomeClass {
    doSomething() {
        new Helper1().doSomething();
        new Helper2().doSomething();
    }
}

当使用 tsc 构建时(我将 VS Code 用作 IDE),我可以完美地将其放入 Javascript 模块中,浏览器可以 运行 它。

import { AwesomeClass } from "./AwesomeClass.js";

// Do something with AwesomeClass

所以我的问题是,如何构建和分发 AwesomeClass?也许不需要 NPM,但来自 CDN?理想情况下,我认为我应该在 dist 文件夹中有以下输出,开发人员可以通过自己托管文件或使用 CDN 来引用它们:

在所有情况下,如果可能的话,我宁愿只将一个 js/ts 文件打包在一起,但如果不能的话也不会破坏交易(即用户将不得不下载 Helper1.jsHelper2.js,如果我不能的话)。

这是我当前的tsconfig.json

{
    "compileOnSave": true,
    "compilerOptions": {
        "noImplicitAny": true,
        "target": "ES2020",
        "module": "ES2020",
        "declaration": true
    },
    "exclude": [
        "node_modules"
    ]
}

这应该是tscongfig.json文件中的核心要求

{
    "compilerOptions": {
        "lib": ["es6", "es2020.promise", "dom", "es2020"],
        "declaration": true,
        "target": "es2020",
        "module": "es2020"
    }
}

虽然要将所有内容打包到一个文件中,但我认为您必须使用类似 webpack 的东西;但我对这个话题的了解还不够,抱歉。

您要问的问题很多,每个问题都有几个答案,所以我会尽量为您提供一些选项的概述。

将所有内容编译到一个文件中

您问的其中一件事是如何将所有内容编译到一个文件中。您可以通过两种不同的方式做到这一点,要么使用 webpack 为客户端捆绑它,要么直接使用 typescript。

  • 如果你使用打字稿,你必须将 outFile 设置为一个特定的文件,在这种情况下,它会将所有内容编译到该文件,但是你只能在 module 也设置成amd或者system,这两个都不理想。虽然这有效,但我建议您不要使用它。

  • 相反,您应该使用 webpack 将所有内容与 output 选项捆绑在一起,在这种情况下,webpack 将使用 ts-loader 为您调用打字稿,编译您的内容并将其捆绑到一个文件中。

您还应在此处注意,这仅适用于您确实希望通过网络提供服务的情况,而不适用于构建库的情况。如果你正在构建一个 npm 包,你打算让人们安装 npx packageName 这样的东西,这样你就可以像 import somePackage from some-package 一样使用它,那么你应该将你的东西编译成 [=16] =] 目录到正常的 javascript,然后让他们将其导入为 javascript。在这种情况下,您没有理由向他们提供原始打字稿。

如何构建和分发它

这实际上取决于您要构建的内容及其使用方式,但总的来说您有 2 个主要选择。

  • 您可以使用您选择的域将其托管在某个服务器上的某个位置,以便人们可以下载它。或者你可以把它放在任何地方,就像一个普通的 git 仓库,人们可以下载它。在这种情况下,你必须自己用 webpack 编译它,自己上传它,然后与其他人分享 link,即 https://example.com/downloads/awesome。或者,您可以使用 webpack 在服务器端呈现它,并将 API 公开给他们可以调用以获取您的代码的人,然后一旦他们调用 API 即 https://api.example.com/awesome 将通过 GET 请求命中你的 API,该请求将路由到 awesome 然后你调用 webpack 的编译器来捆绑你的代码服务器端。

  • 你的另一个选择是像平常一样构建你的包,编译它然后使用官方的 npm 注册表来托管你的 npm 包。使用此选项将允许人们 npx packagenpm i package 您的代码,并允许他们像 import awesome from 'awesome' 一样使用它。如果你走这条路,那么就没有必要使用 webpack,或者它取决于,因为使用它的人会将它导入到他们自己的项目中,并在需要时将其构建到他们自己的 webpack 设置和捆绑中。在这种情况下,你所要做的就是将你的打字稿编译成类似 /lib 的东西,并允许他们安装和导入它。

从你的情况来看 asking/saying 在我看来你正在尝试创建一个 npm 包,为此你所需要的只是创建包,编译你的打字稿,设置一个npm 上的帐户并将您的包推送到他们的注册表,您可以从那里让任何人安装它。为此,您也不应该关心将所有代码编译到一个文件中,因为这无关紧要,如果他们使用 import awesome from 'awesome' 那么该文件可以再次导入您自己的包中的任何其他内容,他们不会不知道。您可以 tsc 您的代码到输出目录,并让他们知道哪个是该包的默认导出。

如果你的代码必须在浏览器中 运行 那么我认为仅仅使用 typescript 是不够的,在这种情况下你将不得不使用 webpack,如果你需要的话你可能还需要 babel支持旧的浏览器和 polyfills,这是你可以添加到 webpack 的东西,然后你将使用 webpack 来编译你的包。然后,Webpack 将通过 ts-loader 调用 typescript,它将编译和打包您的代码,为您准备好用于 web。在这种情况下,您仍然需要将此代码作为一个包推送到 npm 注册表,以便其他人可以使用它。

这些选项之间的选择完全取决于它是什么、谁将使用它以及如何使用它。