CRA与SSR结合时动态import无法正常工作
Hey there, let's tackle this SSR + dynamic import issue you're facing with Create React App! The core problem here is that your Node.js SSR environment doesn't natively support the dynamic import() syntax (especially with variable paths), while CRA enforces using import() instead of the deprecated System.import. Here are a few practical solutions to resolve this:
Solution 1: Environment-Specific Loading (No Config Changes Needed)
The simplest workaround is to use different loading strategies for the server and client. Node.js supports require() for dynamic paths natively, so we can conditionally switch between require() (SSR) and import() (client):
let langData; // Check if we're running in the SSR (Node) environment if (typeof window === 'undefined') { // Server-side: use require to avoid import syntax errors langData = require(`localization/${newLanguage}/${newLanguage}.json`); } else { // Client-side: use import() as CRA recommends langData = await import(`localization/${newLanguage}/${newLanguage}.json`); }
Note: Make sure all your language files are placed in a directory that Node can resolve correctly (relative to your SSR entry file).
Solution 2: Use Loadable Components for SSR-Friendly Code Splitting
If you want a more robust, SSR-compatible code splitting approach, use @loadable/component—it's designed to work seamlessly with React SSR and doesn't require ejecting CRA.
- Install the package:
npm install @loadable/component
- Rewrite your dynamic import to use loadable:
import loadable from '@loadable/component'; // Wrap the dynamic import in a loadable function const loadLanguageFile = loadable(async ({ lang }) => { const file = await import(`localization/${lang}/${lang}.json`); return { default: () => file }; }); // Usage example (in your component) const LanguageData = loadLanguageFile({ lang: newLanguage }); const langData = LanguageData.default();
For SSR, you'll need to set up the @loadable/server package to preload the language files during server rendering—this ensures the data is available before sending the HTML to the client.
Solution 3: Customize CRA Config to Transpile Dynamic Imports
If you're comfortable modifying CRA's underlying config (without ejecting), use react-app-rewired and customize-cra to add the Babel plugin that transpiles import() syntax for Node.js.
- Install dependencies:
npm install react-app-rewired customize-cra @babel/plugin-proposal-dynamic-import --save-dev
- Update your
package.jsonscripts to usereact-app-rewired:
"scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test", "eject": "react-scripts eject" }
- Create a
config-overrides.jsfile in your project root:
const { override, addBabelPlugin } = require('customize-cra'); module.exports = override( addBabelPlugin('@babel/plugin-proposal-dynamic-import') );
This plugin will transpile the import() syntax into a format that Node.js can understand during SSR, while keeping CRA's client-side build intact.
内容的提问来源于stack exchange,提问作者Vincent Hoch-Drei

