Vite連携
最新のJavaScriptアプリケーションには、洗練されたビルドツールが必要です。Nette Assetsは、次世代のフロントエンドビルドツールであるViteとのファーストクラスの連携を提供します。設定の手間なしで、ホットモジュールリプレイスメント(HMR)による超高速開発と最適化された本番ビルドを実現します。
- ゼロ設定 – ViteとPHPテンプレート間の自動ブリッジ
- 完全な依存関係管理 – 1つのタグですべてのアセットを処理
- ホットモジュールリプレイスメント – JavaScriptとCSSの即時更新
- 最適化された本番ビルド – コード分割とツリーシェイキング
Nette AssetsはViteとシームレスに連携するため、テンプレートを通常通り記述しながら、これらすべての恩恵を受けることができます。
Viteのセットアップ
Viteをステップバイステップでセットアップしましょう。ビルドツールに慣れていなくても心配ありません。すべて説明します!
ステップ1: Viteをインストールする
まず、プロジェクトにViteとNetteプラグインをインストールします。
npm install -D vite @nette/vite-plugin
これにより、Viteと、ViteがNetteと完全に連携するのに役立つ特別なプラグインがインストールされます。
ステップ2: プロジェクト構造
標準的なアプローチは、ソースアセットファイルをプロジェクトルートのassets/
フォルダーに配置し、コンパイルされたバージョンをwww/assets/
に配置することです。
web-project/ ├── assets/ ← ソースファイル (SCSS, TypeScript, ソース画像) │ ├── public/ ← 静的ファイル (そのままコピーされる) │ │ └── favicon.ico │ ├── images/ │ │ └── logo.png │ ├── app.js ← メインエントリポイント │ └── style.css ← スタイル └── www/ ← public ディレクトリ (ドキュメントルート) ├── assets/ ← コンパイルされたファイルがここに入る └── index.php
assets/
フォルダーにはソースファイル、つまり記述するコードが含まれています。Viteはこれらのファイルを処理し、コンパイルされたバージョンをwww/assets/
に配置します。
ステップ3: Viteを設定する
プロジェクトルートにvite.config.ts
ファイルを作成します。このファイルは、Viteにソースファイルの場所とコンパイルされたファイルの出力先を指示します。
Nette
Viteプラグインには、設定を簡素化するスマートなデフォルトが付属しています。フロントエンドのソースファイルはassets/
ディレクトリ(root
オプション)にあり、コンパイルされたファイルはwww/assets/
(outDir
オプション)に配置されると想定しています。必要なのはエントリポイントを指定することだけです。
import { defineConfig } from 'vite';
import nette from '@nette/vite-plugin';
export default defineConfig({
plugins: [
nette({
entry: 'app.js',
}),
],
});
アセットをビルドするために別のディレクトリ名を指定したい場合は、いくつかのオプションを変更する必要があります。
export default defineConfig({
root: 'assets', // ソースアセットのルートディレクトリ
build: {
outDir: '../www/assets', // コンパイルされたファイルの出力先
},
// ... その他の設定 ...
});
outDir
パスはroot
からの相対パスと見なされるため、先頭に../
があります。
ステップ4: Netteを設定する
common.neon
でNette AssetsにViteについて伝えます。
assets:
mapping:
default:
type: vite # NetteにViteMapperを使用するよう指示
path: assets
ステップ5: スクリプトを追加する
これらのスクリプトをpackage.json
に追加します。
{
"scripts": {
"dev": "vite",
"build": "vite build"
}
}
これで次のことができます。
npm run dev
– ホットリロード付き開発サーバーを開始npm run build
– 最適化された本番ファイルを作成
エントリポイント
エントリポイントは、アプリケーションが開始するメインファイルです。このファイルから、他のファイル(CSS、JavaScriptモジュール、画像)をインポートし、依存関係ツリーを作成します。Viteはこれらのインポートを追跡し、すべてをバンドルします。
エントリポイントassets/app.js
の例:
// スタイルをインポート
import './style.css'
// JavaScriptモジュールをインポート
import netteForms from 'nette-forms';
import naja from 'naja';
// アプリケーションを初期化
netteForms.initOnLoad();
naja.initialize();
テンプレートでは、エントリポイントを次のように挿入できます。
{asset 'app.js'}
Nette Assetsは、必要なすべてのHTMLタグ(JavaScript、CSS、およびその他の依存関係)を自動的に生成します。
複数のエントリポイント
大規模なアプリケーションでは、個別のエントリポイントが必要になることがよくあります。
export default defineConfig({
plugins: [
nette({
entry: [
'app.js', // public ページ
'admin.js', // 管理パネル
],
}),
],
});
異なるテンプレートで使用します。
{* public ページで *}
{asset 'app.js'}
{* 管理パネルで *}
{asset 'admin.js'}
重要: ソースファイルとコンパイル済みファイル
本番環境では、次のもののみをロードできることを理解することが重要です。
entry
で定義されたエントリポイントassets/public/
ディレクトリのファイル
{asset}
を使用してassets/
から任意のファイルをロードすることはできません。JavaScriptまたはCSSファイルによって参照されているアセットのみです。ファイルがどこからも参照されていない場合、コンパイルされません。Viteに他のアセットを認識させたい場合は、public フォルダーに移動できます。
デフォルトでは、Viteは4KB未満のすべてのアセットをインライン化するため、これらのファイルを直接参照できないことに注意してください。(Vite ドキュメントを参照)。
{* ✓ これは動作します - エントリポイントです *}
{asset 'app.js'}
{* ✓ これは動作します - assets/public/ にあります *}
{asset 'favicon.ico'}
{* ✗ これは動作しません - assets/ 内のランダムなファイルです *}
{asset 'components/button.js'}
開発モード
開発モードは完全にオプションですが、有効にすると大きなメリットがあります。主な利点はホットモジュールリプレイスメント (HMR)です。アプリケーションの状態を失うことなく変更を即座に確認できるため、開発エクスペリエンスがはるかにスムーズで高速になります。
Viteは、開発を信じられないほど高速にする最新のビルドツールです。従来のバンドラーとは異なり、Viteは開発中にコードをブラウザに直接提供するため、プロジェクトの規模に関係なくサーバーの起動が瞬時に行われ、更新も超高速です。
開発サーバーの起動
開発サーバーを実行します。
npm run dev
次のように表示されます。
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
開発中は、このターミナルを開いたままにしてください。
Nette Viteプラグインは、次の条件が満たされたときに自動的に検出します。
- Vite開発サーバーが実行中である
- Netteアプリケーションがデバッグモードである
両方の条件が満たされると、Nette Assetsはコンパイルされたディレクトリからではなく、Vite開発サーバーからファイルをロードします。
{asset 'app.js'}
{* 開発時: <script src="http://localhost:5173/app.js" type="module"></script> *}
{* 本番時: <script src="/assets/app-4a8f9c7.js" type="module"></script> *}
設定は不要です。ただ動作します!
異なるドメインでの作業
開発サーバーがlocalhost
以外のもの(例:
myapp.local
)で実行されている場合、CORS(Cross-Origin Resource
Sharing)の問題が発生する可能性があります。CORSは、ウェブブラウザのセキュリティ機能であり、デフォルトでは異なるドメイン間のリクエストをブロックします。PHPアプリケーションがmyapp.local
で実行されているが、Viteがlocalhost:5173
で実行されている場合、ブラウザはこれらを異なるドメインと見なし、リクエストをブロックします。
これを解決するには2つのオプションがあります。
オプション1: CORSを設定する
最も簡単な解決策は、PHPアプリケーションからのクロスオリジンリクエストを許可することです。
export default defineConfig({
// ... その他の設定 ...
server: {
cors: {
origin: 'http://myapp.local', // PHPアプリのURL
},
},
});
オプション2: Viteを同じドメインで実行する
もう1つの解決策は、ViteをPHPアプリケーションと同じドメインで実行することです。
export default defineConfig({
// ... その他の設定 ...
server: {
host: 'myapp.local', // PHPアプリと同じ
},
});
実際、この場合でも、開発サーバーは同じホスト名ですが異なるポートで実行されるため、CORSを設定する必要があります。ただし、この場合、CORSはNette Viteプラグインによって自動的に設定されます。
HTTPS開発
HTTPSで開発する場合、Vite開発サーバーには証明書が必要です。最も簡単な方法は、証明書を自動的に生成するプラグインを使用することです。
npm install -D vite-plugin-mkcert
vite.config.ts
での設定方法は次のとおりです。
import mkcert from 'vite-plugin-mkcert';
export default defineConfig({
// ... その他の設定 ...
plugins: [
mkcert(), // 証明書を自動生成し、httpsを有効にする
nette(),
],
});
CORS設定(上記のオプション1)を使用している場合、オリジンURLをhttp://
ではなくhttps://
を使用するように更新する必要があることに注意してください。
本番ビルド
最適化された本番ファイルを作成します。
npm run build
Viteは次のことを行います。
- すべてのJavaScriptとCSSをミニファイします
- コードを最適なチャンクに分割します
- キャッシュバストのためにハッシュ化されたファイル名を生成します
- Nette Assets用のマニフェストファイルを作成します
出力例:
www/assets/
├── app-4f3a2b1c.js # メインJavaScript (ミニファイ済み)
├── app-7d8e9f2a.css # 抽出されたCSS (ミニファイ済み)
├── vendor-8c4b5e6d.js # 共有依存関係
└── .vite/
└── manifest.json # Nette Assetsのマッピング
ハッシュ化されたファイル名により、ブラウザは常に最新バージョンをロードします。
Public フォルダー
assets/public/
ディレクトリ内のファイルは、処理されずにそのまま出力にコピーされます。
assets/
├── public/
│ ├── favicon.ico
│ ├── robots.txt
│ └── images/
│ └── og-image.jpg
├── app.js
└── style.css
通常通り参照します。
{* これらのファイルはそのままコピーされます *}
<link rel="icon" href={asset 'favicon.ico'}>
<meta property="og:image" content={asset 'images/og-image.jpg'}>
publicファイルの場合、FilesystemMapperの機能を使用できます。
assets:
mapping:
default:
type: vite
path: assets
extension: [webp, jpg, png] # 最初にWebPを試す
versioning: true # キャッシュバストを追加
vite.config.ts
設定では、publicDir
オプションを使用してpublicフォルダーを変更できます。
動的インポート
Viteは最適なロードのためにコードを自動的に分割します。動的インポートを使用すると、実際に必要なときにのみコードをロードできるため、初期バンドルサイズを削減できます。
// 重いコンポーネントをオンデマンドでロード
button.addEventListener('click', async () => {
let { Chart } = await import('./components/chart.js')
new Chart(data)
})
動的インポートは、必要なときにのみロードされる個別のチャンクを作成します。これは「コード分割」と呼ばれ、Viteの最も強力な機能の1つです。動的インポートを使用すると、Viteは動的にインポートされたモジュールごとに個別のJavaScriptファイルを自動的に作成します。
{asset 'app.js'}
タグは、これらの動的チャンクを自動的にプリロードしません。これは意図的な動作です。使用されない可能性のあるコードをダウンロードしたくありません。チャンクは、動的インポートが実行されたときにのみダウンロードされます。
ただし、特定の動的インポートが重要であり、すぐに必要になることがわかっている場合は、それらをプリロードできます。
{* メインエントリポイント *}
{asset 'app.js'}
{* 重要な動的インポートをプリロード *}
{preload 'components/chart.js'}
これにより、ブラウザはチャートコンポーネントをバックグラウンドでダウンロードし、必要になったときにすぐに使用できるようにします。
TypeScriptサポート
TypeScriptはそのまま動作します。
// assets/main.ts
interface User {
name: string
email: string
}
export function greetUser(user: User): void {
console.log(`Hello, ${user.name}!`)
}
TypeScriptファイルを通常通り参照します。
{asset 'main.ts'}
完全なTypeScriptサポートには、インストールが必要です。
npm install -D typescript
追加のVite設定
以下に、詳細な説明付きの便利なVite設定オプションをいくつか示します。
export default defineConfig({
// ソースアセットを含むルートディレクトリ
root: 'assets',
// 内容がそのまま出力ディレクトリにコピーされるフォルダー
// デフォルト: 'public' ('root'からの相対パス)
publicDir: 'public',
build: {
// コンパイルされたファイルの出力先 ('root'からの相対パス)
outDir: '../www/assets',
// ビルド前に出力ディレクトリを空にするか?
// 以前のビルドからの古いファイルを削除するのに便利
emptyOutDir: true,
// outDir内の生成されたチャンクとアセットのサブディレクトリ
// 出力構造を整理するのに役立つ
assetsDir: 'static',
rollupOptions: {
// エントリポイント - 単一のファイルまたはファイルの配列
// 各エントリポイントは個別のバンドルになる
input: [
'app.js', // メインアプリケーション
'admin.js', // 管理パネル
],
},
},
server: {
// 開発サーバーをバインドするホスト
// ネットワークに公開するには '0.0.0.0' を使用
host: 'localhost',
// 開発サーバーのポート
port: 5173,
// クロスオリジンリクエストのCORS設定
cors: {
origin: 'http://myapp.local',
},
},
css: {
// 開発時にCSSソースマップを有効にする
devSourcemap: true,
},
plugins: [
nette(),
],
});
これで完了です!Nette Assetsと連携した最新のビルドシステムが手に入りました。