7

I'm trying to build a small project node.js + ts using webpack.

tsconfig.json
{
  "compilerOptions": {
    "lib": ["ESNext"],
    "target": "ES2020",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "esModuleInterop": true,
    "types": ["node"],
    "allowSyntheticDefaultImports": true,
    "rootDir": "./"
  },
}

I added it to the package.json line "type": "module"

webpack.config.ts
import * as path         from 'path';
import * as webpack      from 'webpack';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

const PATHS = {
  entry:  path.resolve(__dirname, 'src/server/index.ts'),
  output: path.resolve(__dirname, 'dist'),
};

const config: webpack.Configuration = {
  target:  'node',
  entry:   PATHS.entry,
  output:  {
    path:     PATHS.output,
    filename: 'bundle.js',
  },
  module:  {
    rules: [
      {
        test:    /\.ts(x?)$/,
        use:     'ts-loader',
        exclude: '/node_modules/',
      },
    ],
  },
  resolve: {
    extensions: ['*', '.js', '.jsx', '.json', '.ts', '.tsx'],
  },
};

export default config;

By running the command "build": "webpack --config config/webpack.config.ts --mode development", I get an error :

[webpack-cli] Failed to load '/node_esm/webpack.config.ts' config [webpack-cli] TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /node_esm/webpack.config.ts

I tried adding to my config.json "ts-node": { "esm": true} this didn't help solve my problem. What do I need to do in order to build an application using webpack?

  • node: v16.18.1
  • ts-loader: v9.4.2
  • typescript: v4.9.4
  • webpack: v5.75.0
  • webpack-cli: 5.0.1

UPD I've tried change tsconfig.The first option is to open your tsconfig.json file and look for compilerOptions. Set target to "ES5" and module to "CommonJS" (or completely remove the module option).

{
  "compilerOptions": {
    "target": "ES5",
    "module": "CommonJS",
    "moduleResolution": "NodeNext",
    "esModuleInterop": true,
    "types": ["node"],
    "allowSyntheticDefaultImports": true,
    "rootDir": "./"
  }
}

the error remained the same. The second option is to add settings for ts-node:

You can keep "module": "ESNext" for tsc, and if you use webpack, or another build tool, set an override for ts-node.

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "esModuleInterop": true,
    "types": ["node"],
    "allowSyntheticDefaultImports": true,
    "rootDir": "./"
  },
  "ts-node": {
    "compilerOptions": {
      "module": "CommonJS"
    }
  }
}

also at this point I tried to add

{
  "compilerOptions": {
    "module": "ESNext" // or ES2015, ES2020
  },
  "ts-node": {
    // Tell ts-node CLI to install the --loader automatically, explained below
    "esm": true
  }
}

as stated in the typescript documentation. The third option is to install the tsconfig-paths package it also didn't help.in all cases, the error remained the same as it was written before.

package.json
{
  "name": "node_esm",
  "version": "1.0.0",
  "description": "",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "watch": "webpack --config config/webpack.config.ts --mode development --watch",
    "build": "webpack --config config/webpack.config.ts --mode development"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cross-env": "^7.0.3",
    "express": "^4.18.2"
  },
  "devDependencies": {
    "@types/express": "^4.17.15",
    "@types/node": "^18.11.18",
    "@types/webpack": "^5.28.0",
    "circular-dependency-plugin": "^5.2.2",
    "clean-webpack-plugin": "^4.0.0",
    "nodemon": "^2.0.20",
    "ts-loader": "^9.4.2",
    "ts-node": "^10.9.1",
    "tsconfig-paths": "^4.1.2",
    "tsconfig-paths-webpack-plugin": "^4.0.0",
    "typescript": "^4.9.4",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.1",
    "webpack-dev-server": "^4.11.1",
    "webpack-node-externals": "^3.0.0"
  }
}
qwerty
  • 193
  • 4
  • 14
  • 1
    You need to start the webpack build with `ts-node`. Did you read https://webpack.js.org/configuration/configuration-languages/#typescript? – morganney Jan 22 '23 at 14:26
  • @morganney yes, I tried to do as it is written in the documentation, but it didn't help. – qwerty Jan 22 '23 at 15:11
  • How are you starting the webpack build? – morganney Jan 22 '23 at 15:32
  • @morganney I wrote the command how I run webpack in question. – qwerty Jan 22 '23 at 16:27
  • 1
    Then you don't read documentation clearly. You're not using `ts-node`. – morganney Jan 22 '23 at 18:05
  • @morganney what is it about? I might have missed something in the documentation. I tried specifying ts-node in tsconfig. – qwerty Jan 23 '23 at 05:20
  • @Phil yes, im intsall all deps. I tried all 3 options, the error remained the same – qwerty Jan 24 '23 at 05:46
  • @Phil Of course I tried them separately – qwerty Jan 24 '23 at 06:01
  • Thanks for updating. The error you're seeing is from `ts-node`. See [Can't run my Node.js Typescript project TypeError \[ERR_UNKNOWN_FILE_EXTENSION\]: Unknown file extension ".ts" for /app/src/App.ts](https://stackoverflow.com/q/62096269/283366). At this stage I'd be weighing up how useful Webpack is for this project. You could also save _some_ pain and just use JS for the Webpack config – Phil Jan 24 '23 at 06:54
  • Is there a reason you're using a web bundler to build your server-side app? – Phil Jan 24 '23 at 07:12
  • Not trying to troll, but why put yourself through this pain? I've managed an in-house Webpack app for years and I'm happy to say that I will never do it again. Webpack is intended for libraries and not so much applications. I suggest something like Next.js or Create React App. – eezing Jan 24 '23 at 23:22
  • can you pls provide the code repo or create a reproducible code base? – Yilmaz Jan 24 '23 at 23:52
  • @eezing OP's title says _"Build express server"_. The question isn't even tagged with [tag:reactjs]. Laughably, both Next.js and Create React App also build on Webpack so it's not clear at all where you're going with your comment about libraries – Phil Jan 24 '23 at 23:53

1 Answers1

4

The main issue is that Webpack uses the ts-node API, not the CLI so you need to configure the node loader appropriately.

I got it working using the following configuration.

package.json

"scripts": {
  "build": "NODE_OPTIONS='--loader ts-node/esm' webpack --mode development"
},

See the ts-node documentation on Native ECMAScript modules...

If you are not using our CLI, pass the loader flag to node.

You may want to use something like cross-env or env-cmd if you plan on building this on Windows.


Note: I didn't need anything special in tsconfig.json. No ts-node section is required since that only applies to the CLI.


Aaaaand, I just found this troubleshooting guide in the Webpack CLI reference

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for ./webpack.config.ts

You might encounter this error in the case of using native ESM in TypeScript (i.e. type: "module" in package.json).

webpack-cli supports configuration in both CommonJS and ESM format, at first it tries to load a configuration using require(), once it fails with an error code of 'ERR_REQUIRE_ESM' (a special code for this case) it would try to load the configuration using import(). However, the import() method won't work with ts-node without loader hooks enabled (described at TypeStrong/ts-node#1007).

To fix the error above use the following command:

NODE_OPTIONS="--loader ts-node/esm" npx webpack --entry ./src/index.js --mode production

The SEO on that page must be terrible. Hopefully linking it here helps boost it a little.

Phil
  • 157,677
  • 23
  • 242
  • 245