升级React 18后Webpack报错:无法解析'react-dom/client'模块
React 18升级后
react-dom/client导入失败的解决办法 问题描述
将项目React版本从v17.0.2升级到v18.x后,npm i执行正常,但尝试从react-dom/client导入createRoot方法时,出现以下错误:
Module not found: Error: Can't resolve 'react-dom/client' in 'My-local-path'
不导入该模块时应用可正常编译,只要导入(即使不使用createRoot)就会报错。
相关代码示例(appLoader.js):
import React from 'react'; import ReactDOM from 'react-dom'; import { MemoryRouter, Route } from 'react-router-dom'; // import { createRoot } from 'react-dom/client'; // 这行代码导致报错 // 以下代码可以正常运行 ReactDOM.render( <React.StrictMode> <MemoryRouter> <Route component={() => 'hello world'} /> </MemoryRouter> </React.StrictMode>, document.getElementById('root') ); // 想要替换成的React 18代码 // const container = document.getElementById('root'); // if (container) { // createRoot(container).render( // <React.StrictMode> // <MemoryRouter> // <Route component={() => 'hello world'} /> // </MemoryRouter> // </React.StrictMode> // ); // }
问题根源
查看你的webpack配置文件,发现开发环境下react-dom被别名指向了@hot-loader/react-dom@17.0.1:
// webpack.config.js 中的 resolve.alias 配置 alias: { // ...其他别名 'react-dom': isDev ? '@hot-loader/react-dom' : 'react-dom', }
而@hot-loader/react-dom@17.0.1是适配React 17的热加载补丁版本,根本不存在react-dom/client这个子模块,这就是导致导入失败的直接原因。
解决方案
方案1:升级热加载依赖适配React 18
- 卸载旧版本的
@hot-loader/react-dom:
npm uninstall @hot-loader/react-dom
- 安装与你当前
react-dom版本(18.2.0)匹配的@hot-loader/react-dom:
npm install @hot-loader/react-dom@18.2.0 --save-dev
- 保留原有的webpack别名配置,重新执行依赖安装和编译:
rm -rf node_modules package-lock.json npm install npm run build # 或对应的开发编译命令
方案2:改用React官方Fast Refresh替代react-hot-loader
React 18官方已经支持更高效的热刷新(Fast Refresh),可以完全替换老旧的react-hot-loader:
- 卸载相关旧依赖:
npm uninstall react-hot-loader @hot-loader/react-dom
- 安装Fast Refresh相关依赖:
npm install @pmmmwh/react-refresh-webpack-plugin react-refresh --save-dev
- 修改webpack配置:
- 导入
ReactRefreshWebpackPlugin:const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); - 在
plugins数组中添加开发环境下的插件:ifDev(new ReactRefreshWebpackPlugin()), - 修改babel配置,添加
react-refresh/babel插件(仅开发环境):// babel.config.js module.exports = { // ...其他配置 plugins: [ ['@babel/plugin-proposal-class-properties', { loose: true }], ...(process.env.NODE_ENV === 'development' ? ['react-refresh/babel'] : []), ], };
- 导入
- 移除webpack中
react-dom的别名配置,重新安装依赖并编译。
临时应急方案(不推荐长期使用)
如果暂时不想调整热加载方案,可以在开发环境下取消react-dom的别名强制使用官方版本,但会失去热加载功能:
// webpack.config.js 中修改 alias alias: { // ...其他别名 // 注释或删除这一行:'react-dom': isDev ? '@hot-loader/react-dom' : 'react-dom', }
已尝试方案的补充说明
你之前尝试的删除依赖重装、调整babel配置等操作未解决问题,核心原因就是@hot-loader/react-dom版本不兼容React 18的新模块结构。
配置文件参考
webpack.config.js(关键部分)
// ...其他配置 resolve: { fallback: { crypto: require.resolve('crypto-browserify'), path: require.resolve('path-browserify'), stream: require.resolve('stream-browserify'), }, modules: [ path.resolve(__dirname, './src'), path.resolve(__dirname, './assets'), 'node_modules', ], alias: { '@': path.resolve(__dirname, './src'), '../../theme.config$': path.join( __dirname, './src/theme/semantic/theme.config.less' ), 'react-dom': isDev ? '@hot-loader/react-dom' : 'react-dom', // 问题所在的别名 }, }, // ...其他配置
babel.config.js
module.exports = { sourceType: process.env.NODE_ENV === 'production' ? 'unambiguous' : 'module', presets: [ ['@babel/preset-react', { 'runtime': 'automatic' }], ['@babel/preset-env', { loose: true, useBuiltIns: 'usage', corejs: { version: 3, proposals: true }, modules: false, targets: { browsers: process.env.NODE_ENV === 'production' ? 'chrome 53, safari 10, >0.1%' : 'chrome 86, safari 10' }, }], ], plugins: [ ['@babel/plugin-proposal-class-properties', { loose: true }], 'react-hot-loader/babel', ], };
package.json(部分依赖)
"devDependencies": { "@hot-loader/react-dom": "^17.0.1", // 版本不兼容React 18 // ...其他依赖 }, "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", // ...其他依赖 }
内容的提问来源于stack exchange,提问作者Fer Toasted
相关产品推荐
相关产品推荐

