🥣

作成したJSスクリプトをReactで実装する

2022/05/30に公開約3,500字

ユーザーがそれぞれのプラットフォーム内だけでなく、独自でもhtmlだけでカスタマイズできたらどんなに素敵なことかそんな需要も高まっていると思います。

しかし多くのサービスが仮想DOMライブラリを使って開発されておりピュアDOMの操作が難しくなっております。そんな時代背景もあり SolidJSSvelte などの直接DOM操作を可能としているライブラリが出てきているのだと思って認識しております。

https://www.solidjs.com

https://svelte.dev

今回は Svelteで作成したJS を埋め込みコード(スクリプトタグ)として身立ててReactなどで操作できるようなことを検証していきたいと考えております。

目標

まずはじめにこんな埋め込みコードをReactで実装することを目標とします

<div class="app"></div>
<script type="module" src="https://scripts.hogehoge.com/assets/profile.js"></script>

1. 埋め込みコード作成

Svelte + Vite

https://ja.vitejs.dev/guide/#最初の-vite-プロジェクトを生成する
※ プロジェクト作成は割愛させていただきます

サンプルで、一旦、今回はこのようなスクリプトを作るとします

App.svelte

<script>
</script>

<div class="main">
  <h1>埋め込みスクリプトです</h1>
</div>

<style>
  .main {
    color: #fff;
    background-color: #6699FF;
  }
</style>

CSSファイルを読み込むことまではできないのでビルド対象に入れてJSの中にビルドしておきます。

  • vite.config.js
import { defineConfig } from 'vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    svelte({
      emitCss: false
    })
  ]
})
ビルド
$ npm run build

ビルドされた中身を確認します

ローカルで確認

プロジェクト内 src/index.html で下記のように変更してもローカルでスクリプトで成り立っているか確認しておきます。

index.html

<div id="app"></div>
<script type="module" src="/dist/assets/index.357a1f69.js"></script>

デプロイ前の準備

dist/assets/index.357a1f69.js をスクリプトファイルとして味気ないのでプロフィールを表示させたいという最終的な目標とし、dist/assets/profile.js とかに変更しておきます。

また下記のようにあらかじめ一旦のCORS対策しておくと良いでしょう。下記で記述しますが、surge.shを採用していきます。

https://github.com/surge-sh/example-cors

2. デプロイ

https://surge.sh
今回は仮のデプロイ先、JSを保管させていく場所を Surge.sh 使います。

手順は以下となります

1. surge.sh パッケージをインストールして
2. surge cliからユーザー登録
3. 実際にデプロイする

Surgeではデプロイの度に適当なドメインを割り振られるので継続的に使っていくのであれば CNAMEで最初に割り振られたドメインを保管しておくとよいでしょう。

また実際のデプロイではデプロイさせるディレクトリを聞かれるので dist ディレクトリを指定します。割り振られたドメインを本記事では https://scripts.hogehoge.com/ とします。

最後に https://scripts.hogehoge.com/assets/profile.js にてJavascriptファイル・単体として存在しているか確認、こちらもしておきます。

3. スクリプトタグを読み込む

React + Vite

https://ja.vitejs.dev/guide/#最初の-vite-プロジェクトを生成する
※ こちらのプロジェクト作成もまた割愛させていただきます

こちらの素敵な記事を参考させていただきます

https://zenn.dev/kenta0313/articles/b81eefc1f0de62

こちらの埋め込みコードをReactでも埋め込んでいきます。

<div id="app"></div>
<script type="module" src="https://scripts.hogehoge.com/assets/profile.js"></script>

App.tsx

useEffect(() => {
    // divタグ
    const embedDiv = document.createElement('div') as HTMLDivElement;
    embedDiv.id = 'app';
    
    // scriptタグ
    const embedScript = document.createElement('script') as HTMLScriptElement;
    embedScript.type = 'module';
    embedScript.src = 'https://scripts.hogehoge.com/assets/profile.js';
 
    document.getElementsByTagName('body')[0].appendChild(embedDiv);
    document.getElementsByTagName('body')[0].appendChild(embedScript);
}, []);

ローカルで確認

$ npm run dev
  • localhost:3000 で Reactプロジェクトでも下記表示できたら成功です。

まとめ

Reactでも作成したスクリプトタグを動かしていけるか検証していきました。ReactHookライフサイクルでDOM操作によってできたので、Angularでも同じように ngAfterViewInit にて実装を行えばいけるでしょう。(多分、知らんけど)

最後に上記のように一つのjsスクリプトだけでページ全体で読み込むことしか今回は検証しておりません。Svelte自体コンポーネントとして身立ててjsを作れるので、実際のアプリケーションで複数のjsスクリプトを読み込みたいという要望・需要などが出てくるでしょう。そのような需要が出てきたときに useRef で解決できるのかまだ不透明なので、引き続き調査が必要だなと感じました。

Discussion

ログインするとコメントできます