Web组件化(Web Components) - React转换为Web Component
最近在思考如何实践微前端, 方案有许多,Web Components也是其中之一。 本文就先从如何将React组件转换为Web Component组件开始,探索Web Component实现微前端的方案。 当然市面上成熟的框架,如SingleSPA,QianKun自然也是可以实现Micro-Frontend,本文只是作为一种可能性研究。
首先,参考我先前的文章,建立一个React项目。
最终结构如下:
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/app.tsx',
module: {
rules: [
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript",
],
},
}
}
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js'
}
};
package.json
{
"name": "web-component",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack --mode=development",
"build": "webpack --mode=production"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.15.8",
"@babel/preset-env": "^7.15.8",
"@babel/preset-react": "^7.14.5",
"@babel/preset-typescript": "^7.15.0",
"@types/react": "^17.0.31",
"@types/react-dom": "^17.0.10",
"babel-loader": "^8.2.3",
"babel-plugin-transform-class-properties": "^6.24.1",
"webpack": "^5.59.1",
"webpack-cli": "^4.9.1"
},
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2",
"typescript": "^4.4.4"
}
}
.babelrc
{
"presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"],
"plugins": ["@babel/plugin-proposal-class-properties"]
}
app.tsx
import React from 'react';
import ReactDOM from 'react-dom';
function Hello() {
return (
<div>
Hello World!
</div>
);
}
// Name of our class doesn't matter.
class HelloElement extends HTMLElement {
// Happens every time an instance of this element is mounted
// (can be called again when moved from one container element to another)
connectedCallback() {
ReactDOM.render(
<div>
<Hello></Hello>
<button onClick={() => alert("Clicked")}>
Click Me!
</button>
</div>,
this
);
}
}
const tagName = "hello-component";
if (!window.customElements.get(tagName)) {
// prevent rerunning on hot module reloads
// register to be rendered in place of every <evil-plan> tag
window.customElements.define(tagName, HelloElement);
}
index.html
<html>
<script src='bundle.js'></script>
<body>
<hello-component></hello-component>
</body>
</html>
执行npm run build
webpack会在public文件夹下生成bundle.js, 并被index.html引用。 index.html中使用
最后浏览index.html页面即可。
当然,该demo仅仅是第一步,后面还会讨论:
1:Shell App与Web Component的交互,包括通过属性传参、触发事件等等
2:路由,Shell App如何通过路由变化加载对用的Web Component。 作为React应用,Web Component应该选择什么路由策略,才不会影响Shell App。
3:样式隔离。 Web Component间的样式互相隔离,但Shell App可以通过设置全局变量改变Web Component的样式
4:动态加载Web Component
5:其他暂时未想到的
顺便说一句,GitHub的网站就是通过Web Component实现的,打开源码可以看到。
参考:
https://tinloof.com/blog/how-to-create-microfrontends-with-web-components-in-react/