reactjswebpackrelayyarnpkg-v2

Error when trying to run application with babel-plugin-relay and Webpack 5


I'm having a hard time to get Relay working within my monorepo. I have set everything up with Yarn workspaces (version berry) and Webpack 5.

When I'm trying to run one of my apps, I get the error:

MacroError: The macro you imported from "undefined" is being executed outside the context of 
compilation with babel-plugin-macros. This indicates that you don't have the babel plugin 
"babel-plugin-macros" configured correctly. Please see the documentation for how to configure 
babel-plugin-macros properly: 
https://github.com/kentcdodds/babel-plugin-macros/blob/master/other/docs/user.md

I also get 2 warnings:

Compiled with problems:

WARNING in ../../../.yarn/cache/babel-plugin-macros-npm-2.8.0-451367d7e7-59b09a21cf.zip/node_modules/babel-plugin-macros/dist/index.js 78:24-31

Critical dependency: require function is used in a way in which dependencies cannot be statically extracted


WARNING in ../../../.yarn/cache/import-fresh-npm-3.3.0-3e34265ca9-2cacfad06e.zip/node_modules/import-fresh/index.js 32:31-48

Critical dependency: the request of a dependency is an expression

I have already checked the sources of both, the babel-plugin-marcos and the babel-plugin-relay package and I could locate the lines of error (read here for further information) but I can't figure out what is going on.

My setup

package.json

{
  "name": "@apps/app1",
  "version": "0.0.1",
  "private": true,
  "packageManager": "yarn@3.2.0",
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "dependencies": {
    "@chakra-ui/react": "^1.8.8",
    "@emotion/react": "^11.9.0",
    "@emotion/styled": "^11.8.1",
    "framer-motion": "^6.2.10",
    "react": "18.0.0",
    "react-dom": "18.0.0",
    "react-relay": "^13.2.0"
  },
  "devDependencies": {
    "@babel/core": "^7.17.9",
    "@babel/plugin-transform-runtime": "^7.17.0",
    "@babel/preset-env": "^7.16.11",
    "@babel/preset-react": "^7.16.7",
    "@babel/preset-typescript": "^7.16.7",
    "@babel/runtime": "^7.17.9",
    "@types/babel__core": "^7",
    "@types/babel__plugin-transform-runtime": "^7",
    "@types/babel__preset-env": "^7",
    "@types/events": "^3",
    "@types/node": "^17.0.24",
    "@types/react": "^18.0.3",
    "@types/react-dom": "^18.0.0",
    "@types/react-relay": "^13.0.2",
    "@types/yup": "^0.29.13",
    "babel-loader": "^8.2.4",
    "babel-plugin-relay": "^13.2.0",
    "buffer": "^6.0.3",
    "crypto-browserify": "^3.12.0",
    "events": "^3.3.0",
    "graphql": "^16.3.0",
    "html-webpack-plugin": "^5.5.0",
    "http-proxy-middleware": "^2.0.4",
    "module": "^1.2.5",
    "os-browserify": "^0.3.0",
    "path-browserify": "^1.0.1",
    "pnp-webpack-plugin": "^1.7.0",
    "process": "^0.11.10",
    "stream-browserify": "^3.0.0",
    "string_decoder": "^1.3.0",
    "ts-node": "^10.7.0",
    "typescript": "^4.6.3",
    "util": "^0.12.4",
    "web-vitals": "^2.1.4",
    "webpack": "^5.72.0",
    "webpack-cli": "^4.9.2",
    "webpack-dev-server": "^4.8.1"
  },
  "scripts": {
    "start": "webpack serve --config webpack.dev.config.ts --stats-error-details"
  }
}

webpack.dev.config.ts

import * as path from "path";
import { Configuration as WebpackConfiguration, ProvidePlugin } from "webpack";
import { Configuration as WebpackDevServerConfiguration } from "webpack-dev-server";
const HtmlWebpackPlugin = require("html-webpack-plugin");
const PnpWebpackPlugin = require("pnp-webpack-plugin");

interface Configuration extends WebpackConfiguration {
  devServer?: WebpackDevServerConfiguration;
}

