【问题标题】:compile another typescript output dir without all references编译另一个没有所有引用的打字稿输出目录
【发布时间】:2018-11-07 00:26:25
【问题描述】:

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

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

例如

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

想要的结构:

  • 源
    • A.ts
    • to_public
      • 文件.ts
  • 公开
    • file.js

我的tsconfig.json 有

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

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

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

  • 源
    • A.ts
    • to_public
      • 文件.ts
  • 公开
    • A.js
    • to_public
    • file.js

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

有什么建议吗?谢谢

【问题讨论】:

    标签: node.js typescript nestjs


    【解决方案1】:

    使用捆绑器的解决方案:

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

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

    我重新创建了您的代码:

    • 源
      • A.ts
      • to_public
        • file1.ts
        • file2.ts

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

    parcel build src/to_public/*
    

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

    • 源
      • //...
    • 分布
      • file1.js
      • file2.js

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

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

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

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

    没有捆绑器的解决方案:

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

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

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

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

    然后我将您的源目录拆分为src/server 和src/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
    

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

    【讨论】:

    • 感谢@lhk 的回复。我不是在寻找捆绑商。我希望我的 to_public 文件保持不捆绑。
    • 啊,我明白了。我认为您的解决方案已经是可行的方法。我为您配置了自动设置。它创建配置文件并负责将源/js 复制到正确的位置。
    • 有趣。谢谢,会检查一下!
    • 尝试了类似于您建议的 ts 配置的东西,它创建了 .d.ts 文件,我只是从 git 中忽略它们。现在我可以忍受这一点,当项目的这个领域发展起来时,我会尝试一些更可行的东西。非常感谢!
    【解决方案2】:

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

    // 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) }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-05
      • 1970-01-01
      • 1970-01-01
      • 2017-09-09
      • 1970-01-01
      • 1970-01-01
      • 2020-05-31
      • 2014-02-28
      相关资源
      最近更新 更多