FANZAFANS FANZAをもっと便利に使うサービス
技術ブログ

エロサイトで学ぶsvelte.js その2 - Rollup.jsの使い方

 2022/05/15 23:03:18

前回のおさらい

本サイトのメインサービスであるえっちなのを探す機能に使われている技術を紹介していくコーナーです。
今回のテーマはSvelteです。
前回の記事では、Svelteとはどんなものか、Node.jsのインストール、このサイトはエロサイトであることをお伝えしました。
この記事から読んでる方ご注意下さい。このサイトはエロサイトなので、上司や家族といった人の目があるところで読むと万が一の悲惨な事故に繋がりかねません。それもプレイと楽しめる性癖の方は除き、安全の確保できるセーフティエリアで読んで頂ければと思います。
(この記事自体は真面目な内容です。)

Rollup.jsを使う

前回の記事で説明した通り、Svelteにはコンパイルが必要です。このコンパイルのためにはバンドラーが必要です。
そのバンドラーに相当するものがRollup.jsです。
Rollup.jsを動かすためにはNode.jsをインストールする必要があり、それは前回の記事までで終わりました。ここからはRollup.jsを実際に使って行きます。

ところで、Svelteを単にローカルで試してみたい、というだけであればRollup.jsの詳細を覚える必要すらありません。
というのも、Svelteのプロジェクトテンプレートみたいなものがあり、このテンプレートをコピーしてきて使うだけで特に何もせずともSvelteを動かせるようなものがあるからです。
その手順についてはSvelte for new developersのページに書いてあります(英語)。
ただ試すだけならこれでおしまいにするというのも手なのですが、しかし実際に自分のウェブサイトを作っていく過程ではこのプロジェクトテンプレートを利用するだけではまるで不十分で、その中身を理解していないと意味がありません。
これはあくまでお試し、と思ったほうが良いと思います。

本サイトでは、Rollup.jsを一から記述、理解し実際のウェブ開発でも使えるようにしていきたいと思ます。

Rollup.jsのインストール

Rollup.jsのインストールは、Node.jsのようにインストーラ(やNVM)からインストールするわけではありません。
Node.jsにはnpmというコマンドがあり、このコマンドを使うだけで必要なものがみんなインストールすることができてしまいます。

ちなみに前回の記事で解説したnvmとコマンドが似ており、大変紛らわしいですがnvmnpmは全く別物です。
名前、もうちょっと何とかならなかったんですかね……
nvmはNode.jsを複数バージョン入れて使い分けるためのコマンドでした。これから使って行くnpmは、Node.jsの初期化したり、何か(Rollup.jsのようなものとか)をインストールしたりといったことをするためのコマンドです。
これから先はnpmコマンドしか使わないので、ひとまずnvmについては忘れてしまいましょう。

Node.jsが正しくインストールされていれば、npmコマンドが使えるようになっています。コマンドプロンプトでSvelteのプロジェクトを作成したいディレクトリに異動し、そこで以下のコマンドを入力します。

npm init -y
このコマンドを入力するとカレントディレクトリにpackage.jsonというファイルが生成されているはずです。
このpackage.jsonの中にはプロジェクトの情報的なものが格納されます。
初期化時に -yというオプションを指定しましたが、これを指定しないで
npm init
でも初期化可能です。そうするとpackage.jsonの中に記述されている、名前だとか概要だとかを入力するように求められます。
そういうのめんどくさいからとりあえずぜんぶデフォでいいわっていうのが -yオプションです。後で好きなように自分で編集するしっていう感じ。

npm initで初期化したプロジェクトがいらなくなったら、単にそのディレクトリを削除するだけでOKです。こんな感じで気軽にポンポン初期化して別々のものをつくれます。

とりあえずこれで、初期化は終わってますので次は肝心のRollup.jsをインストールしていきます。

npm install -D rollup
とすれば、インストール完了です。簡単。
このnpmによるインストールはこの初期化したディレクトリにされますので、基本的に他には影響を与えません。
カレントディレクトリにnode_modulesみたいなフォルダやpackage-lock.jsonみたいなファイルが新たにできていると思います。こういうところに入っていますのでこれらを削除しないようにしましょう。(もちろん、そのプロジェクトがいらなくなったら丸ごと削除してOKです)
もし毎回、初期化毎にRollupをインストールするのが嫌な場合は-gオプションをつけてグローバルにインストールすることもできます、が、基本的にはしないほうが良いと思います。
グローバルにインストールすると全体で使えるメリットはありますが、プロジェクト毎にバージョンを変えたりとかできなくなってしまいますので、基本的には使わない方向のほうが良いと思います。
また、上のインストールコマンドには-Dオプションをつけていますが、これは今回に限ってはつけてもつけなくてもどっちでもいいです。
ただ、開発時にしか利用しないようなもの(Svelteをコンパイルするのは開発時だけで、デプロイはコンパイル後のものだけ使います)は-Dオプションをつけましょうというのが基本的な使い方なので、それに倣っています。

