【Svelte Framework入門】Svelteアプリのビルド出力をindex.htmlのみにするViteプラグインを導入してみる


2023/01/07
【Svelte Framework入門】Svelteアプリ開発でrollup.jsからViteに移行する
蛸壺の技術ブログ|Svelteアプリのビルド出力をindex.htmlのみにするViteプラグインを導入してみる

前回では、軽量なJSフレームワーク・
『Svelte』を、高機能フロントエンド開発ツール・『Vite』にお引越しさせる話を紹介していきました。

合同会社タコスキングダム|蛸壺の技術ブログ
【Svelte Framework入門】Svelteアプリ開発でrollup.jsからViteに移行する

Svelteアプリ開発環境で、デフォルトのrollupからViteへ移行する手順を解説します。

参考サイト|Vite - Next Generation Frontend Tooling

このViteの良いところは、爆速の次世代バンドラ・
esbuildによるプリバンドルだけではなく、有志の方々が提供しているプラグインも豊富にあることです。サードパーティ製のViteプラグインは以下のサイトでまとめられていますので、面白いプラグインを宝探し感覚で眺められても良いと思います。

参考サイト|awesome-vite - A curated list of awesome things related to Vite.js

これによって、面倒な実装を自前でやらなくても、ほとんどの場合、誰かが提供しているプラグインを利用させてもらうだけでサッと欲しい機能が追加することができます。

今回のお題は、「ビルド後の出力ファイルを可能な限り減らす」ことに着目して、究極的な話、
index.htmlだけにまとめて全てのリソースを埋め込むための手順を紹介します。


合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】Javascript&Typescriptプログラミング入門のためのオススメ書籍&教材特集

vite-plugin-singlefileプラグインでリソースを一つにまとめる

通常、ViteでSvelteのプロジェクトをビルドしてみると、デフォルトではdistフォルダの中にビルド済みのリソースが固められて出力されています。

            
            $ tree dist/
dist/
├── assets
│   ├── ...
│   └── hoge.jpg
├── lib
│   ├── ...
│   └── piyo.js
├── ...
├── favicon.png
└── index.html
        

これはSvelte標準のrollupよりはまだスッキリとはしているものの、特に静的なアセットファイルは分離されています。

もちろん、リモートのサーバーから必要になったときだけアセットファイルを読み込む方式は、クライアント側の処理のオーバーヘッド時間を短縮させ、遅延読み込みなどにもメリットが大きいのは確かです。

しかし、例えば下のリンク記事で紹介したようにローカルで使用するバイナリSPAだと、最初に一気にリソースを全部プリロードしておいたほうがパフォーマンスは向上すると考えられます。

合同会社タコスキングダム|蛸壺の技術ブログ
【Svelte Framework入門】Svelteアプリのビルド出力をindex.htmlのみにするViteプラグインを導入してみる

Svelteでビルド後の出力ファイルをindex.htmlへ全て埋め込んで一つにまとめるViteプラグインを紹介

つまりは、適宜プログラムに合わせた読み込み方式の使い分けが重要ということになります。

全てのリソースをビルド時にインライン化(コード埋め込み)してくれるViteのプラグインに
「vite-plugin-singlefile」があります。

参考|vite-plugin-singlefile

プラグインの使い方はいつものように、まずインストールします。

            
            $ yarn add vite-plugin-singlefile -D
        
インストールしたら、プロジェクトのvite.config.tsにプラグインを追加します。

            
            import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';

//...中略

//👇追加
import { viteSingleFile } from 'vite-plugin-singlefile';

//...中略

export default defineConfig({
    plugins: [
        svelte(),
        //👇追加
        viteSingleFile(),
        //...以下略
        
これでViteビルドすると、可能な限りindex.htmlに静的なリソースを埋め込んでくれるようになります。


合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】Javascript&Typescriptプログラミング入門のためのオススメ書籍&教材特集

SVGをインライン化する「Vite SVG loader」を使う

先程の「vite-plugin-singlefile」はcssファイルや一部の画像バイナリファイルをインライン化してくれはしましたが、SVG画像などの通常ではインライン化してくれないリソースファイルには、それぞれが対応したローダープラグインを使って、htmlに埋め込めるかどうか検討しないといけません。

SVG画像は
「vite-svg-loader」を使って、プリビルドロードしたものをURLデコードするというちょっと面倒な方式を採る必要があります。

参考|vite-svg-loader

「vite-svg-loader」は元々Vue系のプラグインですが、Rawで呼び出すことで通常のローダーとしてSvelteでも利用することが可能です。

こちらもまずまずプラグインをインストールします。

            
            $ yarn add vite-svg-loader -D
        
インストールしたら、プロジェクトのvite.config.tsにプラグインを追加します。

            
            import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';

//...中略

//👇追加
import svgLoader from 'vite-svg-loader';

//...中略

export default defineConfig({
    plugins: [
        svelte(),
        viteSingleFile(),
        //👇追加
        svgLoader({
            defaultImport: 'raw'
        })
        //...以下略
        
ポイントとしてはVue以外のフレームワークでは、デフォルトでrawモードでローダーを呼び出すことにします。(※ローダーの細かい制御は本家のドキュメントをお読みください。)

ローダーは単にローダーであって、このままだと生のSVGをビルド時に読み込んでくれるだけです。

SVGをindex.htmlにインライン化するには、
「URLエンコード」をする仕組みを別に用意する必要があります。

URLエンコード自体は難しいことはないので、別のnpmパッケージのライブラリユーティリティを使っても良いですし、画像のエラーチェックなどなしに手前味噌でよいならば、以下のように、SVG画像をコンポーネントファイルで呼び出して利用します。

            
            <script lang="ts">
    //👇SVG画像の生ロード
    import hoge from '../../assets/hoge.svg';
    //👇(若干やっつけ仕事な)URLエンコード
    const enc = tacoPlayer
                       .replace(/\r?\n|<!--.*-->/g, '')
                       .match(/<svg.+<\/svg>/)[0]
                       .replace(/"/g, "'").
                       replace(/</g, '%3C')
                       .replace(/>/g, '%3E')
                       .replace(/#/g, '%23');
</script>

<object title="hoge" data="data:image/svg+xml,{enc}" type="image/svg+xml"></object>

<style lang="scss">
object {
    display: block;
    width: 32px;
    height: 32px;
    position: absolute;
}
</style>
        
という感じに呼び出すことが出来ます。

こうすることで、Viteのビルド後に、svg画像も
index.html内に埋め込むことが可能です。


合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】Javascript&Typescriptプログラミング入門のためのオススメ書籍&教材特集

まとめ

今回はSvelte&Viteの開発時に知っておきたい、ビルド生成物の一本化・静的なアセットファイルのインライン化をまとめて紹介しました。

あくまでもインライン化するかしないかは、開発者の考え方によりますが、使い分けの方法を覚えておかれると後々便利に使えるかも知れません。
記事を書いた人

記事の担当:taconocat

ナンデモ系エンジニア

主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。

合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】Javascript&Typescriptプログラミング入門のためのオススメ書籍&教材特集