如何通过script标签对外发布React组件并嵌入第三方站点使用
一、react-scripts 运行与打包核心逻辑
- 本地运行(
npm start)逻辑:react-scripts 底层基于 webpack-dev-server 实现,会对项目源码做增量编译,所有编译产物直接存在内存中,自动注入到项目默认的public/index.html模板中,最终把<App/>组件渲染到模板里id="root"的div节点上,你本地预览的就是这个内存中生成的页面。 - 生产打包(
npm run build)默认产出:默认执行打包命令后,会在项目根目录的build文件夹下生成多份拆分的产物,不存在你需要的单app.js文件:- 多份哈希命名的JS包:分为业务代码包(main.xxx.js)、第三方依赖包(包含React、MUI等公共依赖的2.xxx.js)、webpack运行时包(runtime-main.xxx.js)
- 单独拆分的CSS样式包、静态资源文件、编译后的入口index.html
这种多包拆分是默认的性能优化策略,用来减小单文件体积、提升加载速度,如果要输出单JS文件需要手动修改打包配置。
二、改造为单script嵌入产物的实现步骤
第一步:修改打包配置输出单JS文件
推荐用craco覆盖默认配置,不用弹出eject破坏原有项目结构:
- 安装依赖:
npm i @craco/craco style-loader --save-dev - 项目根目录新建
craco.config.js配置文件,写入以下内容:
module.exports = { webpack: { configure: (webpackConfig) => { // 关闭代码拆分,合并所有JS内容到单文件 webpackConfig.optimization.splitChunks = { cacheGroups: { default: false, }, }; webpackConfig.optimization.runtimeChunk = false; // 固定输出文件名,取消哈希后缀,直接生成app.js webpackConfig.output.filename = 'static/js/app.js'; // 把CSS样式直接内嵌到JS中,不输出单独CSS文件,避免第三方额外引入样式 webpackConfig.module.rules.forEach(rule => { if (rule.oneOf) { rule.oneOf.forEach(oneOf => { if (oneOf.test?.toString().includes('css')) { oneOf.use = oneOf.use.filter(loader => !/mini-css-extract-plugin/.test(loader.loader)); oneOf.use.unshift(require.resolve('style-loader')); } }) } }) return webpackConfig; } } }
- 修改
package.json中的scripts命令,把所有react-scripts替换为craco,示例:
"scripts": { "start": "craco start", "build": "craco build", "test": "craco test", "eject": "react-scripts eject" }
第二步:修改挂载逻辑,自动创建渲染容器
修改入口文件index.js,不依赖第三方站点的现有DOM节点,脚本加载后自动插入容器:
import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; // 自动创建专属挂载节点 const mountNode = document.createElement('div'); mountNode.id = 'custom-support-chat-box'; // 给容器加基础样式,避免被第三方页面样式干扰,示例固定悬浮在右下角 mountNode.style.cssText = ` position: fixed; bottom: 20px; right: 20px; z-index: 999999; width: fit-content; height: fit-content; `; document.body.appendChild(mountNode); const root = ReactDOM.createRoot(mountNode); root.render( <React.StrictMode> <App /> </React.StrictMode> );
注意可以给MUI的ThemeProvider配置自定义类名前缀,进一步避免样式和第三方站点冲突。
第三步:获取最终可分发的app.js
执行npm run build命令完成打包后,直接取build/static/js/app.js文件即可,将该文件上传到你的服务端对应路径myserver.com/support/123456789/下,第三方站点直接引入你给出的script标签就会自动渲染客服聊天盒子。
内容的提问来源于stack exchange,提问作者Ronnis
相关产品推荐
相关产品推荐

