Client-HMR not working for getStaticPages in NextJS
KingMatrix1989 opened this issue · 16 comments
Describe the bug
Client-HMR does not update resource that required in SSG page but not loaded by default in the I18N configuration.
To Reproduce
- Install these two dependencies:
yarn add i18next-hmr i18next-http-backend --dev
- Update the next.config.js like so:
const { resolve } = require("path")
const { I18NextHMRPlugin } = require("i18next-hmr/plugin")
const localesDir = resolve("public/locales")
module.exports = {
// ...other next config options
webpack(config, context) {
if (!context.isServer && context.dev) {
config.plugins.push(new I18NextHMRPlugin({ localesDir }))
}
return config
},
}
- Update the next-i18next.config.js like so:
const HttpBackend = require('i18next-http-backend/cjs');
const config = {
i18n: {
defaultLocale: 'fa',
locales: ['en', 'fa'],
localeDetection: false,
},
localePath: './public/locales',
use: typeof window !== 'undefined' ? [HttpBackend] : [],
};
module.exports = config;
- Create a hook for applying the HMR code during development. I created mine in hooks/use-hmr.ts and it looks like this:
import { useTranslation } from "next-i18next"
import { useEffect } from "react"
export const useHMR = (): void => {
const { i18n } = useTranslation()
if (process.env.NODE_ENV === "development" && !process.browser) {
import("i18next-hmr/server").then(({ applyServerHMR }) => {
applyServerHMR(i18n)
})
}
useEffect(() => {
if (process.env.NODE_ENV === "development") {
import("i18next-hmr/client").then(({ applyClientHMR }) => {
applyClientHMR(i18n)
})
}
}, [i18n])
}
- Import and pass next-i18next.config.js to appWithTranslation (typically in pages/_app.tsx) and use the HMR hook created above within the body of the App component:
import { AppProps } from "next/app"
import { FunctionComponent } from "react"
import { appWithTranslation } from "next-i18next"
import { useHMR } from "../hooks/use-hmr"
import i18nextConfig from "../../next-i18next.config"
export const App: FunctionComponent<AppProps> = ({ Component, pageProps }) => {
useHMR()
return <Component {...pageProps} />
}
export default appWithTranslation(App, i18nextConfig) // Required to use the HttpBackend that enables HMR on the client
- Create a SSG page (here faq):
import { GetStaticProps } from 'next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
const Faq = () => {
return (
// Content of page
<></>
);
};
export const getStaticProps: GetStaticProps = async ({ locale }) => {
return {
props: { ...(await serverSideTranslations(locale, ['common', 'faq', 'footer'])) },
};
};
export default Faq;
- Update content of faq.json (any language)
- Update content of common.json (any language)
Expected behavior
- faq.json updates don't apply to client-side.
- But Update of common.json, affecting client-side as well.
I am using:
- OS: Win
- i18next-hmr version: 1.7.7
- next-i18next version: 11.0.0
- i18next-http-backend version: 1.4.0
It seems Client-HMR only works in case that all namespaces declared in next-i18next-config, because the plugin check for i18n.options.ns by default.
If we change the source code of client-hmr.js as below, problem will be solved:
// other code
module.hot.accept('./trigger.js', () => {
const { changedFiles } = require('./trigger.js');
const currentNSList = Object.keys(i18n.store.data[i18n.language]); // get all loaded namespaces
const list = changedFiles
.map((changedFile) => extractLangAndNS(changedFile, currentNSList))
.filter(({ lang, ns }) => Boolean(lang) && Boolean(ns));
if (!list.length) {
return;
}
log(`Got an update with ${printList(list)}`);
return reloadTranslations(list);
});
Thank you, I'll review it asap
i18next configuration may contain only default namespace common, so options.ns
will be equal to ['common']
; on both the server and client sides.
It is not true, in the images I've added, the values are from server & client at runtime
@felixmosh You are right.
And what do you think about i18n.store.data
? It includes all namespaces on both sides.
It's possible, but I don't want to solve a bug of other lib.
@skmohammadi if you have sometime, maybe you can prepare a PR for next-i18next
, it should be straight forward.
It's possible, but I don't want to solve a bug of other lib.
It appears to be a problem with your library and implementation of i18n.store.data will correct it.
How i18n.options related to this lib, this lib is only reading from it.
The problem is that the field is not properly passed to the client (as a proof, server side works properly).
Hi @skmohammadi , can you try v11.2.1
of next-i18next
it should work now.
Check i18next/next-i18next#1839
Hi @felixmosh. I appreciate you following up on this matter. Sure, I'll check it out.
Thank you @felixmosh. Now, it works as expected.
Can we close this issue?
Please check the new example of Next-i18next https://github.com/felixmosh/i18next-hmr/tree/master/examples/next-with-next-i18next-v11