Nuxt.jsで作ったページをWeb Components化してAmplifyで公開する

Nuxt.js Amplify

Web Componentsとは

Web Componentsとは、独自にカスタムしたHTML要素をカプセル化して、再利用可能にする技術です。Vue.jsなどのJSフレームワークでは一般的なコンポーネントのようなものをイメージするとわかりやすいです。
Web Componentsを利用するにあたってライブラリは不要で、JSのみで利用できます。比較的新しい技術ではありますが、2021年8月時点でのサポート状況を確認してみると、主要なモダンブラウザは一通りサポートしているようです。

使うことになった背景

親となるアプリケーション内で、別のアプリケーションを動かし、同一のアプリケーションのように振舞う仕様とする必要がありました。はじめは捻りなく、iframeでの実装を考えたのですが、フレームはデメリットも多いため、何か方法は無いかと探っていたところ、Web Componentsというワードがヒットしました。

NuxtでのWeb Components公開

今回はNuxt.jsを使用してWeb Componentsを作成し、AWSのAmplify上で公開していきます。「nuxt-custom-elements」というライブラリが用意されており、これを使うと難しいことは無く、通常のNuxt.jsアプリとして開発してカスタムHTML要素を公開することができます。以降で手順を説明していきます。

前提条件

Nuxt.jsアプリケーションを開発できる環境、およびAmplify CLIはインストール済みとします。また、私はWindows10にてWSL2を使用して動かすUbuntu 20.04にて実践しました。
参考: GitHub 公式リポジトリ

1. Nuxt.jsプロジェクト作成と nuxt-custom-elements の追加

まずは通常通り、create-nuxt-appでプロジェクトを作成します。

$ yarn create nuxt-app myapp

続いて、プロジェクトにnuxt-custom-elementsを追加します。

$ yarn add nuxt-custom-elements

たったこれだけです。

2. コンポーネントを作成する

続いて、コンポーネントを作成します。propsでタイトルを受け取り表示する、簡単なコンポーネントです。「/component/Example.vue」を作成し、下記の通り記述します。

<template>
  <div class="custom-element-example">
    <div class="title">
      {{ exampleTitle }}
    </div>
    <div class="content">
      <slot>Default Content</slot>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    title: {
      type: String,
      default: null
    }
  },
  computed: {
    exampleTitle () {
      return this.title || 'Default Title';
    }
  }
};
</script>

<style scoped>
.custom-element-example {
  min-width: 300px;
  padding: 10px;
  font-family:
    'Source Sans Pro',
    -apple-system,
    BlinkMacSystemFont,
    'Segoe UI',
    Roboto,
    'Helvetica Neue',
    Arial,
    sans-serif;
  font-size: 16px;
  color: #35495e;
  text-align: center;
  background: #35495e;
  border-radius: 4px;
}

.title {
  margin-bottom: 10px;
  font-size: 24px;
  font-weight: bold;
  text-transform: uppercase;
}

.title,
.content {
  padding: 5px;
  color: white;
  background: #3b8070;
}
</style>

3. nuxt.config.jsに公開設定を追加する

nuxt.config.jsに公開するWeb Componentsの設定を追加します。

export default {
-省略-
  modules: [
    'nuxt-custom-elements'
  ],
  customElements: {
    entries: [
      {
       name: 'Example',
       tags: [
         {
           name: 'CustomElementExample',
           path: '@/components/Example',
           options: {
             props: {
               title: 'Prop. Example Title'
             }
           },
           slotContent: 'Slot Example Content'
         }
       ]
     }
   ]
  },
-省略-
}

とりあえずの動作確認用に、「/pages/index.vue」を下記の通り編集しておきます。

<template>
  <Example title="Prop. Example Title" />
</template>
<script>
import Example from '~/components/Example.vue'
export default {
  components: { Example }
}
</script>

yarn dev を実行してアクセスすればページが表示されるはずです。
また、yarn generateを実行すると、dist配下に「nuxt-custom-elements/example」というディレクトリが作成され、その中にexample.jsというファイルが作成されるはずです。他のアプリケーションから呼び出す場合は、このファイルを読み込んで利用することになります。

ここまでうまくいったら、amplify publishでホスティングしてください。

Web Componentsの利用

ホスティングが完了したら、利用するのは簡単です。公開したjsファイルを読み込み、カスタム要素をHTMLに記述するだけです。例えば、下記のようなHTMLファイルを作成すれば、作成したコンポーネントと同一のコンテンツが表示されるはずです。

<!doctype html>
<html lang="ja">
    <head><meta charset="utf-8">
        <title>

        </title>
    </head>
    <body>
        <custom-element-example title="Prop. Example Title">
            Slot Example Content
        </custom-element-example>
        <script src="https://xxxxxxxxxxxxxxxx.com/nuxt-custom-elements/example/example.js"></script>
    </body>
</html>

もちろん、他のNuxtアプリからも利用できます。

<template>
  <custom-element-example title="Prop. Example Title">
    Slot Example Content
  </custom-element-example>
</template>
<script>
export default {
  head: {
    script: [
      {
        body: true,
        src: 'https://xxxxxxxxxxxxxxxx.com/nuxt-custom-elements/example/example.js'
      }
    ]
  }
}
</script>

ひとまず駆け足で公開から利用までを試してみました。

コメント

タイトルとURLをコピーしました