编译另一个没有所有引用的打字稿输出目录

时间:2018-11-06 14:51:04

标签: node.js typescript nestjs

我在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) }

所需的结构:

  • src
    • A.ts
    • to_public
      • file.ts
  • 公共
    • file.js

我的tsconfig.json

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

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

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

  • src
    • A.ts
    • to_public
      • file.ts
  • 公共
    • A.js <-不需要
    • to_public <-最好不要
      • file.js

尽管编译后的file.js没有引用任何内容,我可以按原样使用它,但我不希望将整个src项目复制到public

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

捆绑器解决方案:

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

包裹具有“零配置”理念,这意味着(与webpack或browserify完全不同)它可以在不需要任何设置的情况下运行。

我重新创建了您的代码:

  • src
    • A.ts
    • to_public
      • file1.ts
      • file2.ts

我已经在全球范围内安装了包裹(npm install -g parcel),所以我可以运行:

parcel build src/to_public/*

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

  • src
    • // ...
  • dist
    • file1.js
    • file2.js

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

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

包裹具有一些非常好的功能。例如,它缓存编译,并且如果您反复调用它会非常快。而且,它可以与Javascript生态系统中的其他工具很好地交互。与打字稿编译器的互操作是无缝的。 Parcel将使用tsconfig中的设置,甚至默认情况下还会生成源地图。

当然,也可以为其他选择提供充分的理由。我在这里推荐包裹,因为它基本上是零成本。您只需安装该软件包,无需任何配置,它就可以正常工作。

没有捆绑软件的解决方案:

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

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

默认配置是此配置,它将由您的编辑器选择。我已将noEmit设置为true,以避免意外编译会破坏您的文件夹结构。

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.ts中使用to_public/file.ts,请导入"./server/A.ts"

答案 1 :(得分:1)

可能的解决方案 直到进一步的想法,这就是我想出的:

// to_public/definition.d.ts
export * from '../A.ts'

// to_public/file.ts
import {IA} from './definition'
function f(a:IA){ console.log(a.key) }