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: ../../node_modules/@grpc/grpc-js/build/src/channel.js #8231

Open
ErionTp opened this issue May 8, 2024 · 4 comments
Open

Comments

@ErionTp
Copy link

ErionTp commented May 8, 2024

Operating System

Mac Sonoma 14.4.1

Browser Version

Chrome/ Version 124.0.6367.119 (Official Build) (arm64)

Firebase SDK Version

10.11.1

Firebase SDK Product:

Auth, Firestore

Describe your project's tooling

React Native Expo, Web with metro.config.js

Describe the problem

Im trying to add a context provider so I can handle the status of the user. In the native app everything works fine. When I try to open the app on web it warns me like:

WARN  Require cycle: ../../node_modules/@grpc/grpc-js/build/src/channel.js -> ../../node_modules/@grpc/grpc-js/build/src/internal-channel.js -> ../../node_modules/@grpc/grpc-js/build/src/subchannel-pool.js -> ../../node_modules/@grpc/grpc-js/build/src/subchannel.js -> ../../node_modules/@grpc/grpc-js/build/src/channelz.js -> ../../node_modules/@grpc/grpc-js/build/src/make-client.js -> ../../node_modules/@grpc/grpc-js/build/src/client.js -> ../../node_modules/@grpc/grpc-js/build/src/channel.js

Require cycles are allowed, but can result in uninitialized values. Consider refactoring to remove the need for a cycle. 
  factory (../../node_modules/@grpc/grpc-js/build/src/client.js:21:19)
  factory (../../node_modules/@grpc/grpc-js/build/src/make-client.js:20:18)
  factory (../../node_modules/@grpc/grpc-js/build/src/channelz.js:25:23)
  factory (../../node_modules/@grpc/grpc-js/build/src/subchannel.js:26:20)

Steps and code to reproduce issue

I have the firebase config:

import { initializeApp } from "firebase/app";
import {
  initializeAuth,
  connectAuthEmulator,
  getReactNativePersistence,
  browserSessionPersistence,
} from "firebase/auth";
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";
import { getStorage, connectStorageEmulator } from "firebase/storage";
import { connectFunctionsEmulator, getFunctions } from "firebase/functions";

import AsyncStorage from "@react-native-async-storage/async-storage";

import device from "../device";

const firebaseConfig = {
  apiKey: process.env.EXPO_PUBLIC_API_KEY ?? "",
  authDomain: process.env.EXPO_PUBLIC_AUTH_DOMAIN ?? "",
  projectId: process.env.EXPO_PUBLIC_PROJECT_ID ?? "",
  storageBucket: process.env.EXPO_PUBLIC_STORAGE_BUCKET ?? "",
  messagingSenderId: process.env.EXPO_PUBLIC_MESSAGING_SENDER_ID ?? "",
  appId: process.env.EXPO_PUBLIC_APP_ID ?? "",
  measurementId: process.env.EXPO_PUBLIC_MEASUREMENT_ID ?? "",
};


const app = initializeApp(firebaseConfig);

const auth = initializeAuth(app, {
  persistence: device.isWeb ? browserSessionPersistence : getReactNativePersistence(AsyncStorage),
});

const firestore = getFirestore(app);
const storage = getStorage(app);
const functions = getFunctions(app);

if (__DEV__) {
  connectFirestoreEmulator(firestore, process.env.EXPO_PUBLIC_IP ?? "", 8080);
  connectStorageEmulator(storage, process.env.EXPO_PUBLIC_IP ?? "", 9199);
  connectAuthEmulator(auth, `http://${process.env.EXPO_PUBLIC_IP}:9099`, { disableWarnings: true });
  connectFunctionsEmulator(functions, process.env.EXPO_PUBLIC_IP ?? "", 5001);
}

export { app, auth, firestore, storage, functions };

Then I call this in a context provider:

import React, {
  createContext,
  useContext,
  useMemo,
  PropsWithChildren,
  useState,
  useEffect,
} from "react";
import { auth } from "@/src/resources/config/firebase";
import { User, onAuthStateChanged } from "firebase/auth";

type tContext = {
  user: User | undefined | null;
  setUser: React.Dispatch<React.SetStateAction<User | null | undefined>>;
};

const MainContext = createContext<Partial<tContext>>({
  user: undefined,
  setUser: () => Function,
});

export type tMainProviderProps = {};

export const MainProvider = ({ children }: PropsWithChildren<tMainProviderProps>) => {

  const [user, setUser] = useState<User | null | undefined>(undefined);

  const authStateChanged = (authUser: User | null | undefined) => {
    setUser(authUser);
  };


  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, authStateChanged);
    return () => {
      unsubscribe();
    };
  }, []);


  const memoValue = useMemo(() => ({ user, setUser }), [user]);

  return <MainContext.Provider value={memoValue}>{children}</MainContext.Provider>;
};

export default function useMainProvider() {
  const context = useContext(MainContext);
  if (!context) throw new Error("useMainProvider should be within MainProvider");
  return context;
}

There is no other configuration or setup, this project is quite new.

@ErionTp ErionTp added new A new issue that hasn't be categoirzed as question, bug or feature request question labels May 8, 2024
@jbalidiong jbalidiong added needs-attention and removed new A new issue that hasn't be categoirzed as question, bug or feature request labels May 8, 2024
@dlarocque
Copy link
Contributor

