今回は以前紹介したWeb Componentsを使う方法について詳しく書いていこうと思います。
概要
AngularとReactでWeb Componentsを使ってMicrofrontEndsを実装し、Githubに載せている方がいたのでそれを実装してみました。
先にコードを見た方が分かりやすいかもしれないです。
↑実装画面
構成、Usage、使われている技術を紹介します。
構成
micro-fe-ng … Angularのコンポーネント
micro-fe-react … Reactのコンポーネント
micro-fe-wrapper … 上の二つを統合する
Usage
Angularのコンポーネントにおいて
cd micro-fe-ng
npm i
npm i serve
npm start
とすると
http://localhost:5001/main.js
で起動します。
Reactのコンポーネントにおいて
cd micro-fe-react
npm i
npm i serve
npm start
とすると
http://localhost:5002/
で起動します。
Wrapperコンポーネントにおいて
cd micro-fe-wrapper
npm i
npm i serve
npm start
とすると
http://localhost:5000
で起動します。
そして、
http://localhost:5000
を開けば先程の実装画面が表示されます。
使われている技術
serve
Web Componentsを用いてMicrofrontEndsを実装するために、マイクロサービスとして静的なJavaScriptファイルを統合しなければならない。そこで、今回はローカル環境ではserveを使う。
serve - npm
Reactコンポーネントにおいて
Custom ElementのAPI connectedCallback()
と disconnectedCallback()
を使うことによって、Reactのコンポーネントをrender()
と unmount()
にマッピングできる。
class MyCustomElement extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
ReactDOM.render(<MyReactComponent />, this);
}
disconnectedCallback(){
ReactDOM.unmountComponentAtNode(this);
}
}
customElements.define('react-el', ReactElement);
Wrapper コンポーネントにおいて
CDNでzone.jsとcustom-elements-es5-adapter.jsを読み込む
- zone.js はAngularのために必要なもの
- custom-elements-es5-adapter.js はブラウザ内でCustom Elementを使用するために必要。Web Components - React(Reactの公式)でも記述されている。
AngularのコンポーネントとReactのコンポーネントも読み込む
<script src="https://cdnjs.cloudflare.com/ajax/libs/zone.js/0.9.1/zone.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.2.10/custom-elements-es5-adapter.js"></script>
<!- 5001がAngularのコンポーネント、5002がReactのコンポーネント -!>
<script src="http://localhost:5001/main.js"></script>
<script src="http://localhost:5002/main.js"></script>
以下がWeb Componentsが関わっている部分の大まかな全体像
<body onload="tellComponents()">
<div>...</div>
<h5 class="card-header">Angular</h5>
<div class="card-body" id="ng-container"></div>
<h5 class="card-header">React</h5>
<div class="card-body" id="react-container"></div>
<script>
function tellComponents() {
const name = document.getElementById('yourName').value;
const reactEl = document.createElement('react-el');
reactEl.setAttribute('name', name);
reactEl.setAttribute('onHelloEvt', 'onHelloEvt');
reactEl.addEventListener('onHelloEvt', (e) => helloEvent('React'));
const reactElContainer = document.getElementById('react-container')
if (reactElContainer.children.length > 0) {
reactElContainer.removeChild(reactElContainer.children[0]);
}
reactElContainer.appendChild(reactEl);
const ngEl = document.createElement('ng-el');
ngEl.setAttribute('name', name);
ngEl.addEventListener('helloEvt', (e) => helloEvent('Angular'));
const ngElContainer = document.getElementById('ng-container')
if (ngElContainer.children.length > 0) {
ngElContainer.removeChild(ngElContainer.children[0]);
}
ngElContainer.appendChild(ngEl);
logMessage('You', `my name is ${name}`)
}
function helloEvent(who) {
logMessage(who, 'hello');
}
function logMessage(source, msg) {
const msgContainer = document.getElementById('messages');
msgContainer.innerHTML += `<p><strong>${source}</strong> said ${msg}`;
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/zone.js/0.9.1/zone.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/2.2.10/custom-elements-es5-adapter.js"></script>
<script src="http://localhost:5001/main.js"></script>
<script src="http://localhost:5002/main.js"></script>
</body>
イベント(handler)や値をコンポーネント間で受け渡すとき(React)
propとして受け渡す
export class ExampleComponent extends React.Component {
static propTypes = {
name: PropTypes.string,
onHelloEvt: PropTypes.func
}
static defaultProps = {
name: "Chris"
}
render() {
const { name, onHelloEvt } = this.props;
return (
<div className="exampleComponent">
<img src="/images/react.png" alt="React Logo" className="logo" />
<p>Hello <strong>{name}</strong> from your friendly React component.</p>
<button type="submit" className="btn btn-secondary" onClick={onHelloEvt}>Say hello</button>
</div>
)
}
}
参考
Creating Micro-frontends using Web Components (with support for Angular and React)
今回主に参考にしたサイト
Github
伝わりにくい&わかりにくいと思うので実際にコードを見るとわかりやすいと思います。
デモ実装
Web Componentsを用いてマイクロフロントエンドのデモを実装してみました