Webpack:如何使角度自动检测jQuery并将其用作angular.element而不是jqLit​​e?

jquery Webpack

阿飞

2020-03-24

我正在使用Webpack构建Angular 1.4项目。该项目使用了多个jQuery插件,这些插件被包装到angular指令中。这些指令在内部使用angular.element,可能暗示angular.element是真正的jQuery,而不是jqLit​​e。

我想要angular自动检测jQuery并使用它代替jqLit​​e。我试图在本地需要的jquery我的入口点模块app.jsrequire('jquery')并与全球范围内暴露的jQuery require(expose?$!expose?jQuery!jquery)

无论如何,我所做的都是angular.element指jqLit​​e。


我的研究得出了一些发现:

  1. 即使当作为CommonJS模块导入时,Angular也会将自己分配给全局变量window.angular,所以我不需要exposeWebpack:当作为CommonJS模块加载时,Angular是否会将自己分配给全局的`window.angular`吗?
  2. ProviderPlugin似乎无法解决问题:它不会将jQuery公开给全局名称空间;相反,对于依赖于全局名称jQuery的每个模块,它都会插入require('jquery')其中。我不确定100%,但是看起来Angular不会jQuery直接从全局名称空间访问,而是尝试window.jQuerybindJQuery函数中访问,因此这种方法无济于事:使用Webpack将jQuery暴露给真实的Window对象
  3. 由于与ProviderPlugin相同的原因,它imports-loader似乎不适合:Angular想要window.jQuery而不仅仅是jQuery
  4. 使用expose-loader,jquery使其进入window对象。我的问题是Babel将所有导入都提升到结果代码中模块的顶部。因此,尽管源文件中的包require(expose?jquery!jquery)之前import angular from "angular",捆绑包中的包 require("angular")位于文件顶部,jquery之前,所以在导入Angular时,jquery尚不可用。我想知道如何将Webpack加载程序与ECMA6导入语法一起使用。
  5. There was a suggestion to use import syntax instead of require syntax with jquery: import "jquery" or import $ from "jquery", not require(jquery): (Petr Averyanov: How to use Webpack loaders syntax ( imports/exports/expose) with ECMAScript 6 imports?). jquery source code is wrapped with a special wrapper, which idenitifies how jquery is required (with AMD/require, CommonJS or globally with <script> statement). Based on that it sets a special argument noGlobal for jquery fabric and either creates window.jQuery or not, based on the value of noGlobal. As of jquery 2.2.4, upon import "jquery" noGlobal === true and window.jQuery is not created. IIRC, some older versions of jquery didn't recognize import as CommonJS import and added imported jquery to global namespace, which allowed angular to use it.

Details: here's my app.js:

'use strict';

require("expose?$!expose?jQuery!jquery");
require("metisMenu/dist/metisMenu");
require("expose?_!lodash");
require("expose?angular!angular");

import angular from "angular";
import "angular-animate";
import "angular-messages";
import "angular-resource";
import "angular-sanitize";
import "angular-ui-router";
import "bootstrap/dist/css/bootstrap.css";
import "font-awesome/css/font-awesome.css";
import "angular-bootstrap";

require("../assets/styles/style.scss");
require("../assets/fonts/pe-icon-7-stroke/css/pe-icon-7-stroke.css");

// Import all html files to put them in $templateCache
// If you need to use lazy loading, you will probably need
// to remove these two lines and explicitly require htmls
const templates = require.context(__dirname, true, /\.html$/);
templates.keys().forEach(templates);

import HomeModule from "home/home.module";
import UniverseDirectives from "../components/directives";

angular.module("Universe", [
    "ngAnimate",
    "ngMessages",
    "ngResource",
    "ngSanitize",
    "ui.router",
    "ui.bootstrap",

    HomeModule.name,
    UniverseDirectives.name,
])
.config(function($urlRouterProvider, $locationProvider, $stateProvider){
    // $urlRouterProvider.otherwise('/');

    // $locationProvider.html5Mode(true);

    $stateProvider
      .state('test', {
        url: "/test",
        template: "This is a test"
      });
});

第3639篇《Webpack:如何使角度自动检测jQuery并将其用作angular.element而不是jqLit​​e?》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

3个回答
西里Near 2020.03.24

john-reilly获得了这个答案
webpack angular和jquery的神秘案例

bob-sponge的答案不太正确-Provide插件实际上是在其处理的模块上进行文本替换,因此我们需要提供window.jQuery(而不仅仅是angular所寻求的)jQuery

在您webpack.config.js需要将以下条目添加到您的插件:

new webpack.ProvidePlugin({
    "window.jQuery": "jquery"
}),

本品采用的WebPack ProvidePlugin,并在webpackification点(©2016约翰·赖利)将到包含的jQuery的的WebPack模块的引用来代替在代码中window.jQuery所有引用。因此,当您查看捆绑的文件时,您会看到检查window对象的代码jQuery已变为:

jQuery = isUndefined(jqName) ?
  __webpack_provided_window_dot_jQuery : // use jQuery (if present)
    !jqName ? undefined : // use jqLite
    window[jqName]; // use jQuery specified by `ngJq`

那就对了; 的WebPack被提供角度与jQuery同时仍然 放置一个jQuery可变到window整洁吧?

古一 2020.03.24

!!更新

显然,在ES6示例中,您仍然需要使用commonJs对角度的要求。

import $ from "jquery"

window.$ = $;
window.jQuery = $;

var angular = require("angular");

以下是原始答案



我想要一个更简单的解决方案。只需将jQuery设置为全局窗口,以便angular可以识别它:

var $ = require("jquery")

window.$ = $;
window.jQuery = $;

var angular = require("angular");

或您的情况(已过期):

import $ from "jquery"

window.$ = $;
window.jQuery = $;

import angular from "angular";

我希望这有帮助 :)

Stafan路易 2020.03.24

在您的情况下,最好使用ProvidePlugin只需将此行添加到插件部分的webpack配置中,jquery将在您的应用中可用:

    new webpack.ProvidePlugin({
         "$": "jquery",
         "jQuery": "jquery"
    })

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android