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

[8.0.0-beta.4] Module not found: Can't resolve 'fs' #935

Closed
kdelmonte opened this issue Feb 8, 2021 · 36 comments
Closed

[8.0.0-beta.4] Module not found: Can't resolve 'fs' #935

kdelmonte opened this issue Feb 8, 2021 · 36 comments

Comments

@kdelmonte
Copy link

Describe the bug

Getting the following error when running the app:

wait  - compiling...
error - ./node_modules/next-i18next/dist/commonjs/serverSideTranslations.js:28:0
Module not found: Can't resolve 'fs'

Occurs in next-i18next version

8.0.0-beta.4

Steps to reproduce

You must provide a reproducible repository, or copy/paste blocks of code which are sufficient to reproduce the bug.

Expected behaviour

You must provide a clear and concise description of what you expected to happen.

Screenshots

image

@isaachinman
Copy link
Contributor

Hi @kdelmonte – this is most likely because you have imported serverSideTranslations in some place where client side code is being run. It can only be used in server side data fetching methods such as getStaticProps and getServerSideProps. Hope that helps!

@kdelmonte
Copy link
Author

Thank you @isaachinman , I am only using it inside getServerSideProps:

export const getServerSideProps = async ({ locale }) => ({
  props: {
    ...(await serverSideTranslations(locale, ['common', 'loginPage'])),
  },
})

Please advise.

@isaachinman
Copy link
Contributor

@kdelmonte You'll need to provide a reproducible repo.

@kdelmonte
Copy link
Author

@isaachinman I found this issue. I was exporting getServerSideProps from another file into the Next.js page file. Moving getServerSideProps directly to the page file fixed this issue. Thanks.

@ivnmood
Copy link

ivnmood commented Feb 11, 2021

I have same issue, in 8.0.0-beta.4, but I did all the imports correctly and I totally tried to do it like in read.me file and example from the repository

wait - compiling...
error - ../node_modules/next-i18next/dist/commonjs/serverSideTranslations.js:28:0
Module not found: Can't resolve 'fs'
null
react-i18next:: You will need to pass in an i18next instance by using initReactI18next

_app.tsx

import { appWithTranslation } from "next-i18next";
import { AppProps } from "next/app";

const App: React.FC<AppProps> = ({ Component, pageProps }) => {
  const MainLayout = (Component as any).MainLayout || DefaultLayout;
  const NestedLayout = (Component as any).NestedLayout || DefaultLayout;

  return (
    <>
     /.../
              <MainLayout>
                <NestedLayout>
                  <Component {...pageProps} />
                </NestedLayout>
              </MainLayout>
         /.../
    </>
  );
};

const DefaultLayout: React.FC = ({ children }) => <>{children}</>;

export default appWithTranslation(App);

file where i use serverSideTranslations:

import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { GetStaticProps } from "next";
import Grid from "@material-ui/core/Grid";
import { Header } from "../components/Header";

const AppLayout: React.FC = ({ children }) => (
  <>
    <Grid container direction="column" alignItems="center">
      <Header />
      {children}
    </Grid>
  </>
);

export const getStaticProps: GetStaticProps = async ({ locale }) => ({
  props: {
    ...(await serverSideTranslations(locale, ["translation"])),
  },
});

export default AppLayout;

file where i use useTranslation

import { useTranslation } from "next-i18next";

import { NavLink } from "../../../../components/NavLink";

export const Header = () => {
  const { t } = useTranslation();
  return (
/ .../
          <NavLink title={t("something1")} href="/#"  />
          <NavLink title={t("something2")} href="/#"  />
          <NavLink title={t("something3")} href="/#"  />
/ .../
  );
};

next-18next-config.js

import { initReactI18next } from "react-i18next";

const path = require("path");

module.exports = {
  defaultLocale: "en",
  locales: ["en", "ru"],
  localePath: path.resolve("./public/translations"),
  use: [initReactI18next],   // this line did not affect the error in any way
  debug: true,
};

next.config.js

