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/