Project references are a new feature of TypeScript 3.0 that allows the structure of a TypeScript application to be broken up into smaller components. This improves build times (opening Composite automatically turns on incremental compilation), forces logical separation of components, and organizes your code better.

Pain points caused by not using project references

Consider the following code structure: Suppose this is a project that does not separate the front and back ends, and the client directory stores the client code. The server code stored in the server directory; Common stores common code, such as util methods, which client/index.ts and server/index.ts refer to.

The __test__ directory holds some unit test code that references SRC /client/index.ts and SRC /server/index.ts, respectively.

There is only one tsconfig.json, and its main configuration is “outDir”: “./dist”, which is to store the compiled files in the dist folder in the root directory.

. ├ ─ ─ the SRC │ ├ ─ ─ client │ │ ├ ─ ─ but ts │ ├ ─ ─ common │ │ ├ ─ ─ but ts │ ├ ─ ─ server │ │ ├ ─ ─ but ts ├ ─ ─ __test__ │ ├ ─ ─ Client. Spec. Ts │ ├ ─ ─ for server spec. Ts ├ ─ ─ package. The json ├ ─ ─ tsconfig. Json └ ─ ─ yarn. The lock ├ ─ ─ README. The mdCopy the code

Compiled by TSC command, the dist file is roughly as follows.

. ├ ─ ─ dist │ ├ ─ ─ the SRC │ │ ├ ─ ─ client │ │ ├ ─ ─ common │ │ ├ ─ ─ server │ ├ ─ ─ __test__Copy the code

Through the code structure above, several pain points can be listed:

  • We would like files under SRC to be compiled directly into the dist directory, but __test__ makes this impossible.

  • We can’t build client side code, or server side code, alone.

  • We don’t want __test__ to be built into the dist directory.

Retrofit the above items using engineering references

From the above code, we can see that a single tsconfig.json file is not flexible enough to handle personalized compilation configuration, so we tried to add a tsconfig.json file to each directory. ①②③④⑤

. ├ ─ ─ the SRC │ ├ ─ ─ client │ │ ├ ─ ─ but ts │ │ ├ ─ ─ tsconfig. Json/ / 1.│ ├ ─ ─ common │ │ ├ ─ ─ but ts │ │ ├ ─ ─ tsconfig. Json/ / 2.│ ├ ─ ─ server │ │ ├ ─ ─ but ts │ │ ├ ─ ─ tsconfig. Json/ / 3.├ ─ ─ __test__ │ ├ ─ ─ the client. The spec. The ts │ ├ ─ ─ for server spec. Ts │ ├ ─ ─ tsconfig. Json/ / 4.├ ─ ─ package. Json ├ ─ ─ tsconfig. Json/ / 5.└ ─ ─ yarn. The lock ├ ─ ─ the README, mdCopy the code

Next, modify the root tsconfig.json file, i.e. ⑤.

{ "compilerOptions": { "target": "es5", "module": "commonjs", "strict": true, // "outDir": "./dist" Turn off the outDir option, i.e. do not specify the input directory "composite": true in the root configuration, // use composite, which means that the project can be referenced, and support incremental compilation of "declaration": True // To use the Composite option, declaration}} must be enabled.Copy the code

Next, the configuration of ① and ③ is roughly the same and will not be described here.

{ "extends": ".. /.. Json ", // first import ⑤ "compilerOptions": {"outDir": ".. /.. /dist/client" // specify input directory}, "references": [{"path": "../common"}]Copy the code

For ②, because it doesn’t reference any other modules, you just need to configure outDir as follows:

{
  "extends": ".. /.. /tsconfig.json"."compilerOptions": {
    "outDir": ".. /.. /dist/common"}}Copy the code

For ④, to prevent the test files from being compiled into the dist directory, let the compiled files also be stored in __test__.

{
  "extends": ".. /tsconfig.json"."references": [{ "path": ".. /src/client" }, { "path": ".. /src/server"}}]Copy the code

compile

Now that the configuration is written, we can compile happily. To support project references, TypeScript uses build construction mode, which can build individual projects and dependencies automatically. We build server-side applications, where -b is short for Build. Verbose prints some build information.

tsc -b src/server --verbose
Copy the code

When the server side is built, the Server folder and the common folder it depends on are compiled into the dist directory, so when you compile the client, common does not have to be compiled again, which increases compilation efficiency. In addition, it generates incremental compilation files in each directory so that the next compilation is faster.

In addition, you can clean files that a project has built with the –clean argument. Here’s how to clean files generated by __test__.

tsc -b __test__ --clean
Copy the code

conclusion

The advantages of engineering references are as follows:

  • Resolved the structure of the output directory

  • The construction problem of a single project is solved

  • Incremental compilation improves compilation efficiency

Json in the SRC directory, and tsconfig.json in other directories, such as the server directory.

{
  "extends": ".. /tsconfig-base"."compilerOptions": {
    "removeComments": false."outFile": ".. /.. /built/local/server.js"."preserveConstEnums": true."types": ["node"]},"references": [{"path": ".. /compiler" },
    { "path": ".. /jsTyping" },
    { "path": ".. /services"}]."files": [
    "types.ts"."utilities.ts"."protocol.ts"."scriptInfo.ts"."typingsCache.ts"."project.ts"."editorServices.ts"."packageJsonCache.ts"."session.ts"."scriptVersionCache.ts"]}Copy the code