最小の構成でRollup.jsを実行してみよう

まず最初に、Rollup.jsを使う時の最小の流れを見ていきましょう

  1. ソースとなるJavaScriptで書かれた(複数の)ファイルを用意する
  2. rollup.config.jsというファイルを作成する
  3. rollup.config.jsというファイルの中身を記述する
  4. rollupのコマンドで実行する
  5. 出力ファイル(JavaScriptファイル)が得られる
という形になります。
Rollup.jsはバンドラーですので、本来の用途としては複数のJavaScriptを1つにバンドルすることです。
もっとも原始的なJavaScriptだと複数のファイルがある場合、HTMLのscriptタグを順番に並べてかいて、先に書いたJavaScriptの関数とかを暗黙的に使えるみたいなかなりセンスのない書き方をしなければなりませんが、今はJavaScriptもimport文などがサポートされ、複数ファイルがあってもそれを他のプログラミング言語と同じようにモダンな方法で使うことができます。
このような時、Rollup.jsやwebpackのようなバンドラーを通せば、1つのJavaScriptとしてバンドルすることができるので、扱いも楽になります。
バンドラーにはそれ以外にも色々オプションがあり、よく使われているのはバベルのようなトランスパイラ(最新のJavaScript構文を、古いブラウザでも動くように古い書き方に変換する)などがあります。
とはいえ、Svelteを採用するような人が、太古の遺物であるインターネットエクスプローラなどをサポートすることはないでしょうから、今回は使いません。
が、Svelteも同様にバンドラーにプラグインという形で提供されていて、基本的にはバベルなどのトランスパイラと考え方は同じです。

ひとまず、Svelteのコンパイルに行く前に、まずJavaScriptをバンドルするだけのもっとも単純なRollupの使い方を見ていきます。

なにはともあれ、JavaScriptのファイルをお試しで2つ用意します。

girl.js
import { func } from "./boy.js";

func();
boy.js
export function func()
{
    console.log("おぎゃあ");
}

見れば一目瞭然の簡単な中身です。girl.jsでboy.jsをimportしてその中にある関数のfuncを呼び出しているだけです。
この2つのファイルをバンドラーたるRollup.jsで1つにバンドルしてみます。

rollup.config.jsという名前でファイルを作成し、そこに以下のように記述します。

rollup.config.js
export default {
    input: "girl.js",
    output: {
        file: "dst/child.js"
    }
}
これがほぼ最小のrollup.config.jsです。
inputとoutputがあるだけの極めて単純な構造なので解説の必要はほとんど無いと思いますが念のため言っておくと、出力先は必ずしもdst/child.jsみたいにdstにする必要はなく単にカレントに出力したいならchild.jsでもいいし、フォルダ名やファイル名も自由に変えてresult/myson.jsでもかまいません。

あとは、rollupを実行するだけです。以下のコマンドを入力します。

npx rollup -c
npxというのは、Node.jsでインストールしたコマンドを実行するものです。今回はRollup.jsをインストールしたためrollupというコマンドが使えるようになっています。
なのでnpx rollupとすることで、rollupコマンドを利用しています。
-cは--configの略で、設定ファイルを使うよ、という意味です。この-cが指定されている時に、特に何もファイル名が指定されていなければrollup.config.jsを読みに行きます。
特段の理由が無い限りはデフォルト通りの名前にしておくとよいと思います。(rollupの設定ファイルと一目でわかる)

それで上記のコマンドを実行してみるとdstフォルダ以下にchild.jsが作られています。
以下のような中身になっています。

function func()
{
    console.log("おぎゃあ");
}
    
func();
ついにgirl.jsとboy.jsが一つになれました。その結果2つが1つになりchild.jsが誕生しました。
これがバンドラーです。美しいですね。
それでは最後におまけで、Node.jsを使ってこのファイルを実行してみましょう。
node dst/child.js
おぎゃあ
と表示されれば成功です。

これで、複数のJavaScriptをバンドルして1つのファイルにする、ということはできるようになりました。
あとはもう少しできることについて知っておく必要があります。

iifeで出力する

iifeとは即時実行関数型というやつでJavaScriptのテクニックの一つです。
先の例では、出力されたchild.jsにはfuncという関数がむき出しになっていますよね。ということは他のJavaScriptファイルと一緒に利用すると、名前が衝突する可能性があります。
狙って外出ししてるのであればいいのですが、通常は自分の管理できる範囲のコードはRollup.jsでバンドルするので、中だけで使えればいいわけです。中。
そう言った時に、名前空間替わりに使うようなテクニックがiifeで、Rollupでは先ほどの設定ファイルに少しオプションを追加してやるだけでiifeで出力することができます。

export default {
    input: "girl.js",
    output: {
        file: "dst/child.js",
        format: "iife"
    }
}
format: "iife"の部分が追加されたものです。このように書き換えてからもう一度、npx rollup -cを実行してdst/child.jsを出力してみると

