Laravel+Vue+Inertia配置TypeScript遇500服务器错误求助
Laravel + Vue 3 + Inertia 转 TypeScript 后 npm run dev 报 500 错误
我用 Laravel、Vue 3 和 Inertia 技术栈把项目转成 TypeScript 后,执行 npm run dev 时 Chrome 控制台提示「加载资源失败:服务器响应状态码为 500 ()」。完全跟着教程操作还是出问题,排查后怀疑是配置问题,附上我的配置文件和组件代码,求解决:
配置文件
resources/js/app.ts
import "../css/app.css"; import { createApp, h, type DefineComponent } from 'vue' import { createInertiaApp } from '@inertiajs/vue3' import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers' createInertiaApp({ resolve: async (name: string) => { let page = await resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob<DefineComponent>('./Pages/**/*.vue')) return page }, setup({ el, App, props, plugin }) { createApp({ render: () => h(App, props) }) .use(plugin) .mount(el) }, })
tsconfig.json
{ "compilerOptions": { "target": "es2016", "jsx": "preserve", "module": "commonjs", "paths": { "@/*": ["./resources/js/*"] }, "resolveJsonModule": true, "allowJs": true, "isolatedModules": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true } }
resources/views/app.blade.php
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> @vite('resources/js/app.ts') @inertiaHead </head> <body> @inertia </body> </html>
vite.config.js
import { defineConfig } from "vite"; import laravel from "laravel-vite-plugin"; import vue from "@vitejs/plugin-vue"; export default defineConfig({ plugins: [ laravel({ input: ['resources/css/app.css', 'resources/js/app.ts'], refresh: true, }), vue({ template: { transformAssetUrls: { base: null, includeAbsolute: false, }, }, }), ], });
父组件示例
<script setup lang="ts"> import { defineProps, reactive, ref, onMounted } from 'vue'; import WeatherDisplay from './WeatherDisplay'; import { Refs, WeatherData } from '../interfaces/interfaces' import { useDark, useToggle } from '@vueuse/core'; import { router } from '@inertiajs/vue3'; const isDark = useDark(); const toggleDark = useToggle(isDark); // Define the props for the component const props = defineProps<{ data: Object, }>(); // This object contains all required refs const allRefs = ref<Refs>({ searchWeather: '', errorMessage: null, }); // Creates a reactive array that is updated with weatherData const weatherData = reactive<WeatherData[]>([]); // Function to load data from local storage function loadDataFromLocalStorage(): WeatherData[] { const data = localStorage.getItem('weatherData'); return data ? JSON.parse(data) : []; } // Function to set data to local storage function setDataToLocalStorage(data: WeatherData[]) { weatherData.push(props.data); localStorage.setItem('weatherData', JSON.stringify(data)); } // Delete weather data from array and local storage function deleteWeatherData(index: number) { weatherData.splice(index, 1); localStorage.setItem('weatherData', JSON.stringify(weatherData)); } // Load the data from local storage on mounted onMounted(() => { const savedData = loadDataFromLocalStorage(); if (savedData.length > 0) { weatherData.splice(0, weatherData.length, ...savedData); } if (props.data && !props.data.error) { setDataToLocalStorage(weatherData); } else if (props.data && props.data.error) { allRefs.value.errorMessage = props.data.error.message; console.log(allRefs.value.errorMessage); } }); // Define a method to send the GET request to the backend async function submit() { try { await router.get('/weather', { searchWeather: allRefs.value.searchWeather }); } catch (error) { console.log(error); } } </script> <template> <main :class="{ 'dark-mode': isDark }"> <div class="flex flex-col items-center justify-center h-96"> <div class="mb-4 text-center text-4xl font-bold dark:text-[#7371FF]" > SecureClouds </div> <div class="flex flex-row justify-end mb-4"> <div class="mr-4 flex items-center"> <span class="text-xl dark:text-[#7371FF]"> {{ isDark ? 'Dark' : 'Light' }} Mode </span> </div> <div> <button @click="toggleDark()" class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded dark:bg-[#22F1BF] dark:text-black" > Switch </button> </div> </div> <div class="block w-2/3 rounded-lg"> <div class="flex justify-center"> <div class="w-2/3 p-4"> <div v-if="allRefs.errorMessage" class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert" > <strong class="font-bold">{{ allRefs.errorMessage }}</strong> </div> <form @submit.prevent="submit" class="w-full"> <div class="relative mb-4 flex w-full flex-wrap items-stretch" > <input type="search" class="relative bg-[#F9F3EE] m-0 -mr-px block flex-auto border border-neutral-300 rounded-lg shadow dark:bg-transparent bg-clip-padding px-6 py-4 text-lg font-normal text-neutral-700 outline-none transition duration-300 ease-in-out focus:border-primary-600 focus:text-neutral-700 focus:shadow-te-primary focus:outline-none dark:border-[#22F1BF] dark:text-[#22F1BF] dark:placeholder:text-[#22F1BF]" placeholder="Suchen..." name="searchWeather" aria-label="Search" aria-describedby="button-addon3" v-model="allRefs.searchWeather" /> <button type="submit" class="bg-[#F9F3EE] hover:bg-slate-200 text-gray-800 font-semibold py-2 px-6 border border-neutral-300 rounded-lg shadow ml-4 dark:bg-[#22F1BF] dark:border-[#22F1BF] dark:text-black" > Suchen </button> </div> </form> </div> </div> </div> </div> <div class="grid grid-cols-2 sm:grid-cols-2 lg:grid-cols-3 gap-4"> <WeatherDisplay v-for="(data, index) in weatherData" :key="index" :data="data" @delete="deleteWeatherData(index)" > </WeatherDisplay> </div> </main> </template> <style> main { background-color: #b2c8df; overflow-y: scroll; height: 100vh; } .dark-mode { background: #0d1117; } </style>
可能的解决步骤
1. 查看 Laravel 日志定位真实错误
浏览器的 500 错误只是表面现象,真实错误信息在 Laravel 的日志文件里:storage/logs/laravel.log。先打开这个日志,找到对应时间点的错误条目,这是最直接的排查方式。
2. 修正 tsconfig.json 的模块配置
Vite 基于 ES 模块运行,你的 tsconfig.json 里 module 设置为 commonjs 会导致模块解析冲突。修改为:
"module": "ESNext", "moduleResolution": "bundler",
3. 修复 app.ts 中的 resolve 函数
resolvePageComponent 返回的模块可能需要取 default 导出,否则会导致组件加载失败。调整 resolve 函数:
resolve: async (name: string) => { const page = await resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob<DefineComponent>('./Pages/**/*.vue')); // 确保返回组件的默认导出 return page.default || page; },
4. 组件中使用精确的 Props 类型
你当前的组件 props 用了 Object 类型,这不符合 TypeScript 规范,可能导致编译错误。替换为你定义的 WeatherData 类型:
const props = defineProps<{ data: WeatherData | { error: { message: string } }; }>();
5. 安装必要的 TypeScript 依赖
确保安装了 Vue 和 Inertia 的类型定义,以及 Vite 相关的 TypeScript 支持:
npm install -D @types/node vue-tsc @vitejs/plugin-vue
6. 清理缓存并重启服务
- 清理 Laravel 缓存:
php artisan cache:clear && php artisan config:clear - 清理 Vite 缓存:删除
node_modules/.vite文件夹 - 重启
npm run dev和 Laravel 服务
内容的提问来源于stack exchange,提问作者Michael Brilz
相关产品推荐
相关产品推荐