const config: Configuration = {
  mode: "development",
  output: {
    publicPath: "/",
  },
  entry: path.resolve(__dirname, "src/index.tsx"),
  resolve: {
    plugins: [PnpWebpackPlugin],
    extensions: [".tsx", ".ts", ".js", "jsx"],
    fallback: {
      path: require.resolve("path-browserify"),
      stream: require.resolve("stream-browserify"),
      util: require.resolve("util/"),
      crypto: require.resolve("crypto-browserify"),
      buffer: require.resolve("buffer/"),
      events: require.resolve("events/"),
      string_decoder: require.resolve("string_decoder/"),
      os: require.resolve("os-browserify/browser"),
      fs: false,
      module: false
    },
  },
  resolveLoader: {
    plugins: [PnpWebpackPlugin.moduleLoader(module)],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "public/index.html"),
    }),
    new ProvidePlugin({ process: "process/browser.js" }),
  ],
  module: {
    rules: [
      // { test: /\.(css)$/, use: ["style-loader", "css-loader"] },
      { test: /\.(svg|ico|png|gif|jpg|jpeg)$/, type: "asset/ressource" },
      {
        test: /\.(ts|tsx)?$/i,
        // exclude: /node_modules/,
        use: {
          loader: require.resolve("babel-loader"),
          options: {
            generatorOpts: { compact: false },
            presets: [
              "@babel/preset-env",
              ["@babel/preset-react", { runtime: "automatic" }],
              "@babel/preset-typescript",
            ],
          },
        },
      },
    ],
  },
  devtool: "inline-source-map",
  devServer: {
    static: path.join(__dirname, "public"),
    historyApiFallback: true,
    port: 4000,
    open: true,
    hot: true,
  },
};

export default config;

babel.rc

{
  "presets": ["@babel/preset-env", ["@babel/preset-react", { "runtime": "automatic" }], "@babel/preset-typescript"],
  "plugins": [
    ["relay", { "artifactDirectory": "../../__generated__", "eagerESModules": true }],
    ["@babel/plugin-transform-runtime", { "regenerator": true }]
  ]
}

Any tips welcome!


Solution

  • Alright, I've got rid of the error by

    The relevant part of my webpack.config looks like this now

    module: {
      rules: [     
        {
          test: /\.(ts|tsx)?$/,
          use: {
            loader: require.resolve("babel-loader"),
            options: {
            generatorOpts: { compact: false },
              presets: [
                "@babel/preset-env",
                ["@babel/preset-react", { runtime: "automatic" }],
                "@babel/preset-typescript",
              ],
              plugins: [
                ["relay", { artifactDirectory: "../../__generated__", eagerESModules: true }],
                ["@babel/plugin-transform-runtime"],
              ],
            },
          },
        },
      ],
    },
    

    However, the two warnings still persist!

    Compiled with problems:
    
    WARNING in ../../../.yarn/cache/babel-plugin-macros-npm-2.8.0-451367d7e7-59b09a21cf.zip/node_modules/babel-plugin-macros/dist/index.js 78:24-31
    
    Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
    
    
    WARNING in ../../../.yarn/cache/import-fresh-npm-3.3.0-3e34265ca9-2cacfad06e.zip/node_modules/import-fresh/index.js 32:31-48
    
    Critical dependency: the request of a dependency is an expression
    

    I have read that it might have to do with some asynchronous call of a macro!? Can I safely ignore these warnings? Is this a webpack issue?

    Update ---

    I have submitted an issue report at the Webpack GitHub Repo and according to them the babel-plugin-macros warning

    Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

    is a result of something like

    importSomeModules(require); 
    // or
    const myRequire = require;
    

    where require is not a call expression (eg: require(), require.resolve()).

    In case of babel-plugin-macros this is

    function macrosPlugin(babel, 
    // istanbul doesn't like the default of an object for the plugin options
    // but I think older versions of babel didn't always pass options
    // istanbul ignore next
    {
      require: _require = require,
      resolvePath = nodeResolvePath,
      isMacrosName = testMacrosRegex,
      ...options
    } = {}) {}
    

    Unfortunately, babel-plugin-macros is not being maintained anymore (though still a dependency for babel-plugin-relay).

    The other warning coming from import-fresh

    Critical dependency: the request of a dependency is an expression is a result of something like

    let var1 = someCall();
    require(var1); // webpack can't determine var1 value
    

    Guess the affected line of the package can be found here.