SyntaxError: Unexpected token import- Node.js - node.js

I am trying to code split my app with webpack but webpack is not creating the chunks for my dynamic imports. I found one source here:
https://davidea.st/articles/webpack-typescript-code-split-wont-work
which said I needed to change my module property in my tsconfig file from "commonjs" to "esnext" so the typescript compiler won't reduce my dynamic import statements to Promises, resulting in Webpack not knowing they are dynamic imports and thus not creating dynamic chunks. I followed this and during the compilation I can see the chunks now being created! Whoooo! However, the compiler bugs out, with the error in the title of my question, when trying to resolve the import statements in my express app as those ES imports are not being reduced to something node understands anymore. Does anyone know if this is possible to achieve? I want to use ES imports statements in node but without having the module property in my tsconfig file set to "commonjs". I really don't want to have to refactor all the imports statements to commonJS require statements.
tsconfig.json:
{
"compilerOptions": {
"target": "es6",
"module": "esnext",
"allowJs": true,
"sourceMap": false,
"inlineSourceMap": true,
"strict": true,
"strictNullChecks": true,
"noImplicitAny": true,
"noImplicitReturns": true,
"noEmitOnError": true,
"removeComments": false,
"forceConsistentCasingInFileNames": true,
"suppressImplicitAnyIndexErrors": false,
"jsx": "react",
"watch": false,
"moduleResolution": "node"
}}
node version: v8.11.3
I am using ts-node in my npm script to execute my server code:
"start": "webpack && ts-node -- ./src/service/index.ts --env=prod"
My .babelrc looks like the following:
{
"presets": [
"react",
"stage-3",
[
"env",
{
"modules": false
}
]
],
"plugins": [
"react-hot-loader/babel",
"syntax-dynamic-import"
]
}

By default, ts-node uses the compiler options in the tsconfig.json file in the working directory; you can specify a different tsconfig.json file with the --project option. The tsconfig.json file you use with ts-node must have module set to commonjs (or omitted, in which case ts-node defaults it to commonjs) in order for the on-the-fly compilation to generate modules that Node can understand. You may need to use separate tsconfig.json files for the server code you run with ts-node and the client code you package with Webpack.

Related

NPM Package: Conflicts between ES libraries

I am currently trying to split a monorepo which includes the API and all the front-end stuff into different repo (at least have the API appart).
To achieve this, I had to first split the common and angular core libraries into two privates NPM packages. I manage to handle this easily for the angular core library using the CLI.
For the API (express 4.17.2/NodeJS 14.16/TypeScript 4.6), I'm not able to compile properly because of some ES conflicts. It's been two days I've been searching everywhere and the ES configuration seems to be very obscure because I don't find any related documentation.
I tried to follow this example to compile with pure ESM package without success. The first commend explain well the struggle.
Here is my problem:
I did a library named common-lib, it contains mainly services, interfaces and constants...
This library is exported from api/node_modules/#project/project-common-lib/dist/#project/project-common-lib/index.js
export * as constants from './constants/index.js';
export * as enums from './enums/index.js';
export * as interfaces from './interfaces/index.js';
export * as services from './services/index.js';
and installed into the api as an NPM package.
The package.json of the library contains this related information
"exports": "./dist/#project/project-common-lib/index.js",
"types": "./dist/#project/project-common-lib/index.d.ts",
"engines": {
"node": ">=14.16"
},
"type": "module",
And finally, this is my tsconfig.json:
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"allowJs": true,
"removeComments": true,
"resolveJsonModule": true,
"typeRoots": [
"./node_modules/#types"
],
"sourceMap": true,
"outDir": "dist",
"strict": true,
"lib": [
"esnext"
],
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"moduleResolution": "Node",
"skipLibCheck": true,
},
"include": [
"src/**/*"
],
"exclude": ["node_modules"],
}
Once I run npx ts-node-esm src/main.ts I get this error:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/project/project-api/node_modules/#project/project-common-lib/dist/#project/project-common-lib/index.js
require() of ES modules is not supported.
require() of /home/project/project-api/node_modules/#project/project-common-lib/dist/#project/project-common-lib/index.js from /home/project/project-api/dist/app/models/adminUser.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/project/project-api/node_modules/#project/project-common-lib/package.json.
I tried to remove the "type": "module" and to rename the index.js to .csj without any success.
I've come to a frustrating point where I can't make it work trying different configuration not documented so not really knowing what I'm doing.
For example I tried to change the ts compiler options to es5, es6... the "type" to "commonjs"... I have tried many things and I always end up with an error.
One way I get the above error, the other way removing the "type": "module" I get this error:
export * as constants from '#project/project-common-lib/dist/#project/project-common-lib/constants/index.js';
^^^^^^
SyntaxError: Unexpected token 'export'
Can someone clarify me how is it supposed to work ?
I don't use any es5 import const ... require (''). All the API use ES6 syntax with import ... from ...
How can it be so difficult to export/import some basic constants, services and interfaces ?

