既存のサイトにSvelteを導入する

仕事で既存のサイトを改修することになりました。 WordPress で動いているのですが、どうやら jQuery がバリバリ使われているようです。この記事をお読みのあなたなら、どうするでしょうか。

機能を追加、修正するのに、いまさら jQuery を書くのはメンテナンス上問題も出てくると思うし、なにより気が進みません。そこで Svelte を使うことにしました。

この記事では既存のサイトに Svelte プロジェクトを組み込む方法を説明します。 私が触ることになったのはWordPress ですが、当然、他にも応用できます。 Svelte の文法などにはあまり触れないつもりです。公式のチュートリアルで勉強してみてください。

この記事の結論

結論をいいますと、

  1. App.svelte などにアプリを記述
  2. Svelte アプリをマウントしたい場所にマウントポイントを作る( <div id="svelte-app" /> など)
  3. src/main.js で target をマウントポイントに指定する( document.getElementById("svelte-app") など)
  4. Svelte のバンドルファイルをページから読み込む

Svelte のメリット

Svelte とは、 React や Vue といった JavaScript フレームワーク、のようなものです。正確には Svelte はコンパイラなのですが、使用する分には Vue と似たコーディング体験ができます。開発元が New York Times だというのも、なんだか熱いですね。

この「 Svelte はコンパイラである」という点がメリットにつながります。 React や Vue はフレームワークなのでビルドした生成ファイルにフレームワーク自体も入っています。一方 Svelte はプレーンな JavaScript に変換されるため React, Vue に比べてバンドルサイズが小さくなるようです。

既存のサイトに手を加える際に、このバンドルサイズが小さいというのは大きなメリットだと思います。「ハンバーガーメニューを追加したい」といった規模の小さい開発だとフレームワークのファイル容量がなくなるのはメリットだと思います。またハンバーガーメニューに加えて「 FAB をつけたい」という注文があればどうでしょうか。

サイトを丸ごと、あるいはページを丸ごと作り直せるならReactやVueもいいかもしれません。しかし、あくまで既にあるものに埋め込むとなると。別々に React アプリケーションを作ることになるので、 React フレームワークの部分は重複することになりますよね。これに比べて Svelte を導入することでファイルサイズが小さくなり読み込みが早くなるだろうと判断し、採用に至りました。

Svelteの構成を探る

実際にどうやってサイト内に導入していくのでしょうか。それを探るためにまず Svelte の構成を見てみます。お好きなディレクトリで Svelte 環境を整えましょう。今回は JavaScript ですが、実際の開発だと TypeScript が便利なのでオプションをつけてもいいですね。

npx degit sveltejs/template my-svelte-project

my-svelte-project というディレクトリに Svelte アプリが作られました。アプリの中身は JavaScript で src/App.svelte に書いていくのですが、どうやってブラウザ上で実行されるのかを探っていきましょう。同じディレクトリのファイル src/main.js の中身を見てみると、

import App from './App.svelte';

const app = new App({
 target: document.body, // ここ
 props: {
  name: 'world'
 }
});

export default app;

App.svelte からインポートした App を document.body にマウントしているようです。Svelteアプリをコンパイルしたjsファイルを読みこんだページの body 要素にマウントしてDOMが描写されます。

では、そのページはどこにあるのでしょう。 public/index.html というファイルを見てみましょう。まずこのファイルがクライアントサイドにロードされ、 SPA がロードされます。 Svelte のみで開発していると気にする必要がありませんが、今回は他サイトに埋め込むのでこの html ファイルを詳しく見てみます。

<!DOCTYPE html>
<html lang="en">
<head>
 ...
 <link rel='stylesheet' href='/global.css'>
 <link rel='stylesheet' href='/build/bundle.css'>
 
 <!-- ここで読み込み -->
 <script defer src='/build/bundle.js'></script>
</head>

<body> <!-- ここが target -->
</body>
</html>

/build/bundle.js という js ファイルを読み込んでいますね。これが Svelte アプリをコンパイルしたファイルです。アプリをコンパイルしたものをどこに置くのかというのは rollup.config.js で指定されています。

...
export default {
 input: 'src/main.js',
 output: {
  sourcemap: true,
  format: 'iife',
  name: 'app',
  file: 'public/build/bundle.js' // ここ
 },
...

この設定ファイルでは src/main.js をコンパイルして public/build/bundle.js にすると定義されています。このアウトプットのパスとindex.htmlで読み込むパスが一致していないといけませんね。

ここまでをまとめると、

  • アプリは App.svelte など .svelte ファイルに記述する。
  • アプリをマウントするポイントを src/main.js で document.body と定義している。
  • ページ側では /build/bundle.js というjsファイルを読み込んでいる。
  • rollup.config.js でアプリをコンパイルしたファイルは public/build/bundle.js におくと定義している。

このようになっていることがわかりますね。

既存のサイトに埋め込むには

実際に Svelte を既存のサイトに埋め込むにはどうすればいいでしょうか。ざっくりまとめると、

  1. App.svelte などにアプリを記述
  2. Svelte アプリをマウントしたい場所にマウントポイントを作る( <div id="svelte-app" /> など)
  3. src/main.js で target をマウントポイントに指定する( document.getElementById("svelte-app") など)
  4. Svelte アプリをコンパイルした js ファイルをページから読み込む

4 については、たとえばWordPressの場合 function.php で js ファイルを読み込む設定をします。 theme 以下で svelte アプリを作り、そのバンドルファイルのパスを指定します。WordPressの例は後日アップしようかと思っています。