module.exports = {
  images: {
    domains: ["..."],
  },
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      issuer: {
        test: /\.(js|ts)x?$/,
      },
      use: ["@svgr/webpack"],
    });

    return config;
  },
  async redirects() {
    return [
      {
        source: "/",
        destination: "/...",
        permanent: false,
      },
    ];
  },
  i18n: {
    defaultLocale: "en",
    locales: ["en", "ru"],
  },
};

@ivnmood
Copy link

ivnmood commented Feb 12, 2021

I'm resolve this issues, this code

export const getStaticProps: GetStaticProps = async ({ locale }) => ({
  props: {
    ...(await serverSideTranslations(locale, ["translation"])),
  },
});

must be in pages folder, but i'm use it in components folder

@kdelmonte
Copy link
Author

This is exactly what happened to me. Beware, future readers.

@isaachinman
Copy link
Contributor

Just want to note that this is a general NextJs "gotcha", and isn't necessarily specific to next-i18next. It's to do with how chunks are separated by webpack, despite there being client and server code in the same files (pages).

@dohomi
Copy link

dohomi commented Feb 24, 2021

@isaachinman I am using NextJS and Storybook together and I did not share any code SSR related code within both separate builds.

I still realise when I use the useTranslation hook in the Storybook environment I receive the error:

ERROR in ./node_modules/next-i18next/dist/esm/config/createConfig.js
Module not found: Error: Can't resolve 'fs'

I could solve it for now with importing useTranslation from react-118next instead of next-i18next - I am not sure if thats the right way to do this.

// import { useTranslation } from 'next-i18next' // => throws error
import { useTranslation, UseTranslationOptions, UseTranslationResponse } from 'react-i18next'

type TranslationNamespace = 'common'

const useLmTranslation = (
  ns?: TranslationNamespace,
  options?: UseTranslationOptions
): UseTranslationResponse<string> =>
  useTranslation((ns as string) ?? 'common', options)

export default useLmTranslation

EDIT:
I add an alias to point via Webpack config to different alias to solve the error for now.

webpackFinal: async (config, {configType}) => {
    config.resolve.alias = {
      ...config.resolve.alias,
      'next-i18next': 'react-i18next'
    }
    return config
  }

@isaachinman
Copy link
Contributor

Hey @dohomi – hopefully we can solve this together.

As a package, next-i18next runs in both server and browser environments. For the createConfig code your error is referencing, we check if process.browser is true.

Strange that process.browser is not true in your Storybook env.

The swap from typeof window === 'undefined' to process.browser was done in #926 as a bundle optimisation. cc @felixmosh – we may need to also add typeof window === 'undefined' back in.

@isaachinman isaachinman reopened this Feb 24, 2021
@felixmosh
Copy link
Contributor

@isaachinman, sound OK, I will prepare a PR

@isaachinman
Copy link
Contributor

Fixed by #974.

@dohomi
Copy link

dohomi commented Feb 25, 2021

@isaachinman @felixmosh I updated to 8.0.1 and the error still exists and Storybook is not building:

ERROR in ./node_modules/next-i18next/dist/esm/config/createConfig.js
Module not found: Error: Can't resolve 'fs' in '/node_modules/next-i18next/dist/esm/config'
 @ ./node_modules/next-i18next/dist/esm/config/createConfig.js 54:15-28
 @ ./node_modules/next-i18next/dist/esm/appWithTranslation.js
 @ ./node_modules/next-i18next/dist/esm/index.js
 @ ./lib/hooks/useLmTranslation.ts

I'm only using the useTranslation hook the rest is run by react-i18next

@felixmosh
Copy link
Contributor

felixmosh commented Feb 25, 2021

Do you use webpack 5 in you storybook build?

@Kalle-kula
Copy link

Kalle-kula commented Mar 18, 2021

EDIT:
I add an alias to point via Webpack config to different alias to solve the error for now.

webpackFinal: async (config, {configType}) => {
    config.resolve.alias = {
      ...config.resolve.alias,
      'next-i18next': 'react-i18next'
    }
    return config
  }

Putting this in my /storybook/.main.js solved it for me, cheers

