首页 > 解决方案 > 编译另一个没有所有引用的打字稿输出目录

问题描述

我在 TS 中有一个服务器项目,我使用 ts-node 来运行它。我有另一个文件夹,称为public我托管静态文件的地方。

我需要的是一种在to_public文件夹中写入 .ts 文件的方法,这样它们将使用来自服务器的接口进行类型检查,但在不转换所有定义文件的情况下输出为 .js。

例如

// A.ts
export interface A { key: string }
// file.ts
import {A} from '../A.ts'
function f(a:A){ console.log(a.key) }

所需结构:

tsconfig.json

   "compilerOptions": {
      ...
     "outDir": "../../public/js/",
   }
  "include": [
   "../../src/public_ts"
  ],

当 file.ts 没有引用任何东西时,这很完美。

但是当我从 中引用任何内容时src,会复制整个文件夹结构。这是实际结果:

虽然编译后file.js没有引用任何东西,我可以按原样使用它,但我不希望我的整个 src 项目被复制到public.

有什么建议吗?谢谢

标签: node.jstypescriptnestjs

解决方案


使用捆绑器的解决方案:

您的场景似乎是捆绑器的一个很好的用例。这是一个分析您的代码并提取所有依赖项以生成单个输出文件的工具。流行的选择是webpackbrowserifyparcel。这意味着从 A 导入的依赖项将包含在为您的公共脚本生成的输出文件中。

Parcel 具有“零配置”理念,这意味着(与 webpack 或 browserify 非常不同)它无需设置即可工作。

我重新创建了您的代码:

  • 源代码
    • A.ts
    • to_public
      • 文件1.ts
      • 文件2.ts

我已经全局安装了包裹(npm install -g parcel),所以我可以运行:

parcel build src/to_public/*

这会查看您的to_public文件夹并将所有脚本捆绑在其中。Parcel 知道 typescript 并自动调用 typescript 编译器。生成的脚本被复制到一个新dist/目录。您的文件夹现在如下所示:

  • 源代码
    • //...
  • 距离
    • 文件1.js
    • 文件2.js

对于您的 to_public 文件夹之外的文件,您需要 typescript 的完全支持,但您不需要编译它们。为此,您可以将noEmit标志添加到您的 compilerOptions。

{
    "compilerOptions": {
        "module": "commonjs",
        "noEmit": true
    },
    "exclude": [
        "node_modules"
    ]
}

Parcel 有一些非常好的功能。例如,它会缓存编译,如果您重复调用它,它会非常快。此外,它还可以与 Javascript 生态系统中的其他工具很好地交互。与 typescript 编译器的互操作是无缝的。Parcel 将使用 tsconfig 中的设置,甚至默认生成源映射。

当然,也可以为替代方案提出强有力的案例。我在这里推荐包裹,因为它基本上是零成本的。您只需安装软件包,无需任何配置,它就可以正常工作。

没有捆绑器的解决方案:

如果您想避免使用捆绑程序,您可以使用多个编译器配置。问题是打字稿需要了解您正在使用的接口。它可以通过查看源代码或读取定义文件来做到这一点。因此,您的答案是一个可行的解决方案,但如果定义是自动创建的,那就太好了。我已经设置了三个编译器配置:

  • 用于一般语法检查
  • 生成定义文件
  • 编译公共 javascript

默认配置是这个,它将由您的编辑器选择。我已设置noEmittrue, 以避免意外编译会弄乱您的文件夹结构。

tsconfig.json
{
    "compilerOptions": {
        "module": "commonjs",
        "noEmit": true,
        "rootDir": "src"
    }
}

然后我将您的源目录拆分为src/serversrc/to_public. 如果没有这种拆分,就很难从编译器中排除文件(您必须手动列出它们)。

这是生成声明文件的配置。它有标志 emitDeclarationOnly ,输出目录是你的公共 javascript 文件夹:

definitions.json
{
    "compilerOptions": {
        "module": "commonjs",
        "declaration": true,
        "emitDeclarationOnly": true,
        "noResolve": true,
        "rootDir": "src",
        "outDir": "src/to_public"
    }
}

如果您运行上面的配置,它将从您的服务器端代码生成声明。这可用于最后的编译器配置。它读取您的 to_public 文件夹中的文件并将它们编译到输出目录。这里重要的编译器标志是noResolve,这将避免将声明文件复制到输出文件夹。

public_scripts.json
{
    "compilerOptions": {
        "module": "commonjs",
        "noResolve": true,
        "rootDir": "src/to_public",
        "outDir":"public/"
    },
    "exclude": ["src/server"]
}

你现在可以编译你的代码

tsc -p definitions.json
tsc -p public_scripts.json

请注意导入路径。如果你想使用server/A.tsin to_public/file.ts,那么你导入"./server/A.ts"


推荐阅读