Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Require cycle warnings should be opt-in when the source is node_modules #287

Closed
brentvatne opened this issue Oct 9, 2018 · 107 comments
Closed

Comments

@brentvatne
Copy link
Contributor

brentvatne commented Oct 9, 2018

Do you want to request a feature or report a bug?

Feature

What is the current behavior?

Lots of warnings about require cycles from libraries in node_modules in the react-native ecosystem, coming from the following code:

if (__DEV__) {
const initializingIndex = initializingModuleIds.indexOf(
moduleIdReallyIsNumber,
);
if (initializingIndex !== -1) {
const cycle = initializingModuleIds
.slice(initializingIndex)
.map(id => modules[id].verboseName);
// We want to show A -> B -> A:
cycle.push(cycle[0]);
console.warn(
`Require cycle: ${cycle.join(' -> ')}\n\n` +
'Require cycles are allowed, but can result in uninitialized values. ' +
'Consider refactoring to remove the need for a cycle.',
);
}
}

What is the expected behavior?

Don't warn users about require cycles in libraries in node_modules unless the user opts-in. Warnings about code that you don't own, especially when the warnings are non-essential, create unnecessary noise.

Please provide your exact Metro configuration and mention your Metro, node, yarn/npm version and operating system.

React Native 0.57 default configuration and Metro version (0.47.1). Other information irrelevant.

@elkinjosetm
Copy link

Any workaround for this issue?

@dakiesse
Copy link

I get the warn as well. I've tried to ignore this but it didn't help me.

YellowBox.ignoreWarnings([
  'Warning: isMounted(...) is deprecated', // works
  'Module RCTImageLoader', // works
  'Require cycle:', // doesn't work
])

@brianephraim
Copy link

I can't deal with these warnings right now in my app. I mute them via a npm postintall script including this mess:

  const codeToObscure = /console.warn\([\s\S].*"Require cycle: "/;
  const problemFilePath = './node_modules/metro-config/node_modules/metro/src/lib/polyfills/require.js';
  const problemFileContent = fs.readFileSync(problemFilePath,'utf8');
  fs.writeFileSync(problemFilePath,problemFileContent.replace(codeToObscure,'const noConsoleWarn = (""'),'utf8');

@codybrouwers
Copy link

Would love to be able to opt-in to this warning. In the meantime, similar to @defualt, I've used patch-package to apply the below patch to ignore the warning only if its an external dependency:

Patch
patch-package
--- a/node_modules/metro/src/lib/polyfills/require.js
+++ b/node_modules/metro/src/lib/polyfills/require.js
@@ -111,21 +111,29 @@ function metroRequire(moduleId) {
     var initializingIndex = initializingModuleIds.indexOf(
       moduleIdReallyIsNumber
     );
+
     if (initializingIndex !== -1) {
       var cycle = initializingModuleIds
         .slice(initializingIndex)
         .map(function(id) {
           return modules[id].verboseName;
         });
-      // We want to show A -> B -> A:
-      cycle.push(cycle[0]);
-      console.warn(
-        "Require cycle: " +
-          cycle.join(" -> ") +
-          "\n\n" +
-          "Require cycles are allowed, but can result in uninitialized values. " +
-          "Consider refactoring to remove the need for a cycle."
-      );
+
+      var isExternalOnly = cycle.every(function(cycleWarning) {
+        return cycleWarning.includes("node_modules")
+      })
+      
+      if (!isExternalOnly) {
+        // We want to show A -> B -> A:
+        cycle.push(cycle[0]);
+        console.warn(
+          "Require cycle: " +
+            cycle.join(" -> ") +
+            "\n\n" +
+            "Require cycles are allowed, but can result in uninitialized values. " +
+            "Consider refactoring to remove the need for a cycle."
+        );
+      }
     }
   }

@toioski
Copy link

toioski commented Nov 7, 2018

@codybrouwers I have tried to use your patch but I received the following error from patch-package

**ERROR** Failed to apply patch for package metro

  This error was caused because Git cannot apply the following patch file:

    patches/metro+0.45.6.patch

  This is usually caused by inconsistent whitespace in the patch file.

@codybrouwers
Copy link

@toioski Ah yes, I've encountered that issue with patch-package as well. Better to just make the same changes and patch it yourself I think.

@slorber
Copy link

slorber commented Nov 13, 2018

I'd like to add that require cycle may be intentional inside your app code and is fine in many cases if you know what you are doing and don't start calling cycle methods on initialization . I'd like to be able to disable those warnings even for my own code, is there a way?

@luissmg
Copy link

luissmg commented Nov 14, 2018

@slorber In those cases the warning should be displayed. The problem like the OP said is:

Lots of warnings about require cycles from libraries in node_modules in the react-native ecosystem

@rafeca
Copy link
Contributor

rafeca commented Nov 14, 2018

Hi! We added this warning since we got many complains from developers at FB that it was hard to debug the errors caused by cyclic dependencies (since a cyclic dependency causes the returned value of a require statement to be undefined without hard throwing).

The YellowBox.ignoreWarnings method should allow to mute these errors, @dakiesse are you adding it at the top of the entry point of your app?

YellowBox.ignoreWarnings([
  'Require cycle:',
]);

@luissmg
Copy link

luissmg commented Nov 14, 2018

@rafeca I added that in my entry point and it does not work. Like @dakiesse said, the other two warnings don't show up but this one does.

@dakiesse
Copy link

dakiesse commented Nov 15, 2018

@rafeca yes, immediately after imports in entry point

@dakiesse
Copy link

Today I updated versions to:

    "react": "16.6.3",
    "react-native": "0.57.5",
    "metro-react-native-babel-preset": "0.49.1",

And I became to get new warning ListView is deprecated and will be removed in a future release. See https://fb.me/nolistview for more information. I've tried to ignore it.

YellowBox.ignoreWarnings([
  'Require cycle:',
  'ListView is deprecated',
])

It doesn't work as well.

@vrgimael
Copy link

This is so annoying, any updates here?

Every time I load the app I get like a million require cycle warnings which I really don't care about and muting them as suggested doesn't work.

Is there any other way of silencing this?

@dakiesse
Copy link

dakiesse commented Nov 18, 2018

@vrgimael the solution was suggested by @defualt

ozalexo added a commit to ozalexo/ChronoMint-RN that referenced this issue Nov 21, 2018
@abegehr
Copy link

abegehr commented Nov 22, 2018

YellowBox.ignoreWarnings(["Require cycle:"]); worked for me 👍

Here is my index.js:

/** @format */

import { AppRegistry, YellowBox } from "react-native";
import App from "./App";
import { name as appName } from "./app.json";

// ignore specific yellowbox warnings
YellowBox.ignoreWarnings(["Require cycle:", "Remote debugger"]);

AppRegistry.registerComponent(appName, () => App);

@KylePalko
Copy link

YellowBox.ignoreWarnings unfortunately does not hide them in the console :/

@satya164
Copy link
Contributor

IMO this should be opt-in, not opt out. Many people also don't understand what it is and think they need to fix this warning even if nothing is wrong with the code. There are also third-party libs with the warning that you can do nothing about.

Also to find require cycles, you have to go through hundreds of warnings, doesn't seem very efficient to find an issue. Enabling/disabling all of the warnings don't seem ideal either, it'll probably be better to enable this per folder rather than for whole project.

@Exilz
Copy link

Exilz commented Dec 4, 2018

Okaaaay, so if this warning is annoying the hell out of you, and you can't refactor your app because it's too much work, here's how I "suppressed" those warnings until a proper solution shows up :

  • Add a scripts folder in your project
  • Create a stfu.js file with the following content (edited from @dakiesse) :
const fs = require('fs');

const codeToObscure = /console.warn\([\s\S].*"Require cycle: "/;
const problemFilePath = './node_modules/metro/src/lib/polyfills/require.js';
const problemFileContent = fs.readFileSync(problemFilePath,'utf8');
fs.writeFileSync(problemFilePath,problemFileContent.replace(codeToObscure,'const noConsoleWarn = (""'),'utf8');
  • Add the following line to your package.json in your scripts : "postinstall": "node ./scripts/stfu.js",

When it's done, just rm -rf node_modules && yarn to reinstall everything, and make sure these damn warnings are now gone.

This is really really tricky for us since we have LOTS of require cycles because of how we use redux in our app.

I hope this is helpful.

ozalexo added a commit to ozalexo/ChronoMint-RN that referenced this issue Dec 5, 2018
@gwn
Copy link

gwn commented Jan 31, 2021

Ok here's another hack, but this is rather good.

UNIX comes to the rescue, guys. Use grep!!

Define your ignore patterns in a file. Here's mine:

.metroIgnoreLines:

Require cycle: node_modules/react-native-randombytes/index.js -> node_modules/sjcl/sjcl.js
Require cycles are allowed, but can result in uninitialized values

Run Metro like this: react-native start | grep -vF .metroIgnoreLines

This will work, but will also cause the terminal output to lose its colors. The reason is that since the Metro output is not going directly to the terminal anymore but to the grep command, Metro strips any colors from it. We must force it to keep the colors in the output:

FORCE_COLOR=2 react-native start | grep -vf .metroIgnoreLines

See the relevant section in Chalk docs for info on FORCE_COLOR. Since Metro employs Chalk to manage colors, this will work.

Also if you are a big nerd see the script Linux command for a more generic way of doing this, one that will work in every scenario.

I know this is not the fix you're looking for, but to me this is less fragile than the other hacks mentioned above.

@irisjae
Copy link

irisjae commented Feb 3, 2021

Okaaaay, so if this warning is annoying the hell out of you, and you can't refactor your app because it's too much work, here's how I "suppressed" those warnings until a proper solution shows up :

  • Add a scripts folder in your project
  • Create a stfu.js file with the following content (edited from @dakiesse) :
const fs = require('fs');

const codeToObscure = /console.warn\([\s\S].*"Require cycle: "/;
const problemFilePath = './node_modules/metro/src/lib/polyfills/require.js';
const problemFileContent = fs.readFileSync(problemFilePath,'utf8');
fs.writeFileSync(problemFilePath,problemFileContent.replace(codeToObscure,'const noConsoleWarn = (""'),'utf8');
  • Add the following line to your package.json in your scripts : "postinstall": "node ./scripts/stfu.js",

When it's done, just rm -rf node_modules && yarn to reinstall everything, and make sure these damn warnings are now gone.

This is really really tricky for us since we have LOTS of require cycles because of how we use redux in our app.

I hope this is helpful.

Seems that in new versions of metro, the require cycle message uses ` instead of " so your regex breaks. I've modified your code to this in my project, should work with both " and ` (only tested with `):

const fs = require('fs');
const codeToObscure = /console.warn\(\s*(?=["`]Require cycle:)/;
const problemFilePath = './node_modules/metro/src/lib/polyfills/require.js';
const problemFileContent = fs.readFileSync(problemFilePath,'utf8');
fs.writeFileSync(problemFilePath,problemFileContent.replace(codeToObscure,'const noConsoleWarn = ('),'utf8');

@paulo-souza
Copy link

Okaaaay, so if this warning is annoying the hell out of you, and you can't refactor your app because it's too much work, here's how I "suppressed" those warnings until a proper solution shows up :

  • Add a scripts folder in your project
  • Create a stfu.js file with the following content (edited from @dakiesse) :
const fs = require('fs');

const codeToObscure = /console.warn\([\s\S].*"Require cycle: "/;
const problemFilePath = './node_modules/metro/src/lib/polyfills/require.js';
const problemFileContent = fs.readFileSync(problemFilePath,'utf8');
fs.writeFileSync(problemFilePath,problemFileContent.replace(codeToObscure,'const noConsoleWarn = (""'),'utf8');
  • Add the following line to your package.json in your scripts : "postinstall": "node ./scripts/stfu.js",

When it's done, just rm -rf node_modules && yarn to reinstall everything, and make sure these damn warnings are now gone.
This is really really tricky for us since we have LOTS of require cycles because of how we use redux in our app.
I hope this is helpful.

Seems that in new versions of metro, the require cycle message uses instead of " so your regex breaks. I've modified your code to this in my project, should work with both " and (only tested with `):

const fs = require('fs');
const codeToObscure = /console.warn\(\s*(?=["`]Require cycle:)/;
const problemFilePath = './node_modules/metro/src/lib/polyfills/require.js';
const problemFileContent = fs.readFileSync(problemFilePath,'utf8');
fs.writeFileSync(problemFilePath,problemFileContent.replace(codeToObscure,'const noConsoleWarn = ('),'utf8');

Yes, here in my project disappeared this logs in the console.

Thanks!! 👍

@alistairholt
Copy link

I find it hard to believe that 2 years later we still can't silence the console warnings (not YellowBox) without "patching" Metro.

@Jonjoe
Copy link

Jonjoe commented Mar 19, 2021

Guys ... how is this still a problem? Can we please just wrap this logic in a bloody env var and be done with it?

@Jonjoe
Copy link

Jonjoe commented Mar 19, 2021

  • "postinstall": "node ./scripts/stfu.js",

This worked for me. Absolute madness that we have to do this. But I really appreciate the collective work on a community solution 💪🏽.

@ferdicus
Copy link

ferdicus commented Apr 8, 2021

beautiful dev peops, heads up when upgrading to react-native 0.64.x
notice, that the file moved:
node_modules/metro/src/lib/polyfills/require.js => node_modules/metro-runtime/src/polyfills/require.js

@Stevemoretz
Copy link

I use:

LogBox.ignoreLogs(['Require cycle:'])

Right after imports, in App.js; notice this is for newest versions of react native.

@mattijsf
Copy link

mattijsf commented Apr 26, 2021

I use:

LogBox.ignoreLogs(['Require cycle:'])

Right after imports, in App.js; notice this is for newest versions of react native.

Afaik, in react-native 0.64.0, LogBox doesn't affect the output of metro cli itself, only what is logged by the loaded bundle at runtime. Metro is resolving imports and logs this message regardless of what is configured in LogBox.

@Stevemoretz
Copy link

I use:

LogBox.ignoreLogs(['Require cycle:'])

Right after imports, in App.js; notice this is for newest versions of react native.

Afaik, in react-native 0.64.0, LogBox doesn't affect the output of metro cli itself, only what is logged by the loaded bundle at runtime. Metro is resolving imports and logs this message regardless of what is configured in LogBox.

I'm using expo sdk 41 and this is working.

@enesozturk
Copy link

Still have the same issue. Tried to use like below but not worked for me on 0.64.1;

LogBox.ignoreLogs(['Require cycle:'])

And I actually don't want to ignore this error but mostly getting this because of absolute path usage. Is there a proper way to use absolute path without getting this kind of warnings?

@sryze
Copy link

sryze commented Jul 15, 2021

Anyone knows how to disable warnings in Metro server output (after react-native start)?

 ERROR    currentlyFocusedField is deprecated and will be removed in a future release. Use currentlyFocusedInput

LogBox doesn't work

@Stevemoretz
Copy link

Anyone knows how to disable warnings in Metro server output (after react-native start)?

 ERROR    currentlyFocusedField is deprecated and will be removed in a future release. Use currentlyFocusedInput

LogBox doesn't work

Could you replace that with currentlyFocusedInput?

I'm guessing you are using an old version of react navigation, you can use npm patch to create a patch for a node_module disabling the warning will be a problem, because it says it will be removed in a future version.

If you could fix it please send the patch so other people could use it too.

@nejos97
Copy link

nejos97 commented Aug 23, 2021

I've been looking for a solution for a month now and nothing works! I think I'll stop the code

@Stevemoretz
Copy link

Stevemoretz commented Aug 23, 2021

I've been looking for a solution for a month now and nothing works! I think I'll stop the code

Try to refractor your code, and use globalThis where it helps. (if it in your project if warning is in node_modules try to patch it and inform the developers)

@ferdicus
Copy link

I've been looking for a solution for a month now and nothing works! I think I'll stop the code

Now I want a shirt that reads:
Stop the code

@Stevemoretz
Copy link

I've been looking for a solution for a month now and nothing works! I think I'll stop the code

Now I want a shirt that reads:
Stop the code

That'll work as well, no more warnings or errors ever again.

@nejos97
Copy link

nejos97 commented Aug 23, 2021

I've been looking for a solution for a month now and nothing works! I think I'll stop the code

Now I want a shirt that reads:
Stop the code

NEVER

@nejos97
Copy link

nejos97 commented Aug 23, 2021

I've been looking for a solution for a month now and nothing works! I think I'll stop the code

Try to refractor your code, and use globalThis where it helps. (if it in your project if warning is in node_modules try to patch it and inform the developers)

Require cycle: node_modules/react-native/Libraries/Network/fetch.js -> node_modules/whatwg-fetch/dist/fetch.umd.js -> node_modules/react-native/Libraries/Network/fetch.js

@Stevemoretz
Copy link

I've been looking for a solution for a month now and nothing works! I think I'll stop the code

Try to refractor your code, and use globalThis where it helps. (if it in your project if warning is in node_modules try to patch it and inform the developers)

Require cycle: node_modules/react-native/Libraries/Network/fetch.js -> node_modules/whatwg-fetch/dist/fetch.umd.js -> node_modules/react-native/Libraries/Network/fetch.js

That warning of yours comes from the react native itself, I'm on latest version and have not this problem, maybe consider upgrading?

@hsource
Copy link
Contributor

hsource commented Sep 27, 2021

I just created a PR for a solution that should be a bit more flexible, allowing users of Metro to suppress certain libraries' warnings. This ensures that you can still see require cycle warnings for new modules that you've installed (so you can decide for yourself if they're an issue). If anyone is interested in the fix, take a look at #707

@carlos-dubon
Copy link

Wow! 4 years now! Can you PLEASE make this optional. :) Thank you! Can't believe "Facebook Engineers" need this type of stuff to debug their apps.

@robhogan
Copy link
Contributor

Hi @carlos-dubon, thanks for the contribution.

This was addressed in #707 and released in Metro 0.70.2 - requireCycleIgnorePatterns. Closing.

@alamothe
Copy link

Thank you! Can't believe "Facebook Engineers" need this type of stuff to debug their apps.

They don't. It's just how corporations work. Usually it goes like this:

Managers: Why do our apps suck so much??
Engineers: Um...
Managers: Quick! We need some quick explanation to satisfy us.
Engineers: It's because require cycles in JavaScript produce undefined behavior.
Managers: Okay! Let's add another lint warning.

Some engineer implements require cycle detection, gets promoted to E7. The new warning is useless and annoying everyone. Apps still suck. Everyone loses.

@robhogan
Copy link
Contributor

robhogan commented Aug 21, 2022

FWIW, dependency cycles prevent topological ordering, which can be a problem for granular, distributed build systems, as well as potentially introducing surprising runtime behaviour.

The warning isn't useless, but it was too noisy in OSS - mainly due to being unactionable under node_modules. Thanks again @hsource for contributing a solution.

@facebook facebook locked and limited conversation to collaborators Aug 21, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.