├── .gitignore ├── README.md ├── dist ├── anotherFile.js ├── anotherFile.js.map ├── index.js └── index.js.map ├── package.json ├── renovate.json ├── src ├── anotherFile.ts └── index.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | yarn.lock 3 | .vscode -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node ES Modules with TypeScript 2 | 3 | Latest Typescript and Node - as bare-bone as possible example app 4 | 5 | I wanted to start a simple Node project where I can install the latest things I want and using as little compilation from Typescript as possible. 6 | 7 | I remembered Node announced [Node 13 support ESModules without experimental flags](https://medium.com/@nodejs/announcing-core-node-js-support-for-ecmascript-modules-c5d6dc29b663), checked out the [official documentation](https://nodejs.org/api/esm.html) but couldn't find a simple bare bone example, so maybe that would help someone. 8 | 9 | I've committed the dist folder as well to see how the output from Typescript. 10 | 11 | Would love suggestions on how to make it better or to point to a better example! 12 | 13 | ## What I've done (so you can tell me what I should have done...) 14 | 15 | ### Node (package.json) 16 | 17 | - `type: module`: Tell Node that `.js` files are ES Modules. (When file extensions are .mjs then `type=module` is not required in package.json) 18 | - `----experimental-specifier-resolution=node`: Tell Node to enable the automatic extension resolution and importing from directories without specify the `.js` extension.

**Note:** By default, Node wants file extensions in import see: [TypeScript doesn't include file extension in it's output](https://github.com/microsoft/TypeScript/issues/16577) 19 | 20 | ### TypeScript (tsconfig.json) 21 | 22 | - `"module": "esnext"`: Make Typescript output ES Modules 23 | - `"target": "es2020"`: Highest target (from `3.8.0`) 24 | 25 | ## Run app 26 | 27 | 1. Install latest Node (Notice that I've placed the `engines` field on `package.json` so try to make sure you have the exact version or simply delete it from `package.json` 28 | 2. Install dependencies - `yarn` 29 | 3. Compile with `tsc -w` and run Node with `nodemon` - `yarn dev` 30 | 4. You can also use `yarn compile` and `yarn start` separately 31 | 32 | ## Want to import from a commonjs package? 33 | 34 | Here is a branch of the example with including a commonjs pacakge (`pg`): 35 | 36 | https://github.com/Urigo/typescript-node-es-modules-example/commit/98304173e964713955be3a92b4e355a857376dca 37 | 38 | > The [renovate.json](https://github.com/Urigo/typescript-node-es-modules-example/blob/master/renovate.json) file has nothing to do with the project itself. It's a file to activate [RenovateBot](https://github.com/renovatebot/renovate) to automatically PR this repository when a new version of any dependency of that project has been published 39 | -------------------------------------------------------------------------------- /dist/anotherFile.js: -------------------------------------------------------------------------------- 1 | export const printSomething = async (textToPrint) => { 2 | console.log(`Inside ${textToPrint}`); 3 | }; 4 | //# sourceMappingURL=anotherFile.js.map -------------------------------------------------------------------------------- /dist/anotherFile.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"anotherFile.js","sourceRoot":"","sources":["../src/anotherFile.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,WAAmB,EAAE,EAAE;IACxD,OAAO,CAAC,GAAG,CAAC,UAAU,WAAW,EAAE,CAAC,CAAC;AACzC,CAAC,CAAC"} -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | import { printSomething } from './anotherFile'; 2 | console.log('hello world'); 3 | printSomething('new string from function in another file'); 4 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /dist/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;AAE3B,cAAc,CAAC,0CAA0C,CAAC,CAAC"} -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "scripts": { 4 | "start": "node --experimental-specifier-resolution=node dist/index.js", 5 | "dev": "tsc && concurrently \"tsc -w\" \"nodemon --experimental-specifier-resolution=node dist/index.js\"", 6 | "build": "tsc" 7 | }, 8 | "dependencies": {}, 9 | "devDependencies": { 10 | "@types/node": "14.0.4", 11 | "concurrently": "5.2.0", 12 | "nodemon": "2.0.4", 13 | "typescript": "3.9.3" 14 | }, 15 | "engines": { 16 | "node": "14.3.0" 17 | }, 18 | "license": "MIT" 19 | } 20 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/anotherFile.ts: -------------------------------------------------------------------------------- 1 | export const printSomething = async (textToPrint: string) => { 2 | console.log(`Inside ${textToPrint}`); 3 | }; -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { printSomething } from './anotherFile'; 2 | 3 | console.log('hello world'); 4 | 5 | printSomething('new string from function in another file'); -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "esnext", 4 | "target": "es2020", 5 | "strict": true, 6 | "sourceMap": true, 7 | "outDir": "dist" 8 | }, 9 | "include": ["src/**/*"] 10 | } 11 | --------------------------------------------------------------------------------