LoginSignup
5
1

More than 1 year has passed since last update.

iframe内にマークアップをレンダリングしたいときに便利なwhyframeを使ってみる

Last updated at Posted at 2022-12-07

Ateam LifeDesign Advent Calendar 2022(カレンダー2)の8日目は
株式会社エイチームライフデザインの@oekazumaが担当します。

whyframeとは

whyframeを使えば、Svelte、Vue、Solid、Preact、Reactなど、あらゆるUIフレームワークのマークアップをiframe内でレンダリングすることができます。

どういうことをしたい場合に使うと便利か?

  • 実際の使用例を示したコンポーネントライブラリのドキュメントを作りたい
  • コンポーネントの使用例を埋め込む記事を書きたい
  • StoryBookのようなものを作りたい

使い方

※今回はSvelte + Viteの例で使い方を紹介します。
他の構成で試したい場合は公式ドキュメントを参照ください。

インストール

まず、新しいプロジェクトを作成して、依存関係をインストールします。

$ npm create vite@latest whyframe-demo -- --template svelte
$ cd whyframe-demo
$ npm install

次にwhyframeを使うために必要なパッケージをインストールします。

$ npm install -D @whyframe/core @whyframe/svelte

執筆時のバージョン

  • @whyframe/core: 0.1.9
  • @whyframe/svelte:0.1.5

設定

vite.config.jsに設定を記述していきます。

注意
whyframeはコンパイル済みコードではなく生のフレームワークコードを前処理する必要があるのでwhyframeSvelte()svelte()の前に必ず記述するようにしてください。

vite.config.js
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
+ import { whyframe } from '@whyframe/core';
+ import { whyframeSvelte } from '@whyframe/svelte';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
+   whyframe(),
+   whyframeSvelte()
    svelte(),
  ],
});

使い方

App.svelteに以下のようにコードを書きます。
<iframe>data-whyを加えるだけでiframe内にマークアップをレンダリングすることができます。

App.svelte
<iframe data-why>
  Hello World!
</iframe>

ちゃんとHello World!が表示されてます!

スクリーンショット 2022-12-06 12.27.13.png

次は、コンポーネントを表示してみましょう。

ポップアップのコンポーネントを作って表示してみます。

Popup.svelteのコード
Popup.svelte
<script>
  export let content;
  let open = false;
</script>

<button
  class="activator"
  aria-haspopup="dialog"
  on:click={() => (open = !open)}
>
  <slot />
</button>

{#if open}
  <button class="background" on:click={() => (open = false)}>
    <p>{content}</p>
  </button>
{/if}

<style>
  .activator {
    display: block;
    border-radius: 8px;
    border: 1px solid transparent;
    padding: 0.5em 1em;
    font-size: 0.9em;
    font-weight: 500;
    font-family: inherit;
    color: #efefef;
    background-color: #1e1e1e;
    cursor: pointer;
    transition: border-color 0.25s;
  }

  .activator:hover {
    border-color: #ffed24;
  }

  .activator:focus,
  .activator:focus-visible {
    outline: 4px auto -webkit-focus-ring-color;
  }

  .background {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    border: 0;
    background-color: #090909;
    color: #efefef;
    font-size: 1.5rem;
    opacity: 0.8;
    z-index: 1;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .background:focus,
  .background:focus-visible {
    border: 4px solid #ffed24;
  }
</style>

App.svelte
<script>
  import Popup from './Popup.svelte'
  const content = 'Hoozah!'
</script>

<iframe data-why>
  <Popup {content}>Open</Popup>
</iframe>

ポップアップが表示され、動作も確認できました!
コンポーネントにpropsもきちんと渡せています。

popup.gif

HTMLソースを変更する

whyframeでレンダリング時に使用するHTMLソースを指定して変更することができます。
別のHTMLを作成して、HTMLソースを変更してみます。

other.htmlのコード
other.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Whyframe - Other</title>
    <style>
      *,
      *::before,
      *::after {
        box-sizing: border-box;
      }

      html,
      body {
        font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
        width: 100%;
        height: 100%;
        padding: 0;
        margin: 0;
      }

      body {
        background-color: #2b2b2b;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%239e9e9e' fill-opacity='0.4'%3E%3Cpath opacity='.5' d='M96 95h4v1h-4v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4h-9v4h-1v-4H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15v-9H0v-1h15V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h9V0h1v15h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9h4v1h-4v9zm-1 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm9-10v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-10 0v-9h-9v9h9zm-9-10h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9zm10 0h9v-9h-9v9z'/%3E%3Cpath d='M6 5V0H5v5H0v1h5v94h1V6h94V5H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
        background-position: 2px 2px;
        padding: 0.5rem;
        color: #efefef;
      }
    </style>
  </head>
  <body>
    <div id="app"></div>
    <script type="module">
      import { createApp } from "whyframe:app";
      createApp(document.getElementById("app"));
    </script>
  </body>
</html>


App.svelte
<script>
  import Popup from './Popup.svelte'
  const content = 'Hoozah!'
</script>

<iframe data-why>
  <p>Default HTML source</p>
  <Popup {content}>Open</Popup>
</iframe>

<iframe data-why src="/other.html">
  <p>Custom HTML source</p>
  <Popup {content}>Open</Popup>
</iframe>

使用するHTMLソースを変更できました!
スクリーンショット 2022-12-06 15.08.12.png

デフォルトのHTMLソースとして使いたい場合は設定を以下のようにvite.config.jsを変更すれば大丈夫です。

vite.config.js
import { svelte } from "@sveltejs/vite-plugin-svelte";
import { whyframe } from "@whyframe/core";
import { whyframeSvelte } from "@whyframe/svelte";
import { defineConfig } from "vite";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
+   whyframe({ defaultSrc: "/other.html" }),
    whyframeSvelte(),
    svelte(),
  ],
});

