阅读之前你需要知道的知识包括
我们期待所有这个系统中,所有项目的react依赖都指向同一个react core文件,这样在系统所有项目都构建完成后,react的版本就确定了下来,所以我们可以修改webpack.config.js
和项目的HTML模版来达到这个目标: 对于webpack.config.js
增加: 1
2
3
4
5{
//...
external: ['react','react-dom']
//...
}
1 | <script data-tn="react-bundle" type="text/javascript" src="{{reactBundlePath | safe}}"><script> |
这里的 reactBundlePath
和 reactDomBundlePath
是react单独编译后的结果,对应的是两个js文件。
至此react core就完成外置化,所有的子项目在单独开发时,都可以修改自己的HTML模版,以使用公共的react core,并且主系统和子系统的react实例始终一直,在
在webpack5之前,可以在webpack中增加: 1
2
3
4
5
6
7
8
9
10{
//...
resolve:{
//...
alias:{
'<module_name>': 'project/root/path/provide/modules'
}
}
//...
}import * as MouduleName from 'module_name'
的方式使用另一个子项目暴露的功能了。
由于react-refresh-webpack-plugin对于外置加载的react core有严格的顺序要求,所以我们需要修改项目打包的输出,由原来的单入口,改为多入口。并且在HTML模版中控制它们的加载顺序。
对于webpack.config.js
需要修改: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41{
//...
entry: isDevelopment
? {
whm: 'webpack-hot-middleware/client?quiet=true&reload=true&path=/<default>/<route>/__webpack_hmr&timeout=2000', //启用webpack-hot-middleware作为热更新服务时需要增加的
reactRefreshEntry: '@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js', //让react产生局部更新
main: clientEntry, //项目本身的入口文件
}
: clientEntry,//项目本身的入口文件
//...
module: {
rules: [
{
oneOf: [
{
test: /\.(js|ts|tsx)$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
plugins: ['lodash', isDev && require.resolve('react-refresh/babel')].filter(
Boolean
),
presets: [['@babel/env']],
},
},
],
},
],
},
//...
plugins: defultPlugins.concat(isDevelopment ? [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new ReactRefreshWebpackPlugin({
overlay: {
sockIntegration: 'whm',
},
}),
]:[])
}
对于HTML模版(这里的具体语法,需要根据具体使用的模版解析器语法来):
1 | {% if isDev%} |
至此就完成在monorepo下,react项目的局部热更新。