6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

マイクロフロントエンドでWeb Componentsを使う方法について

Last updated at Posted at 2021-07-23

今回は以前紹介したWeb Componentsを使う方法について詳しく書いていこうと思います。

概要

AngularとReactでWeb Componentsを使ってMicrofrontEndsを実装し、Githubに載せている方がいたのでそれを実装してみました。

先にコードを見た方が分かりやすいかもしれないです。

e3ab0ca0-7b18-71f9-16ce-9660e5599d1c.png

↑実装画面

構成、Usage、使われている技術を紹介します。

構成

c5e80bf9-ff1f-d38f-9785-ceb77f7315f9.png

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
で起動します。

a012f4b0-840b-5e87-6057-38c73c881a15.png

そして、
http://localhost:5000
を開けば先程の実装画面が表示されます。

使われている技術

serve

Web Componentsを用いてMicrofrontEndsを実装するために、マイクロサービスとして静的なJavaScriptファイルを統合しなければならない。そこで、今回はローカル環境ではserveを使う。
serve - npm

Reactコンポーネントにおいて

Custom ElementのAPI connectedCallback() と disconnectedCallback() を使うことによって、Reactのコンポーネントをrender()unmount() にマッピングできる。

index.js
class MyCustomElement extends HTMLElement {
  constructor() {
    super();
  }
  connectedCallback() {
    ReactDOM.render(<MyReactComponent />, this);
  }
  disconnectedCallback(){
    ReactDOM.unmountComponentAtNode(this);
  }
}

customElements.define('react-el', ReactElement);

Wrapper コンポーネントにおいて

CDNでzone.jscustom-elements-es5-adapter.jsを読み込む

  • zone.js はAngularのために必要なもの
  • custom-elements-es5-adapter.js はブラウザ内でCustom Elementを使用するために必要。Web Components - React(Reactの公式)でも記述されている。

AngularのコンポーネントとReactのコンポーネントも読み込む

index.html
<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が関わっている部分の大まかな全体像

index.html
<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 - React

serve - npm

デモ実装

Web Componentsを用いてマイクロフロントエンドのデモを実装してみました

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?