使用TypeScript 3构建到dist/文件夹时保留src/文件夹结构

115

我有一个TypeScript nodejs服务器,其结构如下:

tsconfig.json
package.json
src/
    middleware/
    utils/
    index.ts
dist/
    middleware/
    utils/
    index.js

当使用TypeScript 2时,我能够将我的项目从src/转译到dist/文件夹,并拥有一个与我的目录结构相似的镜像版本以供使用。

随着TypeScript 3的发布,他们引入了项目引用并改变了代码转译成输出目录的方式。现在tsc会以嵌套的方式将输出放在dist/文件夹中,类似于这样:

dist/
    src/
        middleware/
        utils/
        index.js

我的 tsconfig.json 文件如下:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "allowJs": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "resolveJsonModule": true,
    "declaration": false,
    "outDir": "dist/",
    "lib": [
      "es7",
      "dom"
    ]
  },
  "include": [
    "src/"
  ]
}

我该如何配置TypeScript,使其将我的src/文件夹作为镜像复制到dist/文件夹中?

10个回答

121

当我最初转换为TypeScript项目时,我也遇到了类似的问题。我同样设置了resolveJsonModule: true,并且src目录被复制到输出的dist目录中。

根本原因在于我的一个源文件required了项目根目录下的package.json文件。一旦我把它删除,tsc就不再将src添加到dist目录中了。

简而言之,请确保您不要require src目录之外的文件。

相关FAQ请参阅:https://github.com/Microsoft/TypeScript/wiki/FAQ#why-does---outdir-moves-output-after-adding-a-new-file


6
行!但是为什么?为什么resolveJsonModule会使tsc将输出到/dist/src而不是/dist?这没有任何意义。 - s.meijer
9
因为它使得 package.json(一个“JsonModule”)可以被导入,这强制 rootDir 自动设置为包含所有源代码的目录(包括 package.json),现在 src 目录不再是 rootDir 而是子目录,因此在输出中反映出来。更多信息和链接以查看 TypeScript 的负责人所说的内容,请访问 https://dev59.com/klMI5IYBdhLWcg3wn85d#61467483。 - Inigo
谢谢这个。当你想要一个结构,例如./src/和./typings,但不希望在./dist中有./src时,它也会产生相同的输出...长话短说,只要你在./src中引用./typings,它就会被包含,因此./src将被保留。T_T - y_nk
4
在我的情况下,"tsconfig.json"文件中的"include": ["**/*.ts"]被修改为"include": ["src/**/*.ts"] - Pavel Staselun
你也可以尝试使用require语法而不是import来解决你的问题。在我的情况下,我正在导入一个service-account.json文件,将import改为require可以使我的ts构建正确输出。 - undefined

68

输出目录的结构由compilerOptions中的rootDir控制。请参见此处的文档,将其设置为./src应该可以解决问题。

{
  "compilerOptions": {
    "rootDir": "src",
    ...
  },
  "include": [
    "src/"
  ]
}

5
实际上,这只会在这种情况下交换问题。OP正在导入package.json,因此如果您将rootDir更改为src,则会得到正确的outDir结构,但会出现编译错误,因为您有源代码位于rootDir之外。有关更多信息和链接,请参见https://dev59.com/klMI5IYBdhLWcg3wn85d#61467483,其中包括TypeScript老板对此的说法。 - Inigo
使用 rootDir 参数解决了我在导入本地 .ts 库时遇到的问题。 - Felipe
我遇到了Inigos提到的问题 - 修复了src而不是dist中的问题,但出现了编译问题 :o( - Jeremy

24

单纯从TypeScript 2升级到3本身不应该改变行为;如果我们可以确认它改变了行为,那可能是个bug。无论如何,请检查rootDir编译选项是否指向您的src目录而不是父目录,因为rootDir下的结构是在outDir下镜像的。


我已经添加了我的tsconfig.json以帮助澄清。该项目的配置围绕使用“include”键来指定src/目录。我刚刚确认,使用此配置,Typescript 2编译器将简单地将src/镜像到dist/中,但是Typescript 3编译器将自动包含package.json和嵌套在dist/中的src/文件夹。尝试将rootDir指向src/会失败,因为package.json文件不在其中。 - nfadili
根据您提供的信息,我无法重现此行为。如果您能够发布一个可以重现问题的存储库,我会进行查看。否则,我只能建议您尝试从项目中删除一些内容,直到问题消失,然后您就会知道是什么导致了它。 - Matt McCutchen
11
我能够确定原因。似乎将resolveJsonModule:true添加到我的tsconfig.json中会导致tsc以不同的方式输出dist/目录。我仍然不完全清楚它为什么会这样,但这似乎是一些Github问题的谈论焦点:https://github.com/Microsoft/TypeScript/issues/25216和https://github.com/Microsoft/TypeScript/issues/24744谢谢您的帮助,Matt! - nfadili
1
这一点在编译器选项页面上根本不清楚。 - trusktr

20

除了指定compilerOptions.outDir之外,还需要在tsconfig.json中指定compilerOptions.rootDir

{
  "compilerOptions": {
     // ...
    "outDir": "dist",
    "rootDir": "./",
    // ...
  }
}

然后在包含tsconfig.json文件的文件夹内运行:$ tsc -b

注意:如果您想将非嵌套文件夹的文件结构包含在tsconfig.json文件所在的文件夹中,应使用compilerOptions.rootDir


-b标志是什么?找不到文档中的--build和--baseUrl,但没有--b。 - Jeremy
1
抱歉晚了。-b 标志是对 --build 标志 的别名。 - rplaurindo
谢谢!它有效。你也可以在tsconfig.json中设置"composite": true选项,而不是使用-b命令行标志。 - Craig Wayne
我不知道。我会试试看。谢谢。这种情况下只需运行 tsc 命令吗? - rplaurindo
1
@CraigWayne 抱歉,但那样做并不正常。当我们使用行命令时,"-b"标志是必需的。 - rplaurindo

5

我使用符号链接来实现这个。它可以让你不直接引用根目录下的文件而达成同样的效果。例如:

  1. /src 目录创建一个链接到 package.json 文件:
ln -s ../package.json ./details.json
  1. 在你的TypeScript文件中参考details.json
import { version } from './details.json';

exports.handler = async function ( event: Event ) {
  console.log( `lambda version v${version}` );
  1. 沉浸在 dist 扁平化的文件结构中:
$ tsc

$ tree dist 
dist
├── index.d.ts
├── index.js
└── details.json

0 directories, 3 files

1
如果您正在尝试将位于/scr/mydir/hello.ts的TypeScript文件编译为/dist/mydir/hello.js,但该文件始终被创建在/dist/hello.js,那么您可以在/src/another.ts中添加另一个TypeScript文件。这样,两个编译后的文件将分别放置在/src/another.js/src/mydir/hello.js中。请记住,在您的tsconfig.json中,outDir必须设置为./dist

1

如果您在include选项下有多个条目,请确保它们被解决。

"include": ["src", "tests"],

例如,如果找不到tests,则src目录将不存在于outDir中。

0

我相信增加一个文件夹,例如包含测试文件的spec文件夹也可以解决这个问题。虽然这并没有回答原始问题,但在这种情况下提到它是有趣的。


0

-2

你可以在 ./src 文件中将文件导入路径从 src/entities/Post -> ../entities/Post 进行更改。

这会更改 dist 文件夹中的导入方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接