laravel9 + inertia + vue3.2
@inertiajs/inertia-vue3@0.6.0
@inertiajs/inertia@0.11.0
@inertiajs/progress@0.2.7
上記環境でサンプルサイトのコードを試していたら
vue3.2からの新機能の<script setup>
でコードを記述の後に
lang="ts"をつけて<script setup lang="ts">
にしてビルドしたところ
以下のエラーがでるようになる。
Compiled with some errors in 12.82s
ERROR in ./resources/js/Pages/Hoge/Show.vue?vue&type=template&id=ad2814ac&ts=true (./node_modules/babel-loader/lib/index.js??clonedRuleSet-5.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[3]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./resources/js/Pages/Hoge/Show.vue?vue&type=template&id=ad2814ac&ts=true)
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: /var/www/html/laravel9vue3/resources/js/Pages/Hoge/Show.vue: Unexpected token, expected "," (8:27)
typescriptの構文エラーとbabel-loaderでのビルドエラーっぽいのでそれらしいメッセージでググってみたがこれといった解決方法が載っていない。
とりあえずビルドが通すまでの手順をメモる。
ncu(npm check update)で最新パッケージにしておく
npm-check-updatesはグローバルに入れておく。
# npm install -g npm-check-updates
ドキュメントのベースフォルダでncuコマンドを実行してアップデートが出ないようにしておく
$ ncu
Checking /var/www/html/hogehoge/package.json
[====================] 39/39 100%
All dependencies match the latest package versions :)
webpack.mix.jsをtypescript対応にする。
mix.ts('resources/js/app.ts', 'public/js')
.vue()
.postCss('resources/css/tailwind.css', 'public/css', [require('tailwindcss'), require('autoprefixer')])
.sass('resources/scss/bootstrap.scss', 'public/css')
.alias({
'@': 'resources/js',
})
.sourceMaps();
お試しでいろいろ付随しているが変えるところは
・mix.js(
の所をmix.ts(
に変更
・resources/js/app.js
をresources/js/app.ts
にリネーム
の2か所。
app.ts(もとはapp.js)の修正
inertia+vueでのapp.jsのサンプルなどでよく見る設定だが以下のように変更
import './bootstrap';
//import '../css/app.css';
import { createApp, h } from 'vue';
import { createInertiaApp } from '@inertiajs/inertia-vue3';
import { InertiaProgress } from '@inertiajs/progress';
import { createI18n } from 'vue-i18n';
import route from 'ziggy-js';
import 'flowbite';
//import "bootstrap/dist/css/bootstrap.min.css";
//import "bootstrap";
const appName = window.document.getElementsByTagName('title')[0]?.innerText || '';
async function loadLocaleMessages(i18n, locale){
const messages = await require(`../../lang/${locale}.json`);
i18n.global.setLocaleMessage(locale, messages)
}
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => require(`./Pages/${name}.vue`),
setup({ el, app, props, plugin }) {
const setupAsync = async ({ el, app, props, plugin }) => {
const i18n = createI18n({
legacy: false,
globalInjection: true,
locale: 'ja'
});
await loadLocaleMessages(i18n, 'ja');
createApp({ render: () => h(app, props) })
.use(plugin)
.use(i18n)
.mixin({ methods: { route } })
.mount(el);
}
setupAsync({ el, app, props, plugin });
},
});
InertiaProgress.init({ color: '#4B5563' });
こちらもお試しでいろいろソースコードが変わっているが変更点としては以下の点。
・import route from 'ziggy-js';
を明記してroute変数を使えるようにする。
こちらがないとcreateApp
のmixinのところでエラーとなる。
・createInertiaApp関数のsetupメソッド内で非同期処理を行うように変更
vue-i18nによる多言語化も試していたため発生。サンプルサイトだと
setupメソッド自体をasyncをつけて非同期化するのだがどうもうまくいかないので
setupAsyncというラッパー関数を作って対応
これでvueファイル内の<script setup lang="ts">
としてもエラーにならなくなった。
追記
vue3でtypescript化するためファイルshims-vue.d.ts
を/resources/js/@types/
配下に格納する。
declare module "*.vue" {
import type { DefineComponent } from "vue";
const component: DefineComponent<{}, {}, any>;
export default component;
}
tsconfig.json
でtypeRoots
を設定する。
...(略)...
"typeRoots": [
"node_modules/@types",
"resources/js/@types"
],
...(略)...
多言語化の対応(未)
app.blade.php
に
<script>
var __locale = '{{ app()->getLocale() }}'
</script>
としてこの__locale変数をapp.jsで使って多言語化する方法があるが
typescript化にすると使えないので、とりあえずapp.tsでは'ja'固定にしている。
laravelの外部定義は別の方法でjsに取り入れたほうがいいのかも。