如何通过react-app-rewired配置externals外置Create React App PWA TypeScript项目中的Material-UI
解决React App Rewired配置Material-UI Externals的问题
我之前在CRA的PWA TypeScript项目里也碰到过一模一样的问题,用react-app-rewired配置externals排除Material-UI时,要么编译报错要么根本没生效,折腾了好一会儿才找到正确的姿势,给你梳理下步骤:
1. 先正确引入CDN资源
首先要在public/index.html里按顺序引入CDN脚本,Material-UI依赖React和ReactDOM,所以必须先加载这两个:
<!-- React 和 ReactDOM 要放在最前面 --> <script crossorigin src="https://unpkg.com/react@你的版本/umd/react.production.min.js"></script> <script crossorigin src="https://unpkg.com/react-dom@你的版本/umd/react-dom.production.min.js"></script> <!-- Material-UI Core --> <script src="https://unpkg.com/@material-ui/core@你的版本/umd/material-ui.production.min.js"></script> <!-- 如果用到Material-UI Icons --> <script src="https://unpkg.com/@material-ui/icons@你的版本/umd/material-ui-icons.production.min.js"></script>
⚠️ 注意:一定要保证CDN的版本和你package.json里的Material-UI版本完全一致,避免兼容性问题。
2. 正确配置React App Rewired的Externals
之前你用数组或正则的方式之所以不行,是因为Material-UI的UMD包是把整个库暴露成一个全局对象,而不是每个子模块单独暴露。所以需要用对象形式的externals,明确映射每个包到对应的全局变量:
在项目根目录的config-overrides.js里修改配置:
module.exports = function override(config, env) { // 合并原有externals,避免覆盖其他配置 config.externals = { ...config.externals, 'react': 'React', 'react-dom': 'ReactDOM', '@material-ui/core': 'MaterialUI', '@material-ui/icons': 'MaterialUI.Icons' }; return config; };
为什么这个配置能生效?
@material-ui/core的UMD包会在全局环境中注册MaterialUI对象,所有组件都挂载在这个对象下(比如MaterialUI.Button)@material-ui/icons的UMD包会把图标挂载到MaterialUI.Icons上(比如MaterialUI.Icons.AddCircle)- 这种对象映射的方式,会告诉Webpack:当代码里导入
@material-ui/core时,直接去全局的MaterialUI对象里取,不用打包进bundle
3. 验证配置是否生效
配置完成后,运行npm run build,然后可以通过以下方式验证:
- 查看
dist目录下的bundle大小,应该会比之前小很多(Material-UI本身体积不小) - 用
source-map-explorer分析bundle,确认@material-ui/core和@material-ui/icons没有被包含在内 - 启动生产环境服务,验证界面上的Material-UI组件能正常渲染
之前你尝试的正则方式之所以报错,是因为Webpack无法找到对应正则匹配模块的全局变量,导致生成的外部模块代码无法正常运行;而单纯的包名字数组也不行,因为没有指定全局变量的映射关系。
内容的提问来源于stack exchange,提问作者Fabian
相关产品推荐
相关产品推荐

