如何通过Symfony AssetMapper将jQuery导入为全局变量?
之前用Webpack Encore时,通过{{ encore_entry_script_tags('add-food') }}就能把脚本正确加到模板里,换用AssetMapper后完全摸不着门路,现在浏览器控制台一直报$ is not defined at add-food-81afe070e8be2f50bb5e13fa8d7573cf.js:1:1的错误,试了好几种方法都没用,到底漏了什么?
当前环境配置
../assets/vendor/installed.php
// ... 'jquery' => array ( 'version' => '3.7.1', 'dependencies' => //...
../assets/app.js
import './bootstrap.js'; import './styles/app.css' import './styles/jquery-ui.min.css' import 'bootstrap/dist/css/bootstrap.min.css'; import './add-food.js'; import jquery from 'jquery'; const $ = jquery; window.$ = $;
base.html.twig
{# ... #} {% block javascripts %} {% block importmap %}{{ importmap('app') }}{% endblock %} {% endblock %} {# ... #}
问题原因与解决方法
问题核心在于加载顺序和ES模块的作用域隔离:
调整脚本加载顺序
你现在先导入了add-food.js,之后才把$挂载到全局,导致add-food.js执行时全局$还不存在。把依赖jQuery的脚本移到全局挂载之后:import './bootstrap.js'; import './styles/app.css' import './styles/jquery-ui.min.css' import 'bootstrap/dist/css/bootstrap.min.css'; // 先挂载全局jQuery import jquery from 'jquery'; const $ = jquery; window.$ = $; window.jQuery = $; // 可选,部分插件依赖全局jQuery变量 // 再导入依赖jQuery的脚本 import './add-food.js';适配AssetMapper的ES模块特性
AssetMapper默认以ES模块方式加载脚本,每个文件都是独立作用域。如果add-food.js没有通过import引入jQuery,必须确保全局$在它执行前已经存在——上面的顺序调整就是解决这个问题。确认importmap配置正确
运行php bin/console importmap:install,确保jQuery已经被正确加入到importmap中,这样import jquery from 'jquery'才能正常解析。处理非ES模块的第三方脚本
如果add-food.js是传统非模块脚本(比如IIFE格式),可以把它放到public/assets目录下,在模板的importmap区块之后通过{{ asset('assets/add-food.js') }}手动引入;或者用php bin/console importmap:require add-food.js命令将其转为模块兼容形式。
内容的提问来源于stack exchange,提问作者geoB

