如何用Yarn构建可被浏览器import的ES6模块及兼容React上下文的组件?
解决React模块构建后无法被浏览器import()访问及上下文冲突问题
一、构建后导出丢失的修复
react-scripts默认是把项目打包成单页应用,不是可复用的库,直接构建会丢失导出内容。需要修改webpack配置,把项目打包成兼容浏览器的UMD格式模块:
- 安装craco(无需eject即可修改create-react-app配置的工具):
yarn add @craco/craco --dev
- 根目录新建
craco.config.js,配置webpack输出为UMD库:
module.exports = { webpack: { configure: (webpackConfig, { env, paths }) => { // 指定库的入口文件(根据你的项目调整路径) paths.appIndexJs = './src/index.js'; // 配置输出为UMD格式,兼容浏览器ES模块、CommonJS等多种规范 webpackConfig.output = { ...webpackConfig.output, library: 'CustomModule', libraryTarget: 'umd', umdNamedDefine: true, globalObject: 'this' }; // 禁用代码分割,避免生成多个零散chunk,保证模块为单一可加载文件 webpackConfig.optimization.splitChunks = undefined; webpackConfig.optimization.runtimeChunk = false; return webpackConfig; } } };
- 修改package.json里的build脚本:
"scripts": { "build": "craco build", // 其他脚本保持不变 }
- 源码用ES模块语法导出需要暴露的内容:
// src/index.js export const funcs = { myFunc: () => { // 你的函数逻辑 } }; export const components = { CloneButton: () => { // 你的组件代码 } };
执行yarn build后,dist目录下的main.js就是可被浏览器import()加载的模块,不会再出现仅输出严格模式包装代码的情况。
二、React上下文冲突的修复
出现useContext、useResourceContext报错,是因为构建后的模块打包了独立的React副本,和主应用的React实例不是同一个,导致上下文不匹配。解决方法是把React设为外部依赖,让库复用主应用的React:
修改craco.config.js,添加externals配置:
module.exports = { webpack: { configure: (webpackConfig, { env, paths }) => { // ...保留之前的配置 // 将React、ReactDOM设为外部依赖,不打包进库文件 webpackConfig.externals = { react: 'React', 'react-dom': 'ReactDOM' // 如果用到其他React生态库(如react-router-dom),也需要添加到这里 }; return webpackConfig; } } };
这样构建后的库不会包含React代码,会直接使用主应用提供的全局React实例,上下文就能保持一致,钩子也能正常工作。
三、验证
- 运行
yarn build,检查dist/main.js,能看到UMD格式的包裹代码,以及你的funcs、components导出内容; - 将dist里的文件放到主应用可访问的静态资源路径;
- 用你提供的代码加载模块:
import(/* webpackIgnore: true */ js_module).then((mod) => { Object.assign(COMPONENTS, mod.components); Object.assign(USER_FUNCS, mod.funcs); });
此时应该能正常访问mod.funcs、mod.components,React组件的钩子也不会再报错。
内容的提问来源于stack exchange,提问作者Sam Bull
相关产品推荐
相关产品推荐

