Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Babel can't resolve imports in it its own source code

I have upgraded a React project to Webpack 5. The aliases are resolved by Babel. Everything was working fine with Webpack 4. But when launching webpack dev server, Babel makes the build crash because it can't resolve its own imports (inside its source code).

I've checked Babel runtime's node modules. Everything looks great:

// from the file babel/runtime/helpers/esm/toConsumableArray.js
import arrayWithoutHoles from "./arrayWithoutHoles";
import iterableToArray from "./iterableToArray";
import unsupportedIterableToArray from "./unsupportedIterableToArray";
import nonIterableSpread from "./nonIterableSpread";
export default function _toConsumableArray(arr) {
  return arrayWithoutHoles(arr) || iterableToArray(arr) || unsupportedIterableToArray(arr) 
|| nonIterableSpread();
}

The following error is displayed in my terminal:

ERROR in ../../node_modules/@babel/runtime/helpers/esm/toConsumableArray.js 4:0-52
Module not found: Error: Can't resolve './nonIterableSpread' in '/Users/MyNamee/Desktop/MyApp/node_modules/@babel/runtime/helpers/esm'
Did you mean 'nonIterableSpread.js'?
BREAKING CHANGE: The request './nonIterableSpread' failed to resolve only because it was resolved as fully specified
(probably because the origin is a '*.mjs' file or a '*.js' file where the package.json contains '"type": "module"').
The extension in the request is mandatory for it to be fully specified.
Add the extension to the request.
 @ ../../node_modules/rc-slider/es/Range.js 2:0-78 77:43-61 193:23-41 337:23-41
 @ ../../node_modules/rc-slider/es/index.js 2:0-28 6:23-28 10:0-50
 @ ../../kit/src/form/slider/index.tsx
 @ ../../kit/src/form/index.tsx 27:41-71
 @ ../shared/src/panels/card-library/index.tsx 10:15-38
 @ ./src/pages/main.tsx 12:47-93
 @ ./src/app.tsx 11:39-82
 @ ./src/index.tsx 6:38-54

I know the issue comes from aliases resolution because I don't get these errors when commenting the alias: {} part in webpack ( alias is automatically filled by babel aliases with this script):

const { isArray, size, get, find, reduce } = require("lodash");
const path = require("path");
const BabelConfig = require("../../../babel.config");

const findModuleResolverPlugin = (plugins) => {
  return (
    find(plugins, (plugin) => {
      return isArray(plugin) && plugin[0] === "module-resolver";
    }) || []
  );
};

const getModuleResolverAliasPlugin = (configuration = {}) => {
  const plugin = findModuleResolverPlugin(configuration.plugins);
  if (size(plugin)) {
    return get(plugin[1], "alias", {});
  } else {
    return {};
  }
};

const getBabelAliases = (rootPath = "") => {
  return reduce(
    getModuleResolverAliasPlugin(BabelConfig),
    (aliases, p, alias) => {
      aliases[alias] = path.resolve(rootPath, p);
      return aliases;
    },
    {}
  );
};

module.exports = getBabelAliases;

So it seems the issue is that I need to add .js at the end of every Babel/runtime imports. This is of course unrealistic. What should I do to fix this?

Here is my Babel config:

   

module.exports = {
    ignore: ["node_modules"],
      babelrcRoots: ["."],
      presets: [
        "@babel/preset-typescript",
        [
          "@babel/preset-env",
          {
            targets: {
              browsers: ["defaults"],
            },
          },
        ],
        "@babel/preset-react",
      ],
      env: {
        test: {
          plugins: [
            [
              "babel-plugin-react-css-modules",
              {
                generateScopedName: "[local]",
                filetypes: {
                  ".less": {
                    syntax: "postcss-less",
                  },
                },
              },
            ],
            //
          ],
        },
        development: {
          plugins: [
            [
              "babel-plugin-react-css-modules",
              {
                webpackHotModuleReloading: true,
                generateScopedName: "[local]___[hash:base64:5]",
                handleMissingStyleName: "warn",
                filetypes: {
                  ".less": {
                    syntax: "postcss-less",
                  },
                },
              },
            ],
            // "react-hot-loader/babel"
          ],
        },
        production: {
          plugins: [
            [
              "babel-plugin-react-css-modules",
              {
                webpackHotModuleReloading: true,
                generateScopedName: "[hash:base64]",
                filetypes: {
                  ".less": {
                    syntax: "postcss-less",
                  },
                },
              },
            ],
          ],
        },
      },
      plugins: [
        "@babel/plugin-transform-object-assign",
        "@babel/plugin-transform-regenerator",
        "@babel/plugin-transform-runtime",
        "@babel/plugin-syntax-dynamic-import",
        "@babel/plugin-transform-modules-commonjs",
        ["@babel/plugin-proposal-class-properties", { loose: true }],
        [
          "module-resolver",
          {
            cwd: "babelrc",
            root: "./",
            alias: {
              "@components": "./components/src",
              "@pages": "./pages/src",
              "@assets": "./assets",
            },
          },
        ],
      ],
    };

Any help would be greatly appreciated!

like image 285
DoneDeal0 Avatar asked Jan 27 '21 15:01

DoneDeal0


1 Answers

I was able to resolve this same issue on webpack 4 to 5 upgrade by adding the following module rule:

// see  https://github.com/webpack/webpack/issues/11467#issuecomment-808618999/
// for details
const webpack5esmInteropRule = {
  test: /\.m?js/,
  resolve: {
    fullySpecified: false
  }
};

config.module.rules = [ webpack5esmInteropRule, ...otherRules ]

If webpack is asked to require an mjs file in the compilation cycle, it needs explicit details on how to handle these file types. The usage of fullySpecified could be unique to your special case, here is more documentation on the behavior:

fullySpecified When enabled, you should provide the file extension when importing a module in .mjs files or any other .js files when their nearest parent package.json file contains a "type" field with a value of "module", otherwise webpack would fail the compiling with a Module not found error

https://webpack.js.org/configuration/module/#resolvefullyspecified

For me I believe the issue occurred because one of my node_modules was requiring an mjs file (but not with the extension), or possibly had:

{ "type": "module" }

in their package.json.

like image 64
lfender6445 Avatar answered Oct 21 '22 11:10

lfender6445