Maintain src/ folder structure when building to dist/ folder with Typescript 3

TypescriptBuildTscTranspiler

Typescript Problem Overview


I have a typescript nodejs server with this structure:

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

When using Typescript 2, I was able to transpile my project from the src/ to a dist/ folder and have a mirror image of my directory structure to work with.

With the release of Typescript 3 they have introduced project references and changed the way code is transpiled into an output directory. Now tsc outputs to the dist/ folder in a nested way like this:

dist/
    src/
        middleware/
        utils/
        index.js

My tsconfig.json is:

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

How can I configure Typescript to output my src/ folder as a mirror image into a dist/ folder?

Typescript Solutions


Solution 1 - Typescript

I had a similar problem when initially converting to a Typescript project. I also set resolveJsonModule: true and the src directory was copied to the output dist directory.

The underlying reason is that one of my source files required package.json at the root of the project. Once i removed that, tsc no longer added src to the dist directory.

In short, make sure you are not requiring files outside of your src directory.

Explanatory FAQ here: https://github.com/Microsoft/TypeScript/wiki/FAQ#why-does---outdir-moves-output-after-adding-a-new-file

Solution 2 - Typescript

The structure of the output directory is controlled by the rootDir of the compilerOptions. See documentation here, setting it to ./src should solve the issue.

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

Solution 3 - Typescript

The upgrade from TypeScript 2 to 3 by itself shouldn't have changed the behavior; if we can confirm that it did, that may be a bug. In any case, check that the rootDir compiler option points to your src directory and not to the parent directory, because the structure under the rootDir is what is mirrored under the outDir.

Solution 4 - Typescript

In addition to specifying compilerOptions.outDir, specify compilerOptions.rootDir in tsconfig.json.

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

Then run: $ tsc -b inside the folder where the tsconfig.json file is.

Solution 5 - Typescript

The problem appears after adding the resolveJsonModule: true to tsconfig.json

Solution 6 - Typescript

If you're trying to compile a typescript file at /scr/mydir/hello.ts to /dist/mydir/hello.js but the file keeps getting created at /dist/hello.js, what you can do is to add another typescript file at /src/another.ts. That way the two compiled files will go to /src/another.js and /src/mydir/hello.js. Rememver, in your tsconfig.json, outDir must be set to ./dist

Solution 7 - Typescript

I've used a symlink to accomplish this. It neatly allows you to reference root-level files without referencing them directly. For example:

  1. From /src, create a link to package.json:
ln -s ../package.json ./details.json
  1. Refer to details.json in your TypeScript file:
import { version } from './details.json';

exports.handler = async function ( event: Event ) {
  console.log( `lambda version v${version}` );
  1. Bask in the grandeur of dist's flattened file structure:
$ tsc

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

0 directories, 3 files

Solution 8 - Typescript

In case you have multiple entries under the include option, make sure they are resolved.

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

For example, if tests is not found, the src directory will not be present in the outDir.

Solution 9 - Typescript

you can change file import from src/entities/Post -> ../entities/Post in file in ./src

this changes the import in the dist folder.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnfadiliView Question on Stackoverflow
Solution 1 - TypescriptLuke WView Answer on Stackoverflow
Solution 2 - TypescriptMorlo MbakopView Answer on Stackoverflow
Solution 3 - TypescriptMatt McCutchenView Answer on Stackoverflow
Solution 4 - TypescriptrplaurindoView Answer on Stackoverflow
Solution 5 - TypescriptOmega CubeView Answer on Stackoverflow
Solution 6 - TypescriptGilbertView Answer on Stackoverflow
Solution 7 - TypescriptrotarydialView Answer on Stackoverflow
Solution 8 - TypescriptSoyal7View Answer on Stackoverflow
Solution 9 - Typescriptakash mauryaView Answer on Stackoverflow