You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建可通过CDN使用且动态导入React的可复用组件

创建可通过CDN加载的无React依赖可复用组件

核心逻辑

默认不把React打包进组件包,先检查全局环境(window/globalThis)里是否存在React,不存在则自动从CDN动态加载,加载完成后再初始化组件。

1. 编写组件代码

以一个简单的自定义按钮组件为例,先做React存在性校验,缺失则动态拉取:

// MyButton.js
let React;
let ReactDOM;

// 确保React已加载的异步函数
async function loadReactIfNeeded() {
  if (!globalThis.React) {
    // 从CDN加载指定版本的React和ReactDOM
    const [reactBundle, reactDomBundle] = await Promise.all([
      import('https://unpkg.com/react@18/umd/react.production.min.js'),
      import('https://unpkg.com/react-dom@18/umd/react-dom.production.min.js')
    ]);
    // 挂载到全局,避免重复加载
    globalThis.React = React = reactBundle.default;
    globalThis.ReactDOM = ReactDOM = reactDomBundle.default;
  } else {
    React = globalThis.React;
    ReactDOM = globalThis.ReactDOM;
  }
}

// 定义组件
export async function MyButton(props) {
  await loadReactIfNeeded();
  return React.createElement('button', { onClick: props.onClick }, props.children);
}

// 提供直接渲染到DOM的方法,方便HTML中调用
export async function renderMyButton(containerId, props) {
  await loadReactIfNeeded();
  const container = document.getElementById(containerId);
  ReactDOM.render(React.createElement(MyButton, props), container);
}

2. 打包配置(以Rollup为例)

关键是配置external排除React和ReactDOM,输出适合CDN加载的UMD格式:

// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';

export default {
  input: 'src/MyButton.js',
  output: {
    file: 'dist/my-button.min.js',
    format: 'umd',
    name: 'MyButtonLib', // 全局暴露的变量名,方便HTML直接调用
    globals: {
      react: 'React',
      'react-dom': 'ReactDOM'
    }
  },
  external: ['react', 'react-dom'], // 不打包这两个依赖
  plugins: [resolve(), commonjs()]
};

3. CDN使用示例

不管页面是否提前引入React,组件都能正常运行:

<!-- 场景1:页面未提前引入React -->
<script src="https://your-cdn-domain/dist/my-button.min.js"></script>
<div id="btn-container"></div>
<script>
  MyButtonLib.renderMyButton('btn-container', {
    onClick: () => alert('按钮被点击!'),
    children: '点我试试'
  });
</script>

<!-- 场景2:页面已提前引入React -->
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://your-cdn-domain/dist/my-button.min.js"></script>
<div id="btn-container"></div>
<script>
  MyButtonLib.renderMyButton('btn-container', {
    onClick: () => alert('按钮被点击!'),
    children: '点我试试'
  });
</script>

注意点

  • 动态导入的React CDN地址可替换为你需要的版本,开发环境可改用非压缩版
  • 若组件用到React的其他子包(如react-dom/client),需在动态导入逻辑中对应添加
  • 打包时务必确认external配置正确,避免误将React打包进组件

内容的提问来源于stack exchange,提问作者Devin Rhode

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:23:21