@wsfung2008
Copy link

I'm resolve this issues, this code

export const getStaticProps: GetStaticProps = async ({ locale }) => ({
  props: {
    ...(await serverSideTranslations(locale, ["translation"])),
  },
});

must be in pages folder, but i'm use it in components folder

This solved it for me

@Ermosparis
Copy link

I'm resolve this issues, this code

export const getStaticProps: GetStaticProps = async ({ locale }) => ({
  props: {
    ...(await serverSideTranslations(locale, ["translation"])),
  },
});

must be in pages folder, but i'm use it in components folder

What to do if I need to use it in components folder?

@wsfung2008
Copy link

What to do if I need to use it in components folder?

you can still use the useTranslation hook in components

@Ermosparis
Copy link

What to do if I need to use it in components folder?

you can still use the useTranslation hook in components

Thank you, I figured out 😅

@jeremyzilar
Copy link

@dohomi Did you figure out a workaround other than the alias to Webpack config?

I add an alias to point via Webpack config to different alias to solve the error for now.

webpackFinal: async (config, {configType}) => {
    config.resolve.alias = {
      ...config.resolve.alias,
      'next-i18next': 'react-i18next'
    }
    return config
  }

@felixmosh
Copy link
Contributor

felixmosh commented Nov 16, 2021

The root cause of this issue in storybook is related to this line.

In Webpack 5 there is no default polyfill for fs & path.

You have 2 choices to solve the issue:

  1. disable fs by
//webpack.config.js
webpackFinal: async (config, { configType }) => {
  config.resolve.fallback = {
    ...config.resolve.fallback,
    fs: false, // <------
    path: false // <-----
  };
  return config;
};
  1. if the first option doesn't works, change it to work with browserify-fs
webpackFinal: async (config, { configType }) => {
  config.resolve.fallback = {
    ...config.resolve.fallback,
    fs: require.resolve("browserify-fs"), // <------
    path: require.resolve("path-browserify"), // <------
  };
  return config;
};

@isaachinman
Copy link
Contributor

@felixmosh Think we'd be better off relying directly on import at this point?

@felixmosh
Copy link
Contributor

@isaachinman I'm not sure I got the idea, import of what?

The "problem" is that the code is isomorphic, and contains code of server side, import won't change anything (because you want to lazy load the server code on the server only).

@isaachinman
Copy link
Contributor

import of whatever we are currently using fs to achieve. Dynamic imports on the server side should be possible.

@brayoh
Copy link

brayoh commented Nov 26, 2021

import of whatever we are currently using fs to achieve. Dynamic imports on the server side should be possible.

import of what?

@sauldeleon
Copy link

sauldeleon commented May 9, 2022

@dohomi Did you figure out a workaround other than the alias to Webpack config?

webpackFinal: async (config, {configType}) => {
    config.resolve.alias = {
      ...config.resolve.alias,
      'next-i18next': 'react-i18next'
    }
    return config
  }

Hi!

when I follow this approach to get this work in storybook then I start getting this errors

ModuleNotFoundError: Module not found: Error: Can't resolve 'next-i18next/serverSideTranslations' in 'myproject/src/pages'

I bet this is because storybook is running in the same folder as the next.js app, and is loading I dont know why a file with that import.

Anybody has faced the same issue?

@MonchiLin
Copy link

