外部JS文件如何正确获取Laravel的public目录路径
- 项目基于Laravel框架开发,Blade模板文件为
index-game.blade.php,模板中通过以下代码引入public目录下的JS文件,目前该JS文件可正常加载:
<script type="text/javascript" src="{{asset('game/')}}/js/CPreloader.js"></script>
CPreloader.js内原有代码通过相对路径加载精灵图资源:
s_oSpriteLibrary.addSprite("bg_menu","./sprites/bg_menu.jpg"); s_oSpriteLibrary.addSprite("progress_bar","./sprites/progress_bar.png");
- 访问该模板的路由为
http://127.0.0.1:8000/games/slot1时,浏览器控制台抛出404报错:
bg_menu.jpg:1 GET http://127.0.0.1:8000/games/sprites/bg_menu.jpg 404 (Not Found) progress_bar.png:1 GET http://127.0.0.1:8000/games/sprites/progress_bar.png 404 (Not Found)
JS中的相对路径是基于当前页面的路由地址解析,而非JS文件自身的存放目录解析。当前错误请求路径为/games/sprites/,实际资源正确存放路径为/game/sprites/,路径层级不匹配导致资源找不到。
手动将JS内所有资源路径前缀改为../game/sprites/可正常加载,但游戏项目JS中包含大量图片资源路径,逐一修改成本过高,需要在不批量修改单个资源路径的前提下,让外部JS正确识别Laravel的public目录路径,完成静态资源加载。
方案1(最优,改动量最小)
所有资源加载都走s_oSpriteLibrary.addSprite方法,只需要修改两处即可全量生效:
- 在Blade模板中引入
CPreloader.js之前,定义全局资源根路径变量,通过Laravel自带的asset()方法生成正确的资源目录地址:
<script> window.GAME_ASSET_ROOT = "{{ asset('game/') }}"; </script> <script type="text/javascript" src="{{asset('game/')}}/js/CPreloader.js"></script>
- 找到JS文件中
s_oSpriteLibrary.addSprite方法的定义位置,添加路径自动拼接逻辑,原有资源调用代码完全不用改动:
// 修改addSprite方法的实现 s_oSpriteLibrary.addSprite = function(sSpriteKey, sResourcePath) { // 仅对相对路径做拼接,绝对路径、http开头的路径保持原样 if (sResourcePath.startsWith('./')) { sResourcePath = window.GAME_ASSET_ROOT + sResourcePath.slice(2); } // 下方保留该方法原有业务逻辑即可 // ...... }
方案2(适合单一场景页面)
如果页面仅承载游戏内容,没有其他模块的路径跳转、资源加载逻辑,可以直接在模板的<head>标签内添加<base>标签,指定当前页面所有相对路径的解析基准:
<head> <!-- 其他头部标签 --> <base href="{{ asset('game/') }}"> </head>
添加后当前页面所有相对路径都会以public/game/目录为基准解析,JS里原有的./sprites/xxx路径会自动映射到正确地址。注意该标签会影响页面所有a标签跳转、CSS/JS资源加载,混合多模块的页面不要用这个方案,避免路径混乱。
方案3(适合可批量操作的场景)
如果JS代码没有混淆加密,可以直接用编辑器的全局替换功能,将所有./sprites/批量替换为/game/sprites/,直接使用站点根目录开头的绝对路径寻址,不会受当前路由层级影响,一次替换即可完成所有路径修正,适配所有路由场景。
注意:静态资源加载尽量不要用
./开头的相对路径,只要路由层级发生变化就会出现404问题,优先使用根路径开头的绝对路径,或者全局变量统一管理资源前缀,方便后续环境迁移、目录调整。
内容的提问来源于stack exchange,提问作者poison pawn

