【9.x対応】Laravel+Mix+Vue 3+TypeScript+Sass(+PurgeCSS)完全導入ガイド

アイキャッチ画像

Laravelで開発する際に必ずやる「フロントエンド環境構築」。調べても古い情報が混合しており中々Laravel Mix関連ので手こずる方も多いのではないでしょうか。

本稿では素早く開発したい人のために、執筆時2022年3月で最新の「Laravel 9.x」でのLaravel Mix+Vue3+TypeScript+SASS+PurgeCSSの導入方法をご紹介します。視認性重視で簡潔に記載します。

Laravelはバージョンによって全く導入手順やコーディング方法が変わります。
v9.x以外での動作検証は行っていませんのでご注意下さい。
▼本記事で構築したプロジェクトの差分サンプルコード
# 動作環境
OS      ->   Ubuntu 20.04 LTS
Env     ->   WSL on Windows10
PHP     ->   v8.0.14 (CLI / OPcache+JIT)
Laravel ->   v9.2
node    ->   v16.13.2

Laravel 9.x 導入

Laravelプロジェクト作成

Laravel Installerを用いるのが一般的だが本題ではないのでComposerだけで使える方法でプロジェクト作成。

$ sudo composer create-project laravel/laravel <プロジェクト名> "9.x"
$ sudo cd <プロジェクト名>
# Permission設定は適宜。artisan serveでエラーが出たら要変更
$ sudo chmod -R 775 *

Laravel Mixインストール

いよいよ本題。Laravel Mixをインストール。これは極めて簡単で、既にパッケージ類はpackage.jsonに記載済みなのでnpmでインストールするだけ。

$ npm install

Laravel Mixの基本コマンド

Laravel Mixの基本コマンドについておさらい。これだけ知っておけば大丈夫。

nom run dev 一般的なビルド=一度のみ行われる
npm run watch ファイルの変更をリアルタイムに検知してビルド
npm run watch-poll watchと違いすべてのファイルを監視する
npm run hot ページを更新せずとも変更を反映するホットリロード
npm run prod 本番ビルド=JS/CSSはMinifyされる

Vue + TypeScript 導入

Vueの導入はv2とv3で大きく変わる。TypeScriptと併用するならComposition APIが使えるVue 3.xが良いだろう。

Vue 2.x系の場合

laravel/uiというパッケージを導入したらnpmコマンドを使わずartisanコマンドだけでvueを導入可能。

$ sudo composer require laravel/ui
$ php artisan ui vue

導入すると「ExampleComponent」という単一ファイルコンポーネント(vueファイル)が出来ていると思うので確認。次項はスキップ。

// webpack.mix.jsも以下のように自動で追記される
mix.js('resources/js/app.js', 'public/js')
    .vue()

Vue 3.x系の場合

laravel/uiは便利だがVue 2.xにしか対応していません。(デフォルトはv2.6.12)

しかし、上記Vue 2.x系の導入後、以下のコマンドを叩くことでLaravel MixとVueのバージョンを上げてnpm経由でインストール可能。

$ npm install -save-dev laravel-mix@next vue@next
# webpack系のWARNが出ることもあるが問題ない

Vueのビルド設定とお試し動作

Vueのv2 or v3がちゃんと導入できているか、テストビルドを行って確認する。
なお、初回のみvue-loaderのインストールが行われるので完了したらもう一度ビルドしましょう。

$ npm run dev
Additional dependencies must be installed. This will only take a moment.
Running: npm install vue-loader@^16.0.0-beta.9 --save-dev --legacy-peer-deps
Okay, done. The following packages have been installed and saved to your package.json dependencies list:

- vue-loader@^16.0.0-beta.9

Finished. Please run Mix again.
# もう一度ビルド
$ npm run dev

以下の画像のようにSuccessfullyと表示されたら問題なし。

TypeScriptトランスパイラ導入

JS関連で最後にTypeScriptのトランスパイラをインストールしてMixのWebpackで処理させる設定を行います。

1. パッケージをインストール

$ npm install ts-loader typescript --save-dev

2. 次にトランスパイルの設定を初期化する(=tsconfig.json作成)

$ tsc -init
You can learn more at https://aka.ms/tsconfig.json
# 適宜ターゲット等を設定

3. /resources/js/app.jsを~/app.tsにリネーム

4. app.ts内を以下に書き換える

import { createApp } from 'vue';
import ExampleComponent from "./components/ExampleComponent.vue";
const app = createApp({
    components: {
        ExampleComponent,
    },
}).mount("#app");

