阅读之前你需要知道的知识包括
我们期待所有这个系统中,所有项目的react依赖都指向同一个react core文件,这样在系统所有项目都构建完成后,react的版本就确定了下来,所以我们可以修改webpack.config.js和项目的HTML模版来达到这个目标:
对于webpack.config.js增加:
javascript{ //... external: ['react','react-dom'] //... }
对于HTML模版(这里的具体语法,需要根据具体使用的模版解析器语法来):
HTML5<script data-tn="react-bundle" type="text/javascript" src="{{reactBundlePath | safe}}"><script> <script data-tn="react-dom-bundle" type="text/javascript" src="{{reactDomBundlePath | safe"></script>
这里的 reactBundlePath 和 reactDomBundlePath是react单独编译后的结果,对应的是两个js文件。
至此react core就完成外置化,所有的子项目在单独开发时,都可以修改自己的HTML模版,以使用公共的react core,并且主系统和子系统的react实例始终一直,在
在webpack5之前,可以在webpack中增加:
javascript{ //... 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需要修改:
javascript{ //... 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模版(这里的具体语法,需要根据具体使用的模版解析器语法来):
HTML5{% if isDev%} <script type="text/javascript" src="{{ bundlePath | safe }}/client.bundle.js"></script> <script type="text/javascript" src="{{ bundlePath | safe }}/vendors.client.bundle.js"></script> <script type="text/javascript" src="{{ bundlePath | safe }}/whm.client.bundle.js"></script> <script type="text/javascript" src="{{ bundlePath | safe }}/reactRefreshEntry.client.bundle.js"></script> {% endif %} <!-- ..... --> {% if isDev%} <script type="text/javascript" src="{{ bundlePath | safe }}/main.client.bundle.js"></script> {% else %} {% for url in clientBundle %} <script type="text/javascript" src="{{ bundlePath }}/{{ url | safe }}"></script> {% endfor %} {% endif %}
至此就完成在monorepo下,react项目的局部热更新。