系统升级后JS报autocomplete未定义、匿名define模块不匹配错误求助
根因说明
两个报错是强关联的,核心问题出在你贴的这段autocomplete代码用的是标准UMD通用模块封装,它的环境判断逻辑有固定优先级:
- 优先判断是否为CommonJS环境(存在
exports和module对象),是就将模块导出到module.exports - 其次判断是否为AMD环境(存在
define函数且define.amd为真),是就调用define注册AMD模块 - 只有前两个环境都不匹配时,才会把
autocomplete函数挂载到全局window对象上
你遇到的Mismatched anonymous define() module错误,说明系统升级后页面里提前加载了RequireJS这类AMD加载器,全局已经存在define函数,但autocomplete是直接通过普通<script>标签引入的,没有走AMD规范的模块加载流程:
- UMD代码检测到
define存在,直接进入AMD分支调用define(factory) - 普通脚本标签引入的匿名模块不符合AMD加载规则,直接抛出define不匹配的错误
- 因为JS脚本抛错后会中断当前执行上下文的后续逻辑,原本负责把autocomplete挂到全局的代码根本没执行,自然会抛出
autocomplete is not defined的错误。
升级前能正常运行,基本就是因为之前页面里没有提前注入AMD加载器,UMD判断直接走了全局挂载分支。
排查步骤
- 检查页面脚本加载顺序:确认autocomplete脚本执行前,是否已经加载了RequireJS或其他实现AMD规范的加载器,生成了全局
define变量 - 检查autocomplete的引入方式:是否没有通过AMD的
require方法加载,而是直接写了普通script标签引入 - 检查是否存在脚本重复加载、全局变量污染的情况:有没有其他脚本篡改了
define变量的状态
可落地解决方案
按需选一个即可:
- 方案1:适配AMD加载规范(推荐,和现有模块体系兼容)
如果页面确实用RequireJS做模块管理,就去掉autocomplete的普通script引入,把autocomplete文件路径加到RequireJS配置中,在使用时通过require回调拿到实例再调用:require.config({ paths: { autocomplete: 'autocomplete文件的实际存放路径' } }) require(['autocomplete'], function(autocomplete) { // 在此处调用autocomplete即可,不会再有未定义问题 autocomplete({ // 你的原有配置参数 }) }) - 方案2:修改UMD判断逻辑,强制走全局挂载(改造成本最低)
如果不想调整现有模块加载逻辑,直接修改autocomplete的UMD头部代码,删掉AMD判断分支,强制把函数挂到全局,把开头的UMD块替换成下面的代码即可,后面的业务逻辑完全不用改:
改完之后无论页面有没有AMD加载器,都不会走define分支,行为和升级前完全一致。<script type="text/javascript"> (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : (global = global || self, global.autocomplete = factory()); } (this, function () { 'use strict'; /* * autocomplete组件 * Copyright (c) 2016 Denys Krasnoshchok * MIT License */ function autocomplete(settings) { // 后续原有逻辑保持不变 - 方案3:调整脚本加载顺序(临时快速修复)
把引入autocomplete的script标签移到所有AMD加载器脚本的前面,这样autocomplete执行时全局还没有define变量,会直接走全局挂载分支,后续加载器初始化也不会影响已经挂载到window的autocomplete函数。
注意:如果后续有代码尝试通过AMD方式引入autocomplete,这个方案会导致模块重复加载,只适合临时救急用。
内容的提问来源于stack exchange,提问作者Ray Meyer
相关产品推荐
相关产品推荐

