jQuery.ui requirejs 优化后未定义

jQuery.ui undefined after requirejs optimization

我的 Web 应用程序中有几个 JavaScript 文件,这些文件以前是通过 <script> 标记加载的,按照相关依赖项的顺序。现在,我正在通过 require.js 重新组织它们,以便为生产积累和缩小它们。

首先,我想简单地将所有文件加载到全局 (window) 上下文中,还没有 AMD 封装:

require([
    'jquery'], function() {
    require([
        'jquery-ui'], function() {
        require([
            'jquery-ui.touch-punch',
            // [...]
        ]);
    });
});

这里的思路是'jquery'定义一个全局(window上下文)jQuery变量,'jquery-ui'设置jQuery.ui'jquery-ui.touch-punch'更改 jQuery.ui(以获得更好的触摸支持)。

这在 运行 原样时效果很好,即没有优化。但是,在编译成一个文件并使用 RequireJS optimizer 缩小后,出现以下错误:

Uncaught TypeError: Cannot read property 'mouse' of undefined

这发生在试图访问 jQuery.ui.mouse 的线路上。

在浏览器控制台中,jQuery 已在 window 上下文中正确设置,但 jQuery.ui 未定义。 但是,手动执行 require(['jquery-ui']) 会按预期设置 jQuery.ui

优化后 jQuery UI 的行为似乎有所不同,但我看不出具体情况或原因。我做错了什么?

独家新闻

使用 shim 设置非 AMD 模块之间的依赖关系,而不是通过嵌套的 require 调用(实际上不设置依赖关系)。还要确保在您提供的配置中使用 wrapShim: true r.js.

说明

您尝试加载的一个或多个模块不是 AMD 模块,但您实际上并未定义非 AMD 模块之间的依赖关系。

当您嵌套 require 调用时,您会强制某些模块在 运行 时加载的顺序,但这实际上并没有在模块之间建立依赖关系。因此,只要模块未优化,此策略就有效,但可能在优化后失败。

建立依赖关系只有两种方式:

  1. 通过将一组依赖项传递给 define 调用。实际为 AMD 规范编写的模块使用此方法。 (RequireJS 也支持使用 CommonJS 的方式来请求模块,但在幕后,它被转换为一个 define 带有依赖数组的调用。所以它不构成第三种方式。)

  2. 通过设置 shim 来列出依赖项。此方法适用于非 AMD 模块。

如果您没有设置 shim,那么优化器可以自由地按照它想要的顺序对非 AMD 模块进行排序。 jquery-ui.touch-punch 可以出现在优化文件中的jquery-uijquery之前,因为没有理由不应该,然后你会运行陷入困境。如果您查看此插件的代码,您会发现它不是 AMD 感知的。它只是期望 jQuery 和 jQuery UI 存在,如果它们不存在就会失败。

当您设置 shim 时,您会强制优化文件中非 AMD 模块的顺序。

您需要 wrapShim,因为 jquery-ui.touch-punch 在使用 jQuery UI 的 AMD 感知版本时。否则,jQuery UI 的工厂在插件需要它之前不会是 运行。