Laravel重写Vite类受保护方法添加script标签defer属性
实现方案
Illuminate\Foundation\Vite类未引入宏扩展特性,且makeScriptTag为受保护方法,无法从外部直接修改,在不改动框架核心代码的前提下,最规范的实现方式是继承重写+服务容器绑定替换,全程不修改vendor目录下的任何文件,不会被后续框架更新覆盖。
步骤1:创建自定义Vite子类
在项目中新建自定义Vite类,继承框架原生的Vite基类,重写makeScriptTag方法,在生成的script标签上新增defer属性。你可以根据自身目录规范调整类的存放位置,例如存放在app/Vite/CustomVite.php:
<?php namespace App\Vite; use Illuminate\Foundation\Vite as BaseVite; class CustomVite extends BaseVite { /** * Generate a script tag for the given URL. * * @param string $url * @return string */ protected function makeScriptTag($url) { return sprintf('<script type="module" src="%s" defer></script>', $url); } }
步骤2:替换服务容器中的Vite绑定
Laravel所有用到Vite实例的地方(包括@vite Blade指令、vite()助手函数)都是从服务容器解析的,你只需要在服务提供者中把原生Vite的绑定替换为自定义子类的实例即可。
打开app/Providers/AppServiceProvider.php,在register方法中添加绑定逻辑:
<?php namespace App\Providers; use App\Vite\CustomVite; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Register any application services. */ public function register(): void { $this->app->singleton(\Illuminate\Foundation\Vite::class, function () { return new CustomVite(); }); } // 其余boot等原有方法保持不变即可 }
验证生效
代码修改完成后,执行php artisan optimize:clear清除应用缓存,刷新页面查看前端源码,就能看到所有Vite自动生成的module类型script标签都已经带上了defer属性,原有资源加载、版本号处理等功能完全不受影响。
说明:
- 不要直接修改
vendor/laravel/framework目录下的核心代码,后续执行composer update时改动会被直接覆盖,且不符合框架扩展规范- 这种继承替换的实现方式是Laravel官方推荐的扩展模式,后续框架升级不会覆盖自定义逻辑,维护成本极低
- 替换绑定后不需要额外修改模板或其他业务代码,所有调用Vite生成资源标签的逻辑都会自动走重写后的方法
内容的提问来源于stack exchange,提问作者Mark Shust at M.academy
相关产品推荐
相关产品推荐