5. webpack.mix.jsを以下のように変更

// 以下の部分を
mix.js('resources/js/app.js', 'public/js')
    .vue()
// 以下のように
mix.ts('resources/js/app.ts', 'public/js')
    .vue()

型定義ファイル作成→テストビルド

この時点ではapp.tsのコンポーネントを読み込む部分でエラーが発生してしまいます。

モジュール ‘./components/ExampleComponent.vue’ またはそれに対応する型宣言が見つかりません。ts(2307)
TS2307: Cannot find module ‘./components/ExampleComponent.vue’ or its corresponding type declarations.

型定義ファイルが無いのが原因ですので、追加しましょう。
shims-vue.d.ts」というファイルを/resources/直下に作成し、以下をコピペ。

declare module '*.vue' {
    import type { DefineComponent } from 'vue'
    const component: DefineComponent<{}, {}, any>
    export default component
 }

これにて長かったTypeScriptの設定は以上になります。
ExampleComponent.vueにコードを書いて、もう一度ビルドしてみましょう。

以下にVue 3のComposition APIを使った例を掲載します。

<template>
  <h1>{{ hello }}</h1>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";

export default defineComponent({
  name: "ExampleComponent",
  setup() {
    const hello = ref("Hello World!");
    return { hello };
  },
  mounted() {
    console.log("mounted!");
  },
});
</script>

※通常のVueと同様にlang=”ts”を設定

SASS(Scss) 導入

続いてPostCSSのSASSを導入します。先程のTypeScriptほど複雑ではないです。

まずは既存の/resources/cssフォルダを~/sassにリネームし、app.cssをapp.scssにリネーム。

次にwebpack.mix.jsを以下のように変更します。

// 以下の部分を
mix.ts('resources/js/app.ts', 'public/js')
    .postCss('resources/css/app.css', 'public/css', [ ]);
// 以下のように置き換え
mix.ts('resources/js/app.ts', 'public/js')
    .sass('resources/sass/app.scss', 'public/css');

あとは初回ビルドの際に以下のようにSASSコンパイラのインストールを勝手にしてくれるので完了したら再度ビルドしてコンパイルされていることを確認して下さい。

$ npm run prod
> production
> mix --production
Additional dependencies must be installed. This will only take a moment.
Running: npm install sass-loader@^12.1.0 sass resolve-url-loader@^5.0.0 --save-dev --legacy-peer-deps Finished.
Please run Mix again.
# もし自動でインストールしてくれない場合は以下コマンドを叩く
npm install sass-loader@^12.1.0 sass resolve-url-loader@^5.0.0 --save-dev --legacy-peer-deps

[オプション]PurgeCSS 導入

最後にオプションとしてPurgeCSSという、本番ビルド時にBlade/Vueファイル内で使っていないCSSを自動で解析して削除してくれるパッケージが有るので一緒に追加しましょう。

$ npm install laravel-mix-purgecss --save-dev

あとはwebpack.mix.jsを以下のように変更するだけで設定は終わり。

const mix = require('laravel-mix');
// 以下を追記
require('laravel-mix-purgecss');

    ︙

mix.ts('resources/js/app.ts', 'public/js')
    .sass('resources/sass/app.scss', 'public/css')
    // 以下を追記
    .purgeCss();

Blade内でVueを読み込ませる

最後にビルドしたファイルをBlade内で読み込ませましょう。

今回はid=”app”にVueコンポーネントをマウントするようにapp.tsで設定したので以下のように記述。
マスタッシュ構文{{ mix(‘files’) }}でビルドしたアセットを読み込めます。

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="{{ mix('css/app.css') }}">
    <title>Hello, world!</title>
</head>
<body>
    <!-- your vue component -->
    <div id="app">
        <v-app>
            <example-component></example-component>
        </v-app>
    </div>
    <script src="{{ mix('js/app.js') }}"></script>
</body>

後の動作確認

最後にすべて動作しているかを確認しましょう。Routeを設定してアクセス。

<?php
Route::get('/vue', function() {
    return view('vue');
});
ちゃんとトランスパイルされたJSファイルが読み込まれ、コンパイルされたCSSファイルも読み込まれています。

LaravelやそれらのFirst-Partyライブラリは仕様変更が激しいので是非参考になりましたら幸いです。

是非ご共有もお願いいたします!(3月下旬なのに手をかじかんている状態で執筆しております︙)