nextjs 12.2 add Edge SSR(https://nextjs.org/blog/next-12-2#edge-server-rendering-experimental) feature, it can also cause this issue.

@Imran-cse
Copy link

I'm using getServerSideProps inside pages but still facing the issue

@lemonspb
Copy link

Сan anyone explain how to solve the problem using components outside of pages?

@t18n
Copy link

t18n commented Oct 18, 2022

In my case, that was the use of

import { useTranslation } from 'next-i18next';

Replace all the occurences with fixes the problem.

import { useTranslation } from 'react-i18next';

As a side note, importing serverSideTranslations as an util works fine for me

export async function getServerSideProps() {
	return {
		props: {
			...(await getI18nProps()),
		},
	};
}

jaehyeon48 added a commit to titicacadev/triple-frontend that referenced this issue Oct 26, 2022
pgs787 pushed a commit to titicacadev/triple-frontend that referenced this issue Nov 10, 2022
jaehyeon48 added a commit to titicacadev/triple-frontend that referenced this issue Dec 1, 2022
jaehyeon48 added a commit to titicacadev/triple-frontend that referenced this issue Dec 9, 2022
jaehyeon48 added a commit to titicacadev/triple-frontend that referenced this issue Dec 14, 2022
jaehyeon48 added a commit to titicacadev/triple-frontend that referenced this issue Dec 21, 2022
@RichGriff
Copy link

Hey, I'm trying to get my head around the internationalization stuff but running into this 'Can't resolve fs' error. I'm using Next.js 13 and with the app routing option. Has anyone managed to find a fix/work around for this?

@adrai
Copy link
Member

adrai commented May 31, 2023

@RithPisey
Copy link

RithPisey commented Jun 3, 2023

  • To do translations in client-side components in Next.js:

Create a i18n.js file in the root of your project with the following content:

const NextI18Next = require('next-i18next').default;

module.exports = new NextI18Next({
  defaultLanguage: 'en',
  otherLanguages: ['fr'], // Add your supported languages here
  localeSubpaths: {},
  localePath: typeof window !== 'undefined' ? 'public/locales' : 'locales',
});

@juanccamachob94
Copy link

juanccamachob94 commented Jun 6, 2023

I personally identified that dependencies serverSideTranslations and useTranslation cannot be together. It works for me.

./i18n/useTranslation.ts

import { useTranslation as useOfficialTranslation } from 'next-i18next';
import { UseTranslationResponse } from 'react-i18next';

import { namespaces } from '@/i18n/helpers/namespaces';

export function useTranslation (ns: string | string[]) {
  const translation = useOfficialTranslation(namespaces(ns));
  const res: UseTranslationResponse<string> = { ...translation };
  res.t = (key: string | string[], options?: any) => {
    if (typeof key === 'string' && typeof ns === 'string' && key.split(':').length === 1)
      return translation.t(`${ns}:${key}`, options);
    return translation.t(key, options);
  };
  return res;
}

./i18n/serverSideTranslations.ts

import { serverSideTranslations as officialServerSideTranslations }
  from 'next-i18next/serverSideTranslations';

import { namespaces } from '@/i18n/helpers/namespaces';

export async function serverSideTranslations (locale: string | undefined, ns: string | string[]) {
  return await officialServerSideTranslations(locale ?? 'de', namespaces(ns));
}

./i18n/helpers/namespaces.ts

export function namespaces (ns: string | string[]) {
  return ['common', ...(typeof ns === 'string' ? [ns] : ns)];
}

any NextJS page

import { useTranslation } from '@/i18n/useTranslation';
import { serverSideTranslations } from '@/i18n/serverSideTranslations';

With this configuration I managed to bypass the explicit use of common. I will implicitly have the specific translation that I require and common.

@mss-souloftware
Copy link

mss-souloftware commented Jun 19, 2023

getStaticProps

Hello @ivnmood But I want to use it in the components folder because I'm using the navbar as a component.
Here is code I'm using.

import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { UseTranslation } from 'next-i18next';

import Link from 'next/link';
import Language from './Language';

const links = [
    { href: '/', label: 'Home' },
    { href: '/about', label: 'About' }
];


export default function MenuItems() {
    const { t } = UseTranslation('menus');
    return (
        <ul className='flex'>
            {
                links.map((link, index) => (
                    <Link
                        key={index}
                        href={link.href}
                        className=" text-[#414052] hover:text-[#AC6DDE] transition-colors mx-[10px]"
                    >
                        {link.label}
                    </Link>
                ))
            }
            <Language />
            {t('about')}
        </ul>
    )
}

export async function getStaticProps({ locale }) {
    return {
        props: {
            ...(await serverSideTranslations(locale, ['menus']))
        }
    };
}

@adrai
Copy link
Member

adrai commented Jun 19, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests