I'd like to make use of the project references features in TypeScript 3.1. The directory structure of my project originally looks like this after the compilation:
.
├── A
│ ├── a.ts
│ ├── dist
│ │ ├── A
│ │ │ └── a.js
│ │ └── Shared
│ │ └── shared.js
│ └── tsconfig.json
└── Shared
├── dist
│ └── shared.js
├── shared.ts
└── tsconfig.json
Contents of the Shared
directory:
shared.ts
:
export const name = "name";
tsconfig.json
:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"outDir": "dist",
"strict": true
}
}
Contents of the A
directory:
a.ts
:
import { name } from "../Shared/shared";
console.log(name);
tsconfig.json
:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"outDir": "dist",
"strict": true
}
}
And I could successfully run it by running node dist/A/a.js
in the A directory.
What I didn't like about this was that everything was getting copied into A's output directory. I thought project references are here to fix this problem.
To enable project references, I added the following line to Shared/tsconfig.json
.
"composite": true
And the following to A/tsconfig.json
:
"references": [
{ "path": "../Shared" }
]
Now when I compile, the directory structure is like the following, which is what I expected:
.
├── A
│ ├── a.ts
│ ├── dist
│ │ └── a.js
│ └── tsconfig.json
└── Shared
├── dist
│ ├── shared.d.ts
│ └── shared.js
├── shared.ts
└── tsconfig.json
However, when I run the node dist/a.js
in the A
directory, I get the following Error:
module.js:538
throw err;
^
Error: Cannot find module '../Shared/shared'
The reason is that in the generated a.js
file, the reference to the imported module is not resolved properly:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var shared_1 = require("../Shared/shared");
console.log(shared_1.name);
Is there a way to get it working without putting all output files into the same directory?
Or, is there a better way to organize my project to make use of project references?
Project references are a new feature in TypeScript 3.0 that allow you to structure your TypeScript programs into smaller pieces. By doing this, you can greatly improve build times, enforce logical separation between components, and organize your code in new and better ways.
The include and exclude properties take a list of glob-like file patterns. The supported glob wildcards are: * matches zero or more characters (excluding directory separators) ?
The tsconfig.json file specifies the root files and the compiler options required to compile the project. JavaScript projects can use a jsconfig.json file instead, which acts almost the same but has some JavaScript-related compiler flags enabled by default.
Include – It is a property that allows you to include a list of TypeScript files using the glob wildcards pattern. “include”: [ “src/**/*” ] Exclude – It is a property that allows you to exclude a list of TypeScript files using the glob wildcards pattern.
Indeed, getting relative import paths to work for both your source files and your output files is a pain. The official recommendation, if I understand it correctly, is to set up a master output directory for the entire composite project and have Shared
and A
subdirectories inside it, so the source files and output files can have the same relative layout. I don't know if that's what you meant you didn't want to do.
The only other option I know of is to have each component import the other components (in your case, you just have A
importing Shared
) using non-relative imports that point to output files (i.e., A/a.ts
would import a path like Shared/dist/shared
). Since you are using non-relative imports, the same import path appearing in either a source file or the corresponding output file resolves to the same target output file. Imports will not resolve in your IDE until you've built the composite project: this is a known limitation. Since tsc
doesn't rewrite imports, you'll need to set up your runtime environment and/or use a bundler to handle the non-relative imports and, if necessary, set the baseUrl
and paths
TypeScript compiler options to match.
I'll be happy to help you through the details of either approach if needed; just let me know where you get stuck.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With