Cannot find module or its corresponding type declarations (monorepo)

Im trying to install, run and learn https://github.com/CMSgov/design-system, but after installation (yarn install), i can't execute (yarn develop) since im getting error for actually any import from #cmsgov/design-system in packages/docs.
There is something probably that needs to be added or modified in tsconfig.json and this is how it looks like:
{
"compilerOptions": {
"target": "es2015",
"jsx": "react",
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"baseUrl": ".",
"skipLibCheck": true
},
"include": ["packages/**/src/**/*"]
}
Ive tried to manually install package inside docs using:
npm install --save #cmsgov/design-system
but without success. Node versions i've tried to compile with are:
18.12.1
and 16.19.0
Because there are no types in DefinetlyTyped, i've also created decs.d.ts in root:
declare module "#cmsgov/design-system"
Is there maybe something related to lerna settings or something else.
Thanks in advice

Building Fullstack Application with ts-node

I am currently having a problem in the build process of my typescript application.
Currently this application is an api using the express framework.
It is run in development mode via ts-node and compiled with tsc:
npm run dev
node --inspect=0.0.0.0:9229 -r ts-node/register -r tsconfig-paths/register ./src/index.ts
npm run build
tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json --silent
I now want to integrate a react ssr client to this application server.
So far no problem my first solution was to make a monorepo style architecture with different packages.json and build my react application independently then give the generated statics files to express.
The problem appeared when integrating react-router into my architecture.
Indeed I can no longer just serve static files I need to serve a static router from react router.
I'm not going to dwell on why I need my application to be isomorphic (I leave you this more than complete comment to answer the question: https://stackoverflow.com/a/36623117/11312725) but when I 'integrate my react to my server the build no longer works.
Whether it's ts-node or tsc, the build is down..
tsconfig.json
{
"compilerOptions": {
// Project options
"allowJs": true, // Allow JavaScript files to be imported inside your project, instead of just .ts and .tsx files
"declaration": false, // Generate .d.ts files for every TypeScript or JavaScript file inside your project
"lib": ["es2019", "es2020", "es2021", "esnext"], // Specifies which default set of type definitions to use ("DOM", "ES6", etc)
"module": "commonjs", // Sets the module system for the program. "CommonJS" for node projects.
"noEmit": false, // Do not emit compiler output files like JavaScript source code, source-maps or declarations.
"outDir": "./dist", // .js (as well as .d.ts, .js.map, etc.) files will be emitted into this directory
"rootDir": "./", // The longest common path of all non-declaration input files
"sourceMap": true, // Enables the generation of sourcemap files
"target": "es2019", // Target environment
// Module resolution
"baseUrl": "./", // Sets a base directory to resolve non-absolute module names
"esModuleInterop": true, // fixes some issues TS originally had with the ES6 spec where TypeScript treats CommonJS/AMD/UMD modules similar to ES6 module
"moduleResolution": "node", // Pretty much always node for modern JS. Other option is "classic"
"paths": {
"#application/*": ["src/application/*"],
"#domain/*": ["src/domain/*"],
"#infrastructure/*": ["src/infrastructure/*"],
"#presentation/*": ["src/presentation/*"],
"#test/*": ["test/*"],
"#/*": ["src/*"]
}, // A series of entries which re-map imports to lookup locations relative to the baseUrl
"typeRoots": ["../node_modules/#types", "node_modules/#types", "src/types"],
// Advanced
"forceConsistentCasingInFileNames": true, // TypeScript will issue an error if a program tries to include a file by a casing different from the casing on disk
"listEmittedFiles": false, // Print names of generated files part of the compilation
"listFiles": false, // Print names of files part of the compilation
"resolveJsonModule": true, // Allows importing modules with a ‘.json’ extension, which is a common practice in node projects
"skipLibCheck": true, // Skip type checking of declaration files
"traceResolution": false, // Report module resolution log messages
// Experimental
"experimentalDecorators": true, // Enables experimental support for decorators
"emitDecoratorMetadata": true, // Enables experimental support for emitting type metadata for decorators which works with the module
// Strict checks
"strict": true, // Enable all strict type-checking options
// "allowUnreachableCode": false, // Pick up dead code paths
// "alwaysStrict": true, // Parse in strict mode and emit "use strict" for each source file
// "noImplicitAny": true, // Raise error on expressions and declarations with an implied 'any' type
// "noImplicitThis": true, // Raise error on 'this' expressions with an implied 'any' type
// "strictFunctionTypes": true, // Enable strict checking of function types
// "strictNullChecks": true, // Enable strict null checks
"strictPropertyInitialization": false, // Enable strict checking of property initialization in classes
// Linter Checks
"noFallthroughCasesInSwitch": true, // Report errors for fallthrough cases in switch statement
"noImplicitReturns": true, // Report error when not all code paths in function return a value
"noUnusedLocals": true, // Report errors on unused local variables
"noUnusedParameters": true, // Report errors on unused parameters
"pretty": true // Stylize errors and messages using color and context
},
"exclude": ["node_modules", "dist"], // Specifies an array of filenames or patterns that should be skipped when resolving include
"compileOnSave": false // Compile on save
}
tsconfig.build.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"sourceMap": false,
"inlineSourceMap": true,
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["src/**/*.test.ts", "src/**/*.spec.ts", "test/**/*.test.ts", "test/**/*.spec.ts", "node_modules", "dist"]
}
I already tried to build my entire application with webpack but it is a non-sense because webpack is used for frontend app.

