facebook / relay

Relay is a JavaScript framework for building data-driven React applications.
https://relay.dev
MIT License
18.42k stars 1.83k forks source link

babel-plugin-relay dependency results in critical dependency warning when building with Webpack 5 #3867

Open Poolshark opened 2 years ago

Poolshark commented 2 years ago

Description

I have a monorepo which uses yarn workspaces with yarn berry. I am running and bundling the react apps with webpack 5.

However, I can't get babel-plugin-relay working. When I'm trying to run the application, I keep getting these errors:

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

My setup

My monorepo has the following form:

frontend/
  apps/
    app1/
      .babelrc
      package.json
    app2/
      .babelrc
      package.json
    app3/
      .babelrc
      package.json
  packages/
    .babelrc
    package.json
    // packages which will be shared with app1, app2 and app3

Every app and the packages have their own package.json. Where I have babel-plugin-relay as a dev dependency.

The .babelrc is situated in the root of each project of the monorepo (see above) and looks like

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

Anyone experiencing the same issue? Can anyone help? I'm stuck on this since days now.

Poolshark commented 2 years ago

UPDATE

I've managed to get an error message from babel-plugin-macros saying

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 have located the line in the source code of babel-plugin-macros

function macroWrapper(args) {
    const {source, isBabelMacrosCall} = args
    if (!isBabelMacrosCall) {
      throw new MacroError(
        `The macro you imported from "${source}" 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',
      )
    }
    return macro(args)
  }

So source is undefined!

I've then checked the babel-plugin-relay source and found the line where babel-plugin-macros gets called

const configName = 'relay';

function BabelPluginRelayMacro({references, state, babel, config}: any) {
  const {types: t} = babel;
  Object.keys(references).forEach(referenceKey => {
    references[referenceKey].forEach(reference => {
      const path = reference.parentPath;
      const ast = getValidGraphQLTag(path);
      if (ast) {
        compileGraphQLTag(
          t,
          path,
          Object.assign(state, config ? {opts: config} : {}),
          ast,
        );
      }
    });
  });
}

module.exports = (createMacro(BabelPluginRelayMacro, {configName}): any);

Does anyone know what is going on here?

Poolshark commented 2 years ago

UPDATE 2

Managed to get rid of the error by

// relevant part of the webpack.config.dev.ts

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

Is this a webpack related issue?

Poolshark commented 2 years ago

Update 3

According to here, the problem is in babel-plugin-marco where require is not call expression.

So something like

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

causes this warning. The exact location in the code source of babel-plugin-macro 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
} = {}) {}

Since babel-plugin-macro is not going to be maintained anymore but babel-plugin-relay relies on it, will you be fixing this? Or can we simply ignore this warning?

edvinerikson commented 2 years ago

@Poolshark, make sure that the graphql tag is imported from react-relay or relay-runtime directly. Not from babel-plugin-relay/macro.

Jimbob001 commented 2 years ago

@edvinerikson is importing graphql from react-relay the recommended approach? All the examples in the documentation import from babel-plugin-relay/macro...?

I've always wondered what the difference / pros / cons are between the different imports, I'm fixing a similar issue to the above so thought it worth clarifying in general.

edvinerikson commented 2 years ago

@Jimbob001 If you don't use babel-plugin-macro you should never import from the /macro path. So yes, importing from react-relay is the supported way. The /macro path is only for when you have babel-plugin-macro configured.

fs-projects commented 1 year ago

I am getting the same issue while using fortawesome. I have raised the bug in their repo.

https://github.com/FortAwesome/react-fontawesome/issues/554

Please help me fix these warnings as it's not allowing me to compile my code.