使用ReactJS CDN导入组件报错:require未定义,求解决方法
解决CDN搭建React项目时的require未定义错误
错误原因
你在News.js中使用了ES Module的import语法,而Babel Standalone默认会将其转换为Node.js环境的require语法,但浏览器原生没有require函数,因此抛出Uncaught ReferenceError: require is not defined错误。
解决方案
下面提供两种适合CDN场景的解决方法:
方法一:将组件挂载到全局对象(最简便)
这种方式无需依赖模块系统,直接把组件暴露到全局window对象中:
- 修改
NewsContent.js,移除export default,将组件挂载到全局:
'use strict'; const React = window.React; const e = React.createElement; function NewsContent(props) { return ( <div> <h1>News Content</h1> <p>Lorem Ipsum</p> </div> ); } // 将组件挂载到全局window对象 window.NewsContent = NewsContent;
- 修改
News.js,移除import语句,直接使用全局的NewsContent:
'use strict'; const React = window.React; const ReactDOM = window.ReactDOM; const e = React.createElement; // 直接从全局获取组件 const NewsContent = window.NewsContent; function News(props) { return ( <div className="container"> <NewsContent /> </div> ); } const domContainer = document.querySelector('#news'); const root = ReactDOM.createRoot(domContainer); root.render(e(News));
- 调整
index.html的脚本引入顺序,确保先加载NewsContent.js再加载News.js:
<html> <head> <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> </head> <body> <div id="news"></div> <!-- 先加载NewsContent.js,再加载News.js --> <script src="NewsContent.js"></script> <script type="text/babel" src="news.js"></script> </body> </html>
方法二:使用浏览器原生ES Module
如果想保留模块导入语法,可以使用浏览器原生支持的ES Module:
- 修改
NewsContent.js,保留export default:
'use strict'; const React = window.React; const e = React.createElement; export default function NewsContent(props) { return ( <div> <h1>News Content</h1> <p>Lorem Ipsum</p> </div> ); }
- 修改
News.js,确保导入路径带.js后缀:
'use strict'; const React = window.React; const ReactDOM = window.ReactDOM; const e = React.createElement; // 注意导入路径必须带.js后缀 import NewsContent from './NewsContent.js'; function News(props) { return ( <div className="container"> <NewsContent /> </div> ); } export default News;
- 调整
index.html,使用type="module"的脚本加载模块,并处理JSX:
<html> <head> <script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> </head> <body> <div id="news"></div> <script type="module"> // 使用Babel转换模块中的JSX const moduleText = await fetch('./news.js').then(res => res.text()); const transformedCode = Babel.transform(moduleText, { presets: ['react'] }).code; const moduleObj = {}; await import('data:text/javascript,' + encodeURIComponent(transformedCode)).then(mod => { moduleObj.News = mod.default; }); const domContainer = document.querySelector('#news'); const root = ReactDOM.createRoot(domContainer); root.render(React.createElement(moduleObj.News)); </script> </body> </html>
注意事项
- 方法一适合快速搭建简单Demo,无需复杂配置;
- 方法二需要浏览器支持ES Module(现代浏览器均支持),但处理JSX需要额外的Babel转换步骤。
内容的提问来源于stack exchange,提问作者Exequiel Vibar
相关产品推荐
相关产品推荐

