CommonJs Modules Flashcards
How are commonJs modules exported?
Identifiers are exported via setting the exports
property on a global called module.
function absolute(num: number) { if (num < 0) return num * -1; return num; } module.exports = { pi: 3.14, squareTwo: 1.41, phi: 1.61, absolute, };
“CommonJS Syntax” (typescriptlang.org). Retrieved May 26, 2023.
How are commonJs modules imported?
Files can be imported via a require
statement:
const maths = require("./maths"); maths.pi;
Or you can simplify a bit using the destructuring feature in JavaScript:
const { squareTwo } = require("./maths"); squareTwo;
“CommonJS Syntax” (typescriptlang.org). Retrieved May 26, 2023.
How can you reduce the friction between CommonJS and ES Modules ?
There is a mis-match in features between CommonJS and ES Modules regarding the distinction between a default import and a module namespace object import. TypeScript has a compiler flag to reduce the friction between the two different sets of constraints with esModuleInterop.
“CommonJS and ES Modules interop” (typescriptlang.org). Retrieved May 26, 2023.
What is module resolution?
Module resolution is the process of taking a string from the import
or require
statement, and determining what file that string refers to.
“TypeScript’s Module Resolution Options” (typescriptlang.org). Retrieved May 26, 2023.
List all TypeScript module resolution strategies
TypeScript includes two resolution strategies: Classic
and Node
. Classic
, the default when the compiler option module is not commonjs
, is included for backwards compatibility. The Node
strategy replicates how Node.js works in CommonJS
mode, with additional checks for .ts
and .d.ts
.
“TypeScript’s Module Resolution Options” (typescriptlang.org). Retrieved May 26, 2023.
Relative vs. Non-relative module imports
Module imports are resolved differently based on whether the module reference is relative or non-relative.
A relative import s one that starts with /
, ./
or ../
. It is resolved relative to the importing file and cannot resolve to an ambient module declaration.
A non-relative import can be resolved relative to baseUrl, or through path mapping. They can also resolve to ambient module declarations.
“Relative vs. Non-relative module imports” (typescriptlang.org). Retrieved May 29, 2023.
Explain classic module resolution strategy
This used to be TypeScript’s default resolution strategy. Nowadays, this strategy is mainly present for backward compatibility.
A relative import will be resolved relative to the importing file. So import { b } from "./moduleB"
in source file /root/src/folder/A.ts
would result in the following lookups:
/root/src/folder/moduleB.ts /root/src/folder/moduleB.d.ts
For non-relative module imports, however, the compiler walks up the directory tree starting with the directory containing the importing file, trying to locate a matching definition file.
For example:
A non-relative import to moduleB such as import { b } from "moduleB"
, in a source file /root/src/folder/A.ts
, would result in attempting the following locations for locating “moduleB”:
/root/src/folder/moduleB.ts /root/src/folder/moduleB.d.ts /root/src/moduleB.ts /root/src/moduleB.d.ts /root/moduleB.ts /root/moduleB.d.ts /moduleB.ts /moduleB.d.ts
“Classic” (typescriptlang.org). Retrieved May 29, 2023.
Explain Node.js module resolution strategy
For Relative paths are fairly straightforward. As an example, let’s consider a file located at /root/src/moduleA.js
, which contains the import var x = require("./moduleB");
Node.js resolves that import in the following order:
- Ask the file named
/root/src/moduleB.js
, if it exists. - Ask the folder
/root/src/moduleB
if it contains a file namedpackage.json
that specifies a “main” module. In our example, if Node.js found the file/root/src/moduleB/package.json
containing{ "main": "lib/mainModule.js" }
, then Node.js will refer to/root/src/moduleB/lib/mainModule.js
. - Ask the folder
/root/src/moduleB
if it contains a file namedindex.js
. That file is implicitly considered that folder’s “main” module.
For non-relative module names, Node will look for your modules in special folders named node_modules
. A node_modules
folder can be on the same level as the current file, or higher up in the directory chain. Node will walk up the directory chain, looking through each node_modules
until it finds the module you tried to load.
“How Node.js resolves modules” (typescriptlang.org). Retrieved May 30, 2023.
Explain TypeScript’s node resolution strategy
TypeScript will mimic the Node.js run-time resolution strategy in order to locate definition files for modules at compile-time. To accomplish this, TypeScript overlays the TypeScript source file extensions (.ts
, .tsx
, and .d.ts
) over Node’s resolution logic. TypeScript will also use a field in package.json
named types
to mirror the purpose of "main"
- the compiler will use it to find the “main”
definition file to consult.
“How TypeScript resolves modules” (typescriptlang.org). Retrieved May 30, 2023.
How can you trace module resolution?
Invoking the compiler with traceResolution
tsc --traceResolution
“Tracing module resolution” (typescriptlang.org). Retrieved May 31, 2023.