typescript 4.4.4: tsconfig paths not resolving as expected

my tsconfig.json
{
"compilerOptions": {
"target": "ES2018",
"module": "CommonJS",
"lib": ["ESNext", "ESNext.AsyncIterable"],
"skipLibCheck": true,
"sourceMap": true,
"outDir": "./dist",
"moduleResolution": "node",
"removeComments": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"resolveJsonModule": true,
"baseUrl": "./",
"paths": {
"#/*": ["src/*"],
"#config": ["src/config"],
}
},
"exclude": ["node_modules"],
"include": ["./src/**/*.ts"]
}
I am pretty sure there is nothing wrong in tsconfig paths because I even get path autocompletion from my IDE. however when my code is compiled (tsc --project tsconfig.json)
import { PRODUCTION } from '#config';
// or
import { PRODUCTION } from '#/config';
I get following javascript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const _config_1 = require("#config");
console.log(_config_1.PRODUCTION);
//# sourceMappingURL=index.js.map
but javascript doesn't understand what "#" is therefore I get "module not found" error. How can I solve this problem?
See this issue on TypeScript's GitHub project: Module path maps are not resolved in emitted code (#10866)
tl;dr
TypeScript won't rewrite your module paths
paths was designed to help TypeScript understand path aliases used by bundlers
You'll either need to:
use a bundler, such as webpack, and configure its own path maps
use a build time tool, such as tspath, to rewrite the paths
modify the runtime module resolver, with something like module-alias
I've been stuck with this issue for 2 whole days trying to find something that works. #Wing's answer is correct, if you're using plain tsc with no other tools, then Node won't know what you mean by #/ (or whatever your alias is) in your imports.
I've tried a few different approaches and I've found one that required no configuration.
What worked:
At the end of my journey I came across a package that is still actively being maintained: tsc-alias. The only thing I needed to do was add && tsc-alias -p tsconfig.json to my tsc command in my build script and voilà, it works. So your full command would be something like tsc -p tsconfig.json && tsc-alias -p tsconfig.json.
What I tried that didn't work:
I tried "module-alias" and I couldn't get it to work.
I tried "tsconfig-paths" as suggested by #AlexMorley-Finch with no luck as well. The package seems to be finding the modules but there seems to be a bug that causes the path of the modules not to be mapped correctly (there's an issue open for it).
I then came across tscpaths. This package requires you to explicitly specify your project, src dir and out dir. I got it to work after figuring out my outdir needed to be ./build/src instead of ./build. The caveat here: this package hasn't been touched since May 2019 as of writing this.

require is not defined in node command line

I have a typescript project that was compiling and running perfectly fine but now I get the error
ReferenceError: require is not defined whenever I try to run node.
I'm not completely sure this is a Typescript issue because when I run a simple plain js file using require I get the same error. I'm a little confused since require should be defined when using node index.js isn't it?
tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"esModuleInterop": true,
"moduleResolution": "node",
"noImplicitAny": false,
"removeComments": true,
"allowSyntheticDefaultImports": true,
"outDir": "dist/",
"sourceMap": false
},
"include": ["src/"],
"exclude": ["node_modules", "**/*.spec.ts"]
}
The problem was that I had enabled experimental support for ES6 Modules in the package.json.
Removing the option: "type": "module" from package.json solved all my problems.
See here: ECMAScript modules on Official NODEjs docs

Resources