需求:
客户的项目需要用我们的功能,且需要提供个modal嵌入到他们的项目里,在他们的table中点击对应的item,弹出我提供的modal。
解决方案
项目使用cra构建,使用webpack@5.70.0的library导出为一个库给第三方使用, 官方教程创建 library
output: {
library: 'Geek'
}
这样的话客户就可以直接window.Geek.showModal()
调用我们的弹窗
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
import 'antd/dist/antd.less';
import { defaultAuditRecord } from 'constants/configration';
const modalState = {};
const createContainer = () => {
const container = document.createElement('div');
container.setAttribute('id', 'container');
document.body.append(container);
};
const renderApp = (showBtn) => {
ReactDOM.render(
,
document.getElementById('container')
);
};
// 渲染sdk
export const mount = (showBtn) => {
createContainer();
renderApp(showBtn);
};
// 显示弹窗
export const showModal = (record = defaultAuditRecord, callback = () => {}) => {
// record 为{id:1,user:""}
modalState.showModal(record, callback);
};
export const closeModal = () => {
modalState.closeModal();
};
// mount(true);
客户调用sdk
const handleAuditBtnClick = useCallback(
(record) => () => {
window.Geek.showModal(
{ id: record.id, user: record.username },
(event) => { // sdk的modal操作动作执行后的回调
if (
event === AuditModalEvent.SAVE_SUCCESS ||
event === AuditModalEvent.SUBMIT_SUCCESS ||
event === AuditModalEvent.CANCEL_SUCCESS
) {
fetchList();
}
}
);
},
[fetchList]
);
useEffect(() => {
window.Geek.mount();
}, []);
为了方便将sdk发给客户,将MiniCssExtractPlugin从配置中移除。
遇到的坑
自定义样式冲突
sdk项目使用的是styled-components,我们内部测试sdk的项目也是用styled-components创建的,我本以为该库生成的classname是随机的,但是两个项目生成的classname很多都是重复的,崩溃。。。 最容易想到的是为sdk所有classname加个前缀。
package.json"babel": { "presets": [ "@babel/preset-env" ], "plugins": [ [ "babel-plugin-styled-components", { "namespace": "geek-sdk" } ] ] },
antd的样式跟客户的样式冲突
客户的项目也用到了antd,只不过是vue版的,但是有些样式是一样的。解决思路同样是修改控件的前缀。
App.jsimport { ConfigProvider, message } from 'antd'; message.config({ prefixCls: 'sdk-antd-message', });
{showBtn && ( Edit
src/App.js
and save to reload.
index.js
import 'antd/dist/antd.less';
webpack.config.js
{
test: /\.less$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'less-loader',
options: {
lessOptions: {
modifyVars: {
'@ant-prefix': 'sdk-antd',
},
javascriptEnabled: true,
},
},
},
],
},
修改后的样式
- sdk 在客户的项目中编译报错 unexpected token
客户的项目是vue3的环境,将sdk放在src目录下编译就会报错,那么只好绕过编译,将生成的sdk.js 放到public目录下,在index.html用script标签直接引用,这样就不会报错了。