如何打包NextJS 14.2.3 React组件以注入任意网站?
打包NextJS React组件用于嵌入外部网站(WordPress/任意站点)
针对你的需求,直接用Webpack打包单个NextJS组件容易出现React重复引入、Tailwind样式丢失、运行时不兼容等问题,下面提供两种可靠方案,涵盖基础组件打包及后续扩展(Stripe、lucide-react、API通信)的适配方法。
方案一:使用Rollup打包独立可嵌入组件(推荐)
Rollup更适合打包库/独立组件,能灵活处理依赖和模块格式,适配任意外部网站。
1. 安装打包依赖
npm install --save-dev rollup rollup-plugin-node-resolve rollup-plugin-commonjs rollup-plugin-typescript2 rollup-plugin-postcss @rollup/plugin-babel @babel/preset-react @babel/preset-env
2. 创建Rollup配置文件(rollup.config.js)
import resolve from 'rollup-plugin-node-resolve'; import commonjs from 'rollup-plugin-commonjs'; import typescript from 'rollup-plugin-typescript2'; import postcss from 'rollup-plugin-postcss'; import babel from '@rollup/plugin-babel'; export default { input: './app/test.tsx', output: { file: './public/test-bundle.js', format: 'umd', // 兼容全局变量、AMD、CommonJS,适合嵌入任意网站 name: 'TestComponent', // 组件挂载到window的全局变量名 globals: { react: 'React', 'react-dom': 'ReactDOM' } }, external: ['react', 'react-dom'], // 不打包React,让宿主网站提供(减小bundle体积) plugins: [ resolve(), // 解析node_modules中的依赖 commonjs(), // 转换CommonJS模块为ES模块 typescript({ tsconfig: './tsconfig.json', useTsconfigDeclarationDir: true }), postcss({ extract: './public/test-bundle.css', // 提取Tailwind样式到单独CSS文件 minimize: true, modules: false }), babel({ presets: ['@babel/preset-react', '@babel/preset-env'], exclude: 'node_modules/**', babelHelpers: 'bundled' }) ] };
3. 确认Tailwind配置(tailwind.config.js)
确保Tailwind能扫描到组件内的类名:
/** @type {import('tailwindcss').Config} */ module.exports = { content: ["./app/**/*.{js,ts,jsx,tsx,mdx}"], theme: { extend: {} }, plugins: [], };
4. 添加打包脚本到package.json
{ "scripts": { "build:component": "rollup -c" } }
5. 执行打包
npm run build:component
执行后会在public/目录生成test-bundle.js和test-bundle.css。
6. 嵌入到外部网站
在目标网站的HTML中添加以下代码(替换路径为你的bundle实际地址):
<!-- 若宿主网站未引入React,需先加载 --> <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script> <!-- 加载组件样式 --> <link rel="stylesheet" href="/path/to/test-bundle.css"> <!-- 加载组件bundle --> <script src="/path/to/test-bundle.js"></script> <!-- 组件挂载容器 --> <div id="test-component-root"></div> <!-- 初始化组件 --> <script> ReactDOM.render(React.createElement(TestComponent), document.getElementById('test-component-root')); </script>
方案二:NextJS导出静态组件(适合依赖NextJS生态的场景)
如果组件依赖NextJS的特定能力(如Image组件),可通过NextJS的静态导出功能生成独立资源:
1. 修改next.config.mjs
/** @type {import('next').NextConfig} */ const nextConfig = { output: 'export', distDir: 'public/component-build', // 导出到public目录下 }; export default nextConfig;
2. 创建单独的组件页面(app/embed/page.tsx)
import Test from '../test'; export default function EmbedPage() { return <Test />; }
3. 执行NextJS构建
npm run build
构建后public/component-build/会生成静态HTML、JS和CSS,可通过iframe嵌入外部网站:
<iframe src="/path/to/component-build/embed" width="100%" height="200" frameborder="0"></iframe>
后续扩展适配
Stripe集成
- 推荐让宿主网站加载官方Stripe脚本:
<script src="https://js.stripe.com/v3/"></script> - 组件中直接使用
window.Stripe初始化,避免打包Stripe增大体积。
lucide-react图标
- Rollup会自动打包图标组件,无需额外配置;若需减小体积,可按需导入单个图标:
import { ShoppingCart } from 'lucide-react';
替代Server Actions(外部网站无法直接调用NextJS Server Actions)
- 将Server Actions的逻辑抽离为NextJS API路由(
app/api/xxx/route.ts) - 组件中用
fetch调用API:
const handleSubmit = async () => { const res = await fetch('https://your-nextjs-domain/api/xxx', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ data: 'xxx' }) }); const data = await res.json(); };
内容的提问来源于stack exchange,提问作者Adrian J
相关产品推荐
相关产品推荐

