准备工作
用webpack新建一个react本地项目、我这里使用webpack5,配置如下:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js', // 入口文件
output: {
filename: 'bundle.js', // 输出文件名
path: path.resolve(__dirname, 'dist') // 输出目录
},
devServer: {
static: {
directory: path.join(__dirname, 'dist'), // 本地服务器所加载的页面所在的目录
},
compress: true, // 启用 gzip 压缩
port: 9000, // 本地服务器端口号
open: true // 自动打开浏览器
},
module: {
rules: [
{
test: /(.jsx|.js)$/,
use: ["babel-loader"],
exclude: /node_modules/
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', // 指定自定义 HTML 模板
filename: 'index.html' // 生成的 HTML 文件名
}),
],
mode: 'development' // 开发模式
};
index.js
import { createRoot } from 'react-dom/client'
import React from 'react'
import App from './App.jsx'
const Root = createRoot(document.getElementById('app'))
Root.render(<App />)
babel.config.json
{
"presets": [
"@babel/preset-react",
]
}
相关依赖
"webpack": "^5.0.0",
"webpack-cli": "^5.0.0",
"webpack-dev-server": "^4.0.0"
"@babel/core": "^7.27.4",
"@babel/preset-react": "^7.27.1",
"@babel/runtime": "^7.27.6",
"babel-loader": "^10.0.0",
"html-webpack-plugin": "^5.6.3",
"react": "^18.3.0",
"react-dom": "^18.3.0",
加入react
现在启动项目应该是能正常启动的,我们在项目中建一个package目录、clone react源码到package下面,同时安装依赖@babel/preset-flow
,因为react使用flow作为类型校验
- 将preset-flow加入babel
{
"presets": [
"@babel/preset-react",
"@babel/preset-flow"
]
}
- 在webpack中设置别名、将react相关引用指向本地
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'react': path.resolve(__dirname, 'package/react/packages/react'),
'react-dom': path.resolve(__dirname, 'package/react/packages/react-dom'),
'react-reconciler': path.resolve(__dirname, 'package/react/packages/react-reconciler'),
'scheduler': path.resolve(__dirname, 'package/react/packages/scheduler'),
'shared': path.resolve(__dirname, 'package/react/packages/shared'),
}
},
处理错误
这个时候我们启动应用会报一堆错误
- react引用错误
更改引用方式
import * as Client from 'react-dom/client'
import * as React from 'react'
const { createRoot } = Client
- ReactFiberHostConfig.js
修改react\packages\react-reconciler\src\ReactFiberHostConfig.js
// throw new Error('This module must be shimmed by a specific renderer.');
export * from './forks/ReactFiberHostConfig.dom'
- Scheduler.js报错
WARNING in ./package/react/packages/react-reconciler/src/Scheduler.js 28:35-64
export 'unstable_yieldValue' (imported as 'Scheduler') was not found in 'scheduler'
WARNING in ./package/react/packages/react-reconciler/src/Scheduler.js 29:45-84
export 'unstable_setDisableYieldValue' (imported as 'Scheduler') was not found in 'scheduler'
修改package\react\packages\scheduler\index.js
export { unstable_yieldValue, unstable_setDisableYieldValue } from './src/forks/SchedulerMock';
export * from './src/forks/Scheduler';
- ReactSharedInternals.js 报错
修改
package\react\packages\shared\ReactSharedInternals.js
// import * as React from 'react';
// const ReactSharedInternals =
// React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
import ReactSharedInternals from 'react/src/ReactSharedInternals';
export default ReactSharedInternals;
- 环境变量缺少
Uncaught ReferenceError: __EXPERIMENTAL__ is not defined
at eval (ReactFeatureFlags.js:155:21)
使用webpackDefinePlugin定义变量
const webpack = require('webpack')
new webpack.DefinePlugin({
__DEV__: true,
__PROFILE__: true,
__UMD__: true,
__EXPERIMENTAL__: true,
__VARIANT__: false,
})
现在运行你的启动命令就大功告成啦,项目结构如下