TLDR; module
in tsconfig.json tells the compiler what syntax to use for the modules in the emitted .js files. Frequently used values are "commonjs"
(require/module.exports) or "ES2015"
(import/export keywords), but there are other module systems. module
affects the module syntax of emitted code while target
affects the rest.
- What does
Specify module code generation
mean?
"module"
in tsconfig.json tells the Typescript (TS) compiler what module syntax
to use when the files are compiled to Javascript (JS).
When you set "module"
to "commonjs"
in tsconfig.json, this means that the modules in the compiled .js files will use the commonJS (CJS) syntax, so var x = require(...)
and module.exports = {...}
to import and export.
If you changed "module"
to "ES2015"
for example, the compiled code would use the import
and export
keywords used in ES2015 module syntax. For an overview of the other syntaxes you can take a look here.
There are several different module systems with CJS and the
native ES Module (ESM) format probably being the ones most widely used.
What to choose depends on your requirements. If it's for a server-side project
that uses Node.js then probably CJS, if it's for an Angular front-end application
than perhaps ESM (or their own NgModules but that's going beyond scope here).
A somewhat similar situation is library and package designs and how you would
like to expose them to consumers. This depends on what sort of users are going to consume
the code, what are they working with (browser, Node) and which of the module systems
is best suited for the job?
ES Modules are now the built-in standard for importing/exporting modules in JS but back when there was no native solution other module systems were designed: This is why we also have CJS, AMD and UMD modules around. They are not all obsolete, CJS is still used a lot in Node.js and the AMD module loader for example allows non-JS imports which can be useful in some cases.
Nowadays, all the modern browsers and Node 13.2.0+ support the ESM format (see this page for compatibility data and more background on modules).
But then we have options like esnext
Newer JS versions sometimes contain more features for module import/export.
setting "module"
to "ESNext"
enables support for these features which often are not added to official specifications yet. Such as the import(...)
expression which is a dynamic import.
Does it mean if I put module option as commonjs, then the compiler compiles the code to commonjs?
The "module"
setting does not affect the rest of the code, "target"
is used for that instead and specifies what JS version the outputs should be compatible with.
This has been explained in other threads, I'm just adding it here for clarity.
Say you want to use require(...)
and module.exports = {...}
in a Node project but also want the code to utilise ES2015 features like let
and const
in the code (for readability/performance/other reasons).
In this case you would set "module"
to "commonjs"
and "target"
to "ES2015"
in tsconfig.
Anyway the purpose of compiler is to compile the code into browser understandable syntax(commonjs).
Yes, the compiler has to turn TS code into JS that a browser understands.
However, JS is no longer limited to browsers, Node runs in other environments (servers) for example. CJS was in fact intended as a server-side module format while AMD modules were/are used for browser imports/exports.
So does it mean the module type you give tells the compiler in what syntax the code is written?
It tells the compiler in what syntax to write the modules in the output .js files