ソースコードを抽出する

「このソースコードを書いたらこのUIが実現できるよ!」というようなことを示したい場合に、ソースコードを抽出して表示できたら便利です。
<iframe>data-why-show-sourceを追加して、getWhyframeSource()を使えば取得できます。

App.svelte
<script>
  import Popup from "./Popup.svelte";
  import { getWhyframeSource } from "@whyframe/core/utils";
  import { onMount } from "svelte";

  const content = "Hoozah!";

  let iframe = null;
  let source = "";

  onMount(() => {
    source = getWhyframeSource(iframe);
  });
</script>

<iframe bind:this={iframe} data-why data-why-show-source>
  <Popup {content}>Open</Popup>
</iframe>

<p>Source:</p>
<pre>{source}</pre>

<iframe>内のソースコードが取得できました! これを使えば、ドキュメントも簡単に作れそうです。

スクリーンショット 2022-12-06 15.32.48.png

コンポーネント化して使い回す

複数箇所で使いたい場合、コンポーネント化して便利に使いまわしたいことがあると思います。
whyframeの場合、ただコンポーネント化するだけではうまく動作せず、少し設定が必要なので説明します。

まず、コンポーネントを用意します。

Story.svelte
<script>
  export let title = 'iframe'
  export let src = undefined
</script>

<p>{title}</p>
<iframe data-why {title} {src}>
  <slot />
</iframe>

コンポーネント化したコンポーネント名を以下のようにvite.config.jsに追加します。

vite.config.js
import { svelte } from "@sveltejs/vite-plugin-svelte";
import { whyframe } from "@whyframe/core";
import { whyframeSvelte } from "@whyframe/svelte";
import { defineConfig } from "vite";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
+   whyframe({ name: 'Story' }),
    whyframeSvelte(),
    svelte(),
  ],
});

Story.svelteApp.svelteで呼び出して使用してみます。

App.svelte
<script>
  import Popup from "./Popup.svelte";
  import Story from "./Story.svelte";
  const content = "Hoozah!";
</script>

<Story>
  <p>This is a Story component</p>
  <Popup {content}>Open</Popup>
</Story>

無事にレンダリングされました!

スクリーンショット 2022-12-06 15.52.19.png

最後に

今回はiframe内にマークアップをレンダリングするときに使うライブラリのwhyframeを紹介してみました!
ニッチなライブラリにはなりますが、知っていると使えるタイミングが意外とあるのでは?と思ったので是非、使ってみてください!

5
1
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
5
1