トランスパイラとモジュールバンドラ
複雑化する Web 開発
JavaScript は、当初は Web サイトに簡易的な動きを追加させるための言語として設計されました。しかしながら、高度な Web アプリケーションの台頭や、Node.js をはじめとしたブラウザにおける JavaScript のユースケースの広がりにより、標準的な JavaScript のみでの開発には限界があることがわかってきました。
このため、現代では、JavaScript は事前に何らかの変換を行っておくことが一般的になっています。
トランスパイラ
トランスパイラは、ソースコードを別のソースコードに変換するためのプログラムです。JavaScript においてトランスパイラが必要になるのは、主に 2 つの理由によります。
ひとつは、最新の機能を使用するためです。JavaScript の言語仕様は、Ecma International の TC39 によって作成されていますが、新しく策定された仕様は、まだブラウザなどによって実装されていない場合があります。Babel は、そういった最新の言語仕様に沿って書かれたプログラムを変換し、古い仕様の範囲内で解釈できるプログラムに変換するための、最も有名なトランスパイラです。
もうひとつは、別の言語で書かれたプログラムを JavaScript に変換するためです。次の章で扱う TypeScript は、トランスパイラを用いて JavaScript に変換されます。
モジュールバンドラ
通常、規模の大きなプログラムは、見通しが良くなるよう複数のファイルに分割されます。HTML から複数の JavaScript を読み込むためには script
タグを並べれば良いですが、HTTP サーバーの節で学んだように、script
タグの数だけ HTTP リクエストが発行されてしまうため非効率的です。
webpack のようなモジュールバンドラを用いることで、複数の JavaScript ファイルを統合できます。
なお、Node.js の場合は、モジュールの読み込みはファイルの読み込みに過ぎず、ネットワークを経由することはないため、このプロセスは通常必要ありません。
Vite を用いたフロントエンド開発
Web 開発の領域では、ブラウザ (クライアント) で動く JavaScript プログラムをフロントエンド、サーバーで動くプログラムをバックエンドと呼ぶことがあります。
Vite は、主にフロントエンドの領域における、トランスパイラやモジュールバンドラなどの機能を持つソフトウェアです。
Vite を用いて新しくプロジェクトを作成してみましょう。
詳細な手順は次のとおりです。
まずは、ターミナルでカレントディレクトリをプロジェクトフォルダを格納するディレクトリに移動し、
npm create vite@latest
を実行します。Select a framework
と尋ねられるので、Vanilla
を選択してください。その後、Select a variant
と尋ねられるので、JavaScript
を選択してください。
すると、package.json
を含む新しいディレクトリがカレントディレクトリに作成されます。このディレクトリを VS Code で開きましょう。
続いて、作成された package.json
をもとに npm から必要なパッケージをダウンロードするため、
npm install
を実行します。完了したら、
npm run dev
を実行してください。
Vite 内蔵のウェブサーバーが起動し、http://localhost:5173/
でウェブサイトが表示されます。
Vite の仕組み
Vite の挙動を理解するため、Ctrl + C
で先ほど起動させたウェブサーバーを停止させ、npm run build
コマンドを実行してみましょう。
$ npm run build
> vite@0.0.0 build
> vite build
vite v4.3.5 building for production...
✓ 7 modules transformed.
dist/index.html 0.45 kB │ gzip: 0.30 kB
dist/assets/javascript-8dac5379.svg 1.00 kB │ gzip: 0.60 kB
dist/assets/index-48a8825f.css 1.24 kB │ gzip: 0.65 kB
dist/assets/index-44b5bae5.js 1.45 kB │ gzip: 0.75 kB
✓ built in 64ms
これにより、カレントディレクトリに dist
ディレクトリが作成され、トランスパイルとバンドルの結果が格納されます。
出力されたファイルを元のファイルと比較してみましょう。元の index.html
や main.js
が、変換された状態で出力されていることがわかります。ディレクトリごと Netlify Drop などにアップロードすれば使用可能になるでしょう。
npm run
コマンドnpm run
コマンドは、package.json
の scripts
プロパティに記載されたコマンドを実行します。開発によく使うコマンドを登録しておくことで、コマンドを打つ手間を削減できます。
npm create vite@latest
が自動的に生成する package.json
の scripts
プロパティは、次のようになっていました。ここに記載されたコマンドでは、npx
コマンドを用いたときのように、npm でインストールされたパッケージをそのまま実行できます。例えば、npm run dev
コマンドを実行することで、npx vite
に相当する処理が行われます。
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
}
ECMAScript モジュール
Node.js では、通常 require
関数と exports
オブジェクトを使用してモジュールを作成していました。しかしながら、この機能は Node.js に特有の機能で、標準的な JavaScript の仕様には含まれていません。
JavaScript 標準のモジュールシステムを、ECMAScript モジュールと呼ぶ場合があります。トランスパイラを用いることで、ECMAScript モジュールを用いてプログラムを記述できます。
ECMAScript モジュールでは、export
文や import
文を用いて他のモジュールとのやりとりを行います。
import { add } from "./sub";
document.getElementById("app").textContent = add(3, 4);
export function add(a, b) {
return a + b;
}
デフォルトエクスポートは、各モジュールにつき一度だけ使えるエクスポート方法です。
import add from "./sub";
document.getElementById("app").textContent = add(3, 4);
export default function add(a, b) {
return a + b;
}
ECMAScript モジュールは、実際にはブラウザや Node.js でも利用可能です。ブラウザであれば script
要素の type
属性に module
を指定すれば良いですし、Node.js であれば --esm
オプションや、拡張子の .mjs
への変更などによって対応できます。
しかしながら、ブラウザでこういった機能を利用することは、HTTP リクエストの増加を招きますし、Node.js の ECMAScript モジュールサポートは、2022 年現在、周辺エコシステムとの関係上、難しい場合が多いです。
なお、exports
オブジェクトや require
関数を使ったモジュールシステムを、CommonJS モジュールと呼ぶ場合があります。
npm のパッケージを Web ブラウザ上で利用する
npm のパッケージがブラウザ上での実行に対応している場合は、Vite をはじめとしたトランスパイラやモジュールバンドラにより、ブラウザ向けの JavaScript に変換させられます。例として date-fns
パッケージを使用してみましょう。
import { format } from "date-fns";
document.getElementById("app").textContent = format(
new Date("2022-01-10"),
"yyyy年MM月dd日"
);
フロントエンドとバックエンドの統合
Vite などのツールによって出力されたブラウザ上で動くアプリケーションと、Node.js をはじめとしたサーバー向けのアプリケーションを統合するためには、複数の手法が考えられます。
最も単純なアプローチは、ビルド時に統合することです。この方法のメリットは、本番環境にデプロイするのが簡単であることです。ディレクトリ構成は、例えば次のようになります。
app
├── client
│ ├── index.html
│ └── main.js
├── package.json
├── package-lock.json
└── server
└── main.js
npm run build
コマンドによって Vite がビルド結果を /dist
に出力するようにしておきます。
{
"scripts": {
"start": "node server/main.js",
"build": "vite build client --outDir ../dist"
}
}
express.static
により Vite が作成したディレクトリを指定すれば完成です。
const express = require("express");
const app = express();
app.use(express.json());
// Vite によって出力されたディレクトリを配信する
app.use(express.static("dist"));
app.listen(3000);
課題
chart.js
を用いると、ブラウザ上に非常に美しいグラフを描画することができます。このパッケージを用いて、適当なデータをビジュアライズしてみましょう。Vite を用いて作成した Web フロントエンドと、Node.js のバックエンドが協調して動作するアプリケーションを Render にデプロイしてみましょう。