Laravel 10 + Vite CSS注入致加载视觉突兀问题排查
背景
我有一个Laravel 10项目,使用laravel-vite-plugin,之前熟悉WebPack,刚接触Vite,不确定操作是否正确。
需求
- 本地开发启用HMR(热模块替换)
- 部署时执行
npm run build生成可部署的打包静态资源
遇到的问题
- Vite在请求完成后才注入CSS,导致页面加载视觉体验极差,出现突兀的加载效果
- 具体表现:图片先显示大尺寸再缩小、背景在DOM加载过程中才填充(耗时不足1秒,但体验违和)
- 尝试添加加载遮罩,但遮罩也受CSS注入影响,无法发挥预期作用
疑问
- 生产环境静态资源部署方式是否正确?如果不对,问题出在哪?
- 我的构建流程有没有错误?
- 为什么部署静态资源后仍存在CSS注入问题?
相关配置代码
head.blade.php(生产环境仅部署静态资源)
@if(!app()->environment('production')) @vite('resources/css/app.css') @else <link rel="preload" href="{{ asset('build/assets/app-e0be5467.css') }}" as="style" onload="this.onload=null;this.rel='stylesheet'"> <noscript><link rel="stylesheet" href="{{ asset('build/assets/app-e0be5467.css') }}"></noscript> <link rel="preload" href="{{ asset('build/assets/app-1c9978c6.css') }}" as="style" onload="this.onload=null;this.rel='stylesheet'"> <noscript><link rel="stylesheet" href="{{ asset('build/assets/app-1c9978c6.css') }}"></noscript> @endif
vite.config.js
import { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; import path from 'path'; export default defineConfig({ plugins: [ laravel({ input: ['resources/sass/app.scss', 'resources/js/app.js'], refresh: true, }), ], });
package.json
"scripts": { "dev": "vite", "build": "vite build && vite build --ssr" },
问题解答
1. 生产环境部署方式错误
你手动写死了CSS文件的哈希文件名,且未使用Laravel Vite提供的@vite指令自动处理生产环境资源。Vite打包后的资源哈希文件名用于缓存更新,手动写死会导致后续构建后文件名变化时,页面加载旧资源;更关键的是,preload + onload的加载方式会延迟CSS的解析,这正是页面加载时样式缺失、视觉突兀的核心原因。
正确写法无需手动区分环境,直接使用@vite指令:
@vite(['resources/sass/app.scss', 'resources/js/app.js'])
Laravel Vite插件会自动根据环境生成对应资源标签:开发环境注入HMR相关脚本和样式,生产环境直接输出带正确哈希的<link rel="stylesheet">和<script>标签,不会延迟CSS加载。
2. 构建流程存在冗余
你的build脚本执行了两次vite build,第二次的--ssr参数如果没有用到SSR(服务端渲染),完全是多余的,只会增加构建时间。
修正后的package.json脚本:
"scripts": { "dev": "vite", "build": "vite build" },
若确实需要SSR,需单独配置SSR入口,而非重复执行build命令。
3. 部署后仍有CSS注入问题的原因
你用preload方式加载CSS时,浏览器会先预加载资源,但不会立即解析为样式表,需等到onload触发后才会将rel改为stylesheet,导致页面在CSS解析前已渲染无样式DOM,出现视觉闪烁。而正确使用@vite指令后,生产环境会直接输出标准的<link rel="stylesheet">标签,浏览器会在渲染DOM前优先加载解析CSS,避免无样式内容闪烁(FOUC)。
另外,@vite指令中传入的resources/css/app.css与vite.config.js里的resources/sass/app.scss不匹配,开发环境可能出现资源加载异常,建议保持路径一致。
内容的提问来源于stack exchange,提问作者Ryan Dorn

