Have been wrestling with this for a couple days now... Writing a TypeScript, React, Express, Node, Webpack and Babel project. First, I was getting the SyntaxError: Cannot use import statement outside a module
error trying to use import
syntax in my src/server/index.ts
file and serving it with node src/server/index.ts
in my start
script.
but this works: nodemon src/server/index.ts
as a start
script.
Can anyone explain to me why nodemon
works but node
and ts-node
do not?
tsconfig.json
{
"ts-node": { /* EDIT: these ts-node options apparently are very important... */
"compilerOptions": { /* if i remove these lines, even _with_ nodemon, I get the first error: */
"module": "commonjs" /* `SyntaxError: Cannot use import statement outside a module` */
}
},
"compilerOptions": {
"target": "ES5",
"module": "ESNext",
"moduleResolution": "nodenext",
"lib": [
"DOM",
"ESNext"
],
"jsx": "react-jsx",
"noEmit": true,
"isolatedModules": true,
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"allowJs": true
},
"include": [
"src/client/**/*"
]
}
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const paths = {
DIST: path.resolve(__dirname, 'dist'),
SRC_ENTRY: path.resolve(__dirname, 'src', 'client', 'Index.tsx'),
HTML_TEMPLATE: path.resolve(__dirname, 'src', 'client', 'index.html'),
};
module.exports = {
mode: 'development',
entry: paths.SRC_ENTRY,
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: 'bundle.js',
path: paths.DIST,
},
module: {
rules: [
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
use:
{
loader: 'babel-loader',
},
},
],
},
plugins: [
new HtmlWebpackPlugin({ template: paths.HTML_TEMPLATE }),
new ForkTsCheckerWebpackPlugin(),
],
};
src/server/index.ts
import express, { Express } from 'express'; /* <-- this is the first import where the error is thrown */
import path from 'path';
export const app: Express = express();
/* ... */
Tried many different fixes including the outdated and popular "add "type": "module"
to your package.json
file, as well as changing around my "target", "moduleResolution", "module", "allowJS" and basically any other relevant property in my tsconfig.json
...
I have provided my code above, but for the tl;dr, npm i --save-dev nodemon
if you don't already have it globally installed and change your "start" script in your package.json
to nodemon your/path/to/file.ts
and you can use import
syntax in your server file to serve.
To reiterate.. this problem was fixed by adding the ts-node
options to my tsconfig.json
and installing and implementing nodemon
instead of node. I just don't understand why that fixes it and was hoping someone would help me out with that...
here is the outdated but classic SO solution with "type": "module" in package.json
: ol' faithful
as well as an "updated" solution from 2022 that also did not work for me: most recent