score:10

Accepted answer

Well, it turns out that these errors are all cause by create-react-app's default webpack.config.js. If you navigate to code node_modules/react-scripts/config/webpack.config.js you fill find a line include: paths.appSrc which basically limits Babel to the src/ folder of the react app itself.

That means, if you've yarn linked a folder outside of it, Babel will not transpile it to normal JS, and thus React cannot use it.

There are two hacky solutions, but I would like a better one.

  1. Manually (or via a build script) delete the include: paths.appSrc line from react-scripts every time you install a node module
  2. Make a script that copies the external directory into your React src directory every time the external directory is modified.

I really wish there were an official way around this...

score:0

The other answers to this question suggest removing the include in react-scripts' webpack.config (either with craco or react-app-rewired). I found this worked with yarn start, but when I made a production build with yarn build I got the error Uncaught ReferenceError: exports is not defined at runtime.

Instead of removing the include, I had to add the other project's src in addition to the existing src directory. Here's my config-overrides.js to be used with react-app-rewired.

For react-scripts 4:

const path = require("path");

module.exports = function override(config) {
    // See https://stackoverflow.com/questions/65893787/create-react-app-with-typescript-and-npm-link-enums-causing-module-parse-failed.
    config.module.rules[1].oneOf[2].include = [
        path.join(__dirname, './src'),
        path.join(__dirname, '../backend/src')
    ];
    return config
}

For react-scripts 5:

const path = require("path");

module.exports = function override(config) {
    // See https://stackoverflow.com/questions/65893787/create-react-app-with-typescript-and-npm-link-enums-causing-module-parse-failed.
    config.module.rules[1].oneOf[3].include = [
        path.join(__dirname, './src'),
        path.join(__dirname, '../backend/src')
    ];
    return config
}

score:0

My craco config, does the same thing as Phil Mo's version as far as I can tell but is easier to understand

module.exports = {
    webpack: {
        configure: (webpackConfig) => {
            webpackConfig.module.rules[0].oneOf.find(
                ({ test: t }) =>
                    t != null &&
                    !Array.isArray(t) &&
                    t.toString().includes('ts')
            ).include = undefined

            return webpackConfig
        }
    }
}

score:3

It is possible to automatically remove the include path setting mentioned in the other answer using react-app-rewired.

The following config-overrides.js works for react-scripts:4.0.3 and causes babel to also transpile files in node-modules.

// config-overrides.js
module.exports = function override(config, env) {
  // This line might break with other react-script versions
  delete config.module.rules[1].oneOf[2].include
  return config
}

score:6

Based on @foxtrotuniform6969's answer, i created a @cracro/craco configuration that gets rid of the misbehaving setting by itself.

module.exports = {
  webpack: {
    configure: (webpackConfig) => ({
      ...webpackConfig,
      module: {
        ...webpackConfig.module,
        rules: webpackConfig.module.rules.map((rule) => {
          if (!rule.oneOf) return rule;
          return {
            ...rule,
            oneOf: rule.oneOf.map((ruleObject) => {
              if (
                !new RegExp(ruleObject.test).test('.ts') ||
                !ruleObject.include
              )
                return ruleObject;
              return { ...ruleObject, include: undefined };
            }),
          };
        }),
      },
    }),
  },
};

https://gist.github.com/PhilippMolitor/00f427d12a9c5bca84309058d88846b7


Related Query

More Query from same tag