(function () {
    'use strict';

    function func()
    {
        console.log("おぎゃあ");
    }

    func();

})();
このように即時実行される関数の中に入るようになり、外から参照できないようになります。これによって名前衝突することがなくなります。
基本的にウェブ制作では多くの状況でiifeで出力することになると思います。
このほか、もっと出力できるフォーマットは色々あるのですが(amd, cjs, esm, umd, system)おそらくsvelteと共にウェブ制作をする場ではほとんどiifeとして出力することになるでしょう。

iifeの中にアクセスする

iifeにすると外からアクセスすることができなくなり、名前衝突しなくなるということは前項で述べました。
とはいえ、その隠された中に、アクセスしたくなっちゃうことってあると思います。
そういう時にじゃあどうすればいいの?って、iifeをやめてしまうと全てを丸出しにすることになります。いつでも丸出しというのはいただけません。
いつでも丸出しのものに魅力を感じますか?感じませんよね。
やはり隠されたその中にアクセスするから良いのです。

というわけでコードを書き換えてみます。
まずgirl.jsを以下のように書き換えます。

import { func } from "./boy.js";

func();
    
export function cry()
{
    func();
    func();
}

export function cry()関数を追加しました。
外部に見せるためには、これを外に見せたいよという印を付ける必要があります。それがexportです。
外から触れるのは、このexportがついているものだけです。

次にrollup.config.jsを変更します。

export default {
    input: "girl.js",
    output: {
        file: "dst/child.js",
        format: "iife",
        name: "myson"
    }
}

outputの中に、name: "myson"というものが追加されました。
この状態でRollupを動かしてバンドルしてみましょう。npx rollup -cでした。
そうすると、child.jsの中身は

var myson = (function (exports) {
    'use strict';

    function func()
    {
        console.log("おぎゃあ");
    }

    func();

    function cry()
    {
        func();
        func();
    }

    exports.cry = cry;

    Object.defineProperty(exports, '__esModule', { value: true });

    return exports;

})({});

このようになりました。
見ればわかる通り、exportsというオブジェクトにcryをセットして、それを返すような形に書き換わっています。
そして、その戻り値は、先頭行のvar myson = ...のところでrollup.config.jsに指定したname: "myson"と同じ名前の変数に格納されるようになっています。
つまり、exportしたcryという関数を外部から呼び出すためには
myson.cry();
とすればいいわけですね。
蛇足なのでやりませんが、呼び出してみれば、おぎゃあおぎゃあと言うはずです。

ところで、このRollup.jsによって出力されるJavaScriptって随分と人間に読みやすい出力だと思いませんか?
そうなるよね、っていう当たり前の出力をしてくれます。これは地味に良い点で、他のバンドラーだとなにこれ宇宙語?みたいな出力がされることもしばしばあります。

複数のインプット

最小の例では、girl.jsをinputとしてバンドラを動かしました。
全てをたった1つにバンドルするのならそれでいいですが、実際にウェブ開発していくなかでも人生でも、そんなことは稀ですよね。
各ページごとに必要なJavaScriptのコードは異なり、それぞれ異なったinputを指定して、別々の出力を得たい。
そんな当たり前のこと、もちろんできます。単に配列にすればいいだけです。

export default [
//girl---------
{
    input: "girl.js",
    output: {
        file: "dst/child.js",
        format: "iife",
        name: "myson"
    }
},
//doxy---------
{
    input: "doxy.js",
    output: {
        file: "dst/doxychild.js",
        format: "iife",
        name: "doxyson"
    }
}
]

単に配列になっているだけで、その中身はこれまで解説してきたものですので特にこれ以上の説明は必要ないでしょう。

変更のウォッチをする

これはSvelteをやっていく上で必須の機能というわけではないのですが、便利なので知っておきましょう。
今までは、JavaScriptのファイルを編集してnpx rollup -cとコマンドをうちバンドルしていました。
しかし、いちいち変更毎にnpx rollup -cと打つのはめんどくさい。というときのためにウォッチ機能があります。
npx rollup -cのかわりに
npx rollup -c -w

このように-w(または--watch)オプションをつけるとウォッチモードに突入します。この状態でJavaScriptファイルを変更すると、自動的にバンドルが走るようになります。
いちいち毎回npx rollup -cと打たなくていいので便利になります。

また、rollup.config.jsの中で

process.env.ROLLUP_WATCH

を見ることで、watch中かどうかを知ることができます。知ってどうすんだよって感じですが、次回、Svelteのコンパイルでは、この特性を用いてリリース版、デバッグ版みたいにビルドを分けてみたいと思います。

今回までで、Node.jsのインストールから始まり、Rollup.jsの基本的な使い方、書き方についてマスターしました。
次回はいよいよSvelteをコンパイルして、実際にサイトを作成してみましょう。