1

I am trying to set up a proxy for my React TypeScript app using http-proxy-middleware to prevent CORS errors while developing.

I have this in my project:

proxy/proxy.tsx

import * as express from 'express'
import { createProxyMiddleware } from 'http-proxy-middleware'

const app = express()

app.use('/api', createProxyMiddleware({ target: 'localhost:8080', changeOrigin: true }))
app.listen(3000)

Then in

package.json

"main": "src/index.tsx",
"scripts": {
  ...
  "proxy": "cross-env nodemon proxy/proxy",
  ...
},

However when I run the script in the console I get this:

[nodemon] starting `node proxy/proxy src/index.tsx`
(node:28564) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
C:\*path to project*\pet-project-fe\src\index.tsx:1
import React from 'react'
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:1053:16)
    at Module._compile (internal/modules/cjs/loader.js:1101:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1157:10)
    at Module.load (internal/modules/cjs/loader.js:985:32)
    at Function.Module._load (internal/modules/cjs/loader.js:878:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
    at internal/main/run_main_module.js:17:47
[nodemon] app crashed - waiting for file changes before starting...

If I try adding type": "module" to packages.json then my actual app stops running with the error:

"C:\Program Files\nodejs\node.exe" C:\*path to npm*\npm\node_modules\yarn\bin\yarn.js run start
yarn run v1.22.4
$ cross-env NODE_ENV=development webpack-dev-server --open --content-base ./public --port 3001
internal/modules/cjs/loader.js:1153
      throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
      ^

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: C:\*path to project*\pet-project-fe\webpack.config.js
require() of ES modules is not supported.
require() of C:\*path to project*\pet-project-fe\webpack.config.js from C:\*path to project*\pet-project-fe\node_modules\webpack-cli
\bin\utils\convert-argv.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 webpack.config.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from C:\*path to project*\pet-project-fe\package.json.

    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1153:13)
    at Module.load (internal/modules/cjs/loader.js:985:32)
    at Function.Module._load (internal/modules/cjs/loader.js:878:14)
    at Module.require (internal/modules/cjs/loader.js:1025:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at WEBPACK_OPTIONS (C:\*path to project*\pet-project-fe\node_modules\webpack-cli\bin\utils\convert-argv.js:114:13)
    at requireConfig (C:\*path to project*\pet-project-fe\node_modules\webpack-cli\bin\utils\convert-argv.js:116:6)
    at C:\*path to project*\pet-project-fe\node_modules\webpack-cli\bin\utils\convert-argv.js:123:17
    at Array.forEach (<anonymous>)
    at module.exports (C:\*path to project*\pet-project-fe\node_modules\webpack-cli\bin\utils\convert-argv.js:121:15) {
  code: 'ERR_REQUIRE_ESM'
}
error Command failed with exit code 1.

I not even sure what "type" is used for and why its apparently needed in this case, so I don't really want to add random things without knowing what I'm doing. It doesn't solve the problem anyway as I get a new error then when running the proxy:

$ cross-env nodemon proxy/proxy
[nodemon] 2.0.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: tsx,json
[nodemon] starting `node proxy/proxy src/index.tsx`
(node:25420) ExperimentalWarning: The ESM module loader is experimental.
internal/modules/run_main.js:54
    internalBinding('errors').triggerUncaughtException(
                              ^

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".tsx" for C:\*path to project*\pet-project-fe\src\index.tsx
    at Loader.defaultGetFormat [as _getFormat] (internal/modules/esm/get_format.js:65:15)
    at Loader.getFormat (internal/modules/esm/loader.js:113:42)
    at Loader.getModuleJob (internal/modules/esm/loader.js:244:31)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async Loader.import (internal/modules/esm/loader.js:178:17) {
  code: 'ERR_UNKNOWN_FILE_EXTENSION'
}
[nodemon] app crashed - waiting for file changes before starting...

Not sure if this has anything to do with TypeScript, but I thought I'd mention it just in case.

What am I doing wrong here?

1 Answer 1

2

I finally got it working.

First of all I gave up on trying to get the proxy to work with a .txs filetype. So I went with .js and also used require(...) instead of import

const express = require('express')
const { createProxyMiddleware } = require('http-proxy-middleware')

const app = express()
    
app.use('/api/**', createProxyMiddleware({ target: 'http://localhost:8080', changeOrigin: true }))
app.listen(3002)

Then I realized that this all makes no sense, because if I made a query to ./api it would direct it to the actual apps port, which is port 3001, because that is where my actual app is running at.

"start": "cross-env NODE_ENV=development webpack-dev-server --open --content-base ./public --port 3001",

Making a direct call to port 3002 resulted in a failure and running them both on 3001 stopped my app from working altogether. So the solution was to add this to webpack.config.js:

config.devServer = {
  ...
  proxy: [{
    context: ['/api'],
    target: `http://localhost:3002`,
    changeOrigin: true,
  }],
};

Now hold on a second here. Why am I doing this? Why not just target port 8080 right away here any bypass that proxy.js totally... and what do you know. It works. All I had to do was add

config.devServer = {
  ...
  proxy: [{
    context: ['/api'],
    target: `http://localhost:8080`,
    changeOrigin: true,
  }],
};

to webpack.config.js.

And with that I concede that I have absolutely no idea what I am doing and all of this stuff is very confusing, error-prone and complicated. I was able to remove express and http-middleware-proxy from my dependencies (the dev server seems to get them on their own).

In conclusion I gave up trying to set up my own express proxy, realized that apparently webpack-dev-server already has proxy capabilities, resorted to just using that and left feeling defeated even though I got it working in the end.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.