dlarocque commented May 9, 2024

Hi @ErionTp, thanks for submitting this issue.

I was able to produce a minimal reproduction:

  1. npx create-expo-app testapp
  2. cd testapp
  3. npm install firebase
  4. Edit app/(tabs)/index.tsx to be:
import { initializeApp } from 'firebase/app';
import { getFirestore } from "firebase/firestore";

const firebaseConfig = {
  /* Replace me with your firebase project config */
};
const app = initializeApp(firebaseConfig);

getFirestore(app);
  1. npm run web
  2. Visit http://localhost:8081
  3. See warning once web is bundled:
testapp git:(main) ✗ npm run web

> [email protected] web
> expo start --web

Starting project at /Users/dlarocque/workspace/repro/8231/testapp
Starting Metro Bundler

› Metro waiting on exp://127.0.0.1:8081
› Scan the QR code above with Expo Go (Android) or the Camera app (iOS)

› Web is waiting on http://localhost:8081

› Using Expo Go
› Press s │ switch to development build

› Press a │ open Android
› Press i │ open iOS simulator
› Press w │ open web

› Press j │ open debugger
› Press r │ reload app
› Press m │ toggle menu
› Press o │ open project code in your editor

› Press ? │ show all commands

Logs for your project will appear below. Press Ctrl+C to exit.
λ Bundled 10107ms node_modules/expo-router/node/render.js (955 modules)
Web Bundled 10277ms node_modules/expo-router/entry.js (848 modules)
λ  WARN  Require cycle: node_modules/@grpc/grpc-js/build/src/channel.js -> node_modules/@grpc/grpc-js/build/src/internal-channel.js -> node_modules/@grpc/grpc-js/build/src/subchannel-pool.js -> node_modules/@grpc/grpc-js/build/src/subchannel.js -> node_modules/@grpc/grpc-js/build/src/channelz.js -> node_modules/@grpc/grpc-js/build/src/make-client.js -> node_modules/@grpc/grpc-js/build/src/client.js -> node_modules/@grpc/grpc-js/build/src/channel.js

Require cycles are allowed, but can result in uninitialized values. Consider refactoring to remove the need for a cycle. 
  factory (node_modules/@grpc/grpc-js/build/src/client.js:21:19)
  factory (node_modules/@grpc/grpc-js/build/src/make-client.js:20:18)
λ  WARN  Require cycle: node_modules/@grpc/grpc-js/build/src/experimental.js -> node_modules/@grpc/grpc-js/build/src/load-balancer-outlier-detection.js -> node_modules/@grpc/grpc-js/build/src/experimental.js

Require cycles are allowed, but can result in uninitialized values. Consider refactoring to remove the need for a cycle. 
  factory (node_modules/@grpc/grpc-js/build/src/load-balancer-outlier-detection.js:24:24)
  factory (node_modules/@grpc/grpc-js/build/src/experimental.js:37:41)
λ  WARN  Require cycle: node_modules/protobufjs/src/util/minimal.js -> node_modules/protobufjs/src/util/longbits.js -> node_modules/protobufjs/src/util/minimal.js

Require cycles are allowed, but can result in uninitialized values. Consider refactoring to remove the need for a cycle. 
  factory (node_modules/protobufjs/src/util/longbits.js:4:12)
  factory (node_modules/protobufjs/src/util/minimal.js:26:17)
λ  WARN  Require cycle: node_modules/protobufjs/src/enum.js -> node_modules/protobufjs/src/namespace.js -> node_modules/protobufjs/src/field.js -> node_modules/protobufjs/src/enum.js

Require cycles are allowed, but can result in uninitialized values. Consider refactoring to remove the need for a cycle. 
  factory (node_modules/protobufjs/src/field.js:8:13)
  factory (node_modules/protobufjs/src/namespace.js:8:16)
λ  WARN  props.pointerEvents is deprecated. Use style.pointerEvents 
"shadow*" style props are deprecated. Use "boxShadow".
λ  WARN  accessibilityRole is deprecated. Use role.

@tom-andersen
Copy link
Contributor

tom-andersen commented May 9, 2024

This appears to be from within a dependent library. They have an open issue for dependency cycles within their code:

grpc/grpc-node#1821

@tom-andersen
Copy link
Contributor

Those particular modules are not required for web. I think there might be something wrong with how the bundler is configured.

Firebase Web SDK variants

@hsubox76
Copy link
Contributor

This looks like a recurring issue with the default Metro config resolving to main or one of the exports subfields that points to the Node bundle, here:

"main": "dist/index.node.cjs.js",

The Metro config needs to be changed somehow so that it resolves to browser, module, or any of the exports subfields that point to a bundle that doesn't have the word "node" in it. Unfortunately we don't seem to have the expertise in configuring Metro for React Native to come up with a Metro config change that makes this work, and it would be really helpful if someone with expertise in Metro or React Native could come up with a workaround using this information.

I think this is beyond the scope of the JS SDK as all the paths in our package.json seem to follow standards for how to label browser, Node, ESM, and CJS bundle and Metro ought to be able to follow these fields to a web bundle, and not a Node bundle. We can leave this issue open in case anything spots anything wrong with our package.json configuration, but it seems at the moment like the issue is with Metro, or the default Metro config at least.

See previous issue:
#7849 (comment)

@tom-andersen tom-andersen removed the bug label May 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants