ビルド環境で使える、Vue 3の機能 第1回 Vue 3と始めるビルドシステム
ビルドシステムを前提とした、Vue 3の機能を解説します。まずはなぜビルドシステムが必要か、Viteが提供するビルド環境を利用しながら理解していきましょう。
はじめに
シリーズ「Vue 3から始める、Vue.js」では、全20回にわたり、Vueを用いたアプリケーション制作で必要となるVueの特性と機能、それらを前提としたコード設計について解説しました。このシリーズは、フロントエンド開発の入門者向けでもあったため、CDNのVueを<script>
タグで読み込むという、「小さく手軽に」はじめられるVueのメリットを活かした手法を採用しました。
一方で、Vueは「プログレッシブフレームワーク」というコンセプトを持っており、Vue.jsのコア機能に対して、サポートライブラリやツールを重ねることで、より高度な機能や開発体験を実現できます。次の図が示すように、「Build System(ビルドシステム)」を利用した開発も可能です。
Vueにはこのビルドシステムを前提とした機能があり、同シリーズの最終回で触れた、次の機能もこれに該当します。
- Viteを利用したビルドツールチェーン
<script setup>
構文の追加- Volar(ボラー)によるTypeScriptIDEサポートの改善
そこで本シリーズでは、近年のフロントエンド開発の現場では当たり前のように利用されているビルドシステムの導入の手引も兼ね、上記リストを網羅したビルド環境で使えるVue 3の機能について解説していきます。
まずは、なぜビルドシステムが必要なのかを考えてみましょう。
なお、本記事の解説に使用したサンプルプログラムを、次のリポジトリで公開しているので、併せて参考にしてください。
ビルド環境で使える、Vue 3の機能
ビルドシステムとは
フロントエンド開発におけるビルドとは、自身で実装したコードやライブラリ、画像のようなアセットファイルをはじめとしたソースをもとに、トランスパイル(コードの変換)、ミニファイ(コードの縮小化)、バンドル(コードの集約)といった処置を経て、実行環境に適した実行用のファイルを生成することを指します。
この処理は、Node.js環境下で利用可能な「パッケージ」という単位で配布されるプログラムを組み合わせ、「ビルド」という1つのタスクとして実行できるようにするのが一般的です。
パッケージはnpmjs.comで公開されており、ビルドの一連の処置に利用できる便利な汎用処理、あるいは、Vueのようなフレームワーク自体も含めさまざまなものが存在します。
パッケージの利用は、自身で実装する必要がなく便利ですが、その選択や管理上の難しさもあります。多数のパッケージが存在するということは、そこから必要なものを選定し、その使い方を理解する必要があるからです。
また、導入したパッケージの数が多ければ多いほど、その分、プロジェクトのパッケージに対する依存が増えることを意味します。さらに、利用するパッケージ間にも依存関係が生じることもあり、プロジェクトの長期運用を要するケースでは、パッケージ間のバージョンの整合性をとることに苦心しながら、バージョンアップに追随しなければならないこともしばし起こります。
ブラウザという実行環境で、そのまま動作させることができるJavaScriptというスクリプト言語の利用にあたって、その特性を活かさず、このような手間を踏んでまでビルドシステムを採用するメリットとは何なのでしょうか?
ビルドにより得られるメリット
ビルドシステムのメリットと一口に言っても、その内容は構成によりさまざまです。しかし、Vueアプリケーションに用いられる一般的なビルドシステムでは、次のようなメリットが得られると考えられるでしょう。
モジュール取得のパフォーマンス問題の回避
Vueをはじめとした同類のUIフレームワークには、コンポーネントと呼ばれるモジュール単位にUIの実装を分割する機能があります。このモジュールは、保守性の観点からもモジュールごとにファイルを分けて管理することが重要です。
JavaScriptには、これを実現するためのES Modulesという機能が備わっていますが、Webアプリケーションの実装においては、他言語のように気軽に利用できないという事情を抱えています。
というのも、ブラウザ上で動かす必要のあるJavaScriptの場合、実行時にインポート対象となったモジュールファイルを取得するサーバリクエストが発生するため、その数によってはアプリケーション全体のパフォーマンス低下につながってしまう可能性があるからです。
一方で、ビルドシステムを採用した場合は、分割されたモジュールファイルはバンドル処理により単一ファイルにまとめられるため、この問題を回避できます。
エラーの事前検出による品質の向上
上述のとおり、バンドル処理で事前にモジュールをまとめるということは、インポート処理としてコードに記述されたパスを頼りにモジュールを読み込むことになります。当然、このパスに誤りがあればモジュールは読み込めず、ビルド処理は失敗しますが、エラーメッセージの表示でエラー理由を知ることができます。
さらには、実装をTypeScriptで行いビルドステップの1つとしてトランスパイルを挟んでおけば、設定の強度に応じた型チェックを適用しつつ、モジュールのインポート処理自体の記述漏れ、変数名のタイポ、といった単純ミスもエラーとして検出できるようになります。
これらのことは、従来のようにDevToolsのコンソールに表示されたエラーメッセージで実装のミスを知るのではなく、ビルド時のエラー通知で知り、事前にエラーを修正できることを意味します。つまりは、動作確認やその先にあるリリース処置も、一定の品質が確保された状態で行われることとなり、品質のみならず手戻り作業の軽減も期待できます。
独自構文と対応エディタによる開発体験の向上
プログラミングの文脈において「開発体験」という言葉は、「気持ちよく開発・保守できるかどうか」を示すものとされています。この開発体験を向上させる1つの方法として、標準の言語仕様に存在しない保守しやすい独自構文でソースコードを記述し、ビルドによって実行可能なコードに変換するというアプローチがあります。
本記事冒頭で触れた、Vue 3の追加機能の1つである、
- Viteを利用したビルドツールチェーン
のViteは、ビルド環境を含むプロジェクトの雛形を生成する機能を持ち、そのビルド環境下では、SFC(Single-File Component)、JSXといった独自構文が利用可能になります。
また、次の追加機能も同様です。
<script setup>
構文の追加- VolarによるTypeScriptIDEサポートの改善
前者の<script setup>
構文はSFC採用時に利用可能な構文、後者のVolarはSFCにもVS Codeの補完機能を対応させる拡張機能になります。他にも同環境下では、CSSの適用範囲をモジュール内のみに限定するScoped CSSや、CSS Modulesも利用できるようになります。
エディタのサポートを受けながら利用するこれらの機能は、開発体験のみならず品質の向上にも寄与します。
Viteによるビルド環境の生成
ビルドシステムには前節で述べたようなメリットがある一方で、構築と運用の難しさが伴いました。しかし、Viteを使うとビルド環境を含むプロジェクトの雛形を生成でき、すぐにでもビルドシステムを利用できるようになります。
そこでここからは、Viteを使ってプロジェクトを生成し、VolarをはじめとしたVS Codeの拡張機能を使い、どのような開発体験が得られるのかを確認できる環境を作っていきましょう。
なお、Viteの詳細については次のシリーズを参照ください。本稿ではビルドシステムの導入と利用にあたって、最低限必要な知識と手順のみを扱います。
Vue CLIとの使い分け
Vite同様に、プロジェクトを構築するツールとしてVue CLIがあります。
しかし、Vue CLIは現在メンテナンスモードに入っており、特定のwebpackの機能を使いたいなどの理由がなく、新しくプロジェクトを開始する場合はViteを利用することが推奨されています。
プロジェクトの作成
まずは、Node.jsのLTS(2022年11月現在ではv18.12.1)をインストールしましょう。これにより、npmコマンドが使えるようになるので、ターミナルを起動し、次のコマンドを入力します。
Viteによるプロジェクトの作成
npm init vite@latest
すると、プロジェクト名、フレームワーク、何をベースにプロジェクトを生成するか、を聞かれます。
プロジェクトの生成条件の指定
✔ Project name: … cg-vue-project
✔ Select a framework: › Vue
✔ Select a variant: › JavaScript
ここでは上記のように、それぞれ、cg-vue-project、Vue、JavaScriptを指定することとします。
これにより、プロジェクトの雛形が生成された旨と、次に入力するコマンドが表示されます。
プロジェクト生成完了メッセージとコマンドの表示
Scaffolding project in /path/to/cg-vue-project...
Done. Now run:
cd cg-vue-project
npm install
npm run dev
ディレクトリ・ファイル構成の確認
まずは、いったん、どのようなディレクトリ・ファイル構成のプロジェクトが生成されたのかを見てみましょう。
プロジェクトのディレクトリ・ファイル構成
cg-vue-project
|--.gitignore
|--.vscode
| |--extensions.json
|--README.md
|--index.html
|--package-lock.json
|--package.json
|--public
| |--vite.svg
|--src
| |--App.vue
| |--assets
| | |--vue.svg
| |--components
| | |--HelloWorld.vue
| |--main.js
| |--style.css
|--vite.config.js
cg-vue-project/src
に、サンプルアプリケーションの実装らしきファイルが見受けられます。Viteでプロジェクトを生成すると、これらのファイルの存在により、簡単なアプリケーションの動作確認ができるようになっています。
また、ここにはApp.vue
やHelloWorld.vue
といった.vue
拡張子のファイルがありますが、これが前節で触れたSFCで記述されたVueコンポーネントになります。
.vue
ファイルの中身は別途確認するとして、ここではpackage.json
の中身を見てみましょう。このファイルには、プロジェクトで使用するパッケージやコマンドなどが記述されています。
package.jsonの中身
{
... // 省略
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.2.37"
},
"devDependencies": {
"@vitejs/plugin-vue": "^3.1.0",
"vite": "^3.1.0"
}
}
アプリケーションの実装に必要なパッケージがdependencies
に、主に開発のサポートとして必要なパッケージがdevDependencies
に記述され、それぞれ、VueとVite関連のパッケージが設定されています。
このことから、Viteは単にプロジェクトを生成するのみでなく、ビルドシステムを始めとした開発支援を担うパッケージとして、存在していることがわかります。
パッケージのインストール
package.json
に記述されたパッケージを利用するには、npm install
コマンドを使い、パッケージをインストールする必要があります。そこで、プロジェクト生成後に表示された次のコマンドを入力してみます。
プロジェクト生成後に表示されたコマンド
cd cg-vue-project
npm install
カレントディレクトリを、package.json
が存在するプロジェクトルートに移動させ、package.json
に指定されたパッケージをインストールさせようとしていることがわかります。
この処置でインストールが行われると、package.json
に設定されたパッケージが依存するパッケージも含め、新しく生成されたnode_modules
ディレクトリ以下に配置されます。
package.jsonに記述されたVueやVite以外にも、それらが依存するパッケージも含め配置されていることがわかる。
ビルドシステムの利用
前節の手順によって、ビルドシステムが利用可能な状態になりました。Viteで生成されたプロジェクトでは、ビルドシステムを使うための3つのコマンドが設定された状態になっています。このコマンドは、先ほどのpackage.json
のscripts
で確認できます。
package.jsonに記述された3つのコマンド
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
ビルド処理
まずはビルドシステムのメイン機能である、ビルド処理を行ってみましょう。これには、scripts
の2つ目に定義されたbuild
コマンドを使います。npm run
コマンドの引数として指定し、次のように実行します。
ビルド処理の実行
npm run build
するとdist
ディレクトリが作られ、その配下には、ビルドによって生成されたファイルとディレクトリの一式が出力されます。
サイト上に公開する場合は、このdist
以下のファイルとディレクトリを、そのままホスティングするようにします。
公開先に合わせたベースパスの設定
ビルドによって生成されたindex.57fc9ac3.js
などのアセットファイルは、<script>
タグから絶対パスで読み込まれます。
index.html
<script type="module" src="/assets/index.57fc9ac3.js" crossorigin></script>
そのため、ネストしたパブリックパスをベースパスとしてアプリケーションを公開する場合は、ネストしたパスを絶対パスの指定に反映する必要があります。
たとえば、GitHub Pagesでは、/repository_name/index.html
のように、リポジトリ名からはじまるURLで公開されるため、アセットファイルを指定する絶対パスは/repository_name
から始まっている必要があります。
これに対応するには、vite.config.js
ファイル内にあるdefineConfig
の設定で、baes
プロパティを追加しベースパスを指定するようにします。
vite.config.js
export default defineConfig({
plugins: [vue()],
base: "/repository_name", // 追加
});
この状態でビルド処理を行うと、絶対パスは指定したベースパスから始まるようになります。
index.html
<script type="module" src="/repository_name/assets/index.57fc9ac3.js" crossorigin></script>
ビルド結果の動作確認
preview
コマンドを実行すると、ローカルでサーバーが起動され、ビルドによってdist
ディレクトリに出力されたアプリケーションの動作確認ができます。
確認用のサーバーの起動
npm run preview
上記コマンドを入力すると、次のようにURLが表示されます。
確認用のURLの表示
> [email protected] preview
> vite preview
➜ Local: http://localhost:4173/
➜ Network: use --host to expose
このURLにブラウザでアクセスすると、アプリケーションの動作確認ができます。
ボタンクリックでカウントアップする、カウンターアプリケーションの動作確認ができます。
開発モードでの起動
実装しながら動作確認したい場合はdev
コマンドを使い、開発モードとしてサーバーを起動します。
開発モードでのサーバーの起動
npm run dev
preview
コマンドの場合と同様に、表示されたURLにブラウザでアクセスすると、アプリケーションの動作確認ができます。
開発モード用の動作確認URLの表示
VITE v3.1.7 ready in 644 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
preview
コマンドとの違いは、ソースコードの監視により実装の変更を検出し、その変更内容が起動中のアプリケーションに即座に反映されるという点です。これにより、実装を調整する都度、ビルドしブラウザをリロードするといった手間から開放され、リアルタイムに実装中の機能の動作確認を行うことができます。
まとめ
今回は、ビルドシステムの導入のメリットと、Viteを用いた開発手順について解説しました。
次回は、Viteで生成したプロジェクトに含まれるサンプルアプリケーションをベースに、SFCをはじめとしたビルド環境下での実装の基本構成を抑えつつ、それらのメリットをより享受するための開発環境を整えていきます。