Webpack:如何制作角度自动检测jQuery并将其用作angular.element而不是jqLit​​e? [英] Webpack: how to make angular auto-detect jQuery and use it as angular.element instead of jqLite?

查看:67
本文介绍了Webpack:如何制作角度自动检测jQuery并将其用作angular.element而不是jqLit​​e?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using Webpack to build an Angular 1.4 project. The project makes use of several jQuery plugins, which are wrapped into angular directives. Those directives internally use angular.element, probably implying that angular.element is the real jQuery, not jqLite.

我想要angular自动检测jQuery并使用它而不是jqLit​​e.我试图在我的入口点模块app.js:require('jquery')中本地要求使用jquery,并使用require(expose?$!expose?jQuery!jquery)在全球范围内公开jQuery.

I want angular to auto-detect jQuery and use it instead of jqLite. I tried to require jquery locally in my entry point module app.js: require('jquery') and to expose jQuery globally with require(expose?$!expose?jQuery!jquery).

无论如何,angular.element都指向jqLit​​e.

Still, whatever I do, angular.element refers to jqLite.

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

My research resulted in several findings:

  1. 即使将其作为CommonJS模块导入,Angular也会将其自身分配给全局变量window.angular,所以我不需要使用Webpack对其进行expose:使用Webpack将jQuery暴露给真实的Window对象.
  2. 出于与ProviderPlugin相同的原因,imports-loader似乎不合适:Angular需要window.jQuery,而不仅仅是jQuery.
  3. 使用expose-loader,jquery使其进入窗口对象.我的问题是Babel将所有导入都提升到了所得代码中的模块顶部.因此,尽管在源文件中require(expose?jquery!jquery)import angular from "angular"之前,但捆绑包require("angular")在文件的顶部,在jquery之前,因此在导入Angular时,jquery尚不可用.我想知道如何将Webpack加载程序与ECMA6导入语法一起使用.
  4. 有人建议在jquery中使用import语法而不是require语法:import "jquery"import $ from "jquery",而不是require(jquery) :( Petr Averyanov:用特殊包装器包裹的,确定如何需要jquery(使用AMD/require,CommonJS或全局使用<script>语句).基于此,它为jquery fabric设置一个特殊的参数noGlobal,并根据noGlobal的值创建或不创建window.jQuery.从jquery 2.2.4开始,不会在import "jquery" noGlobal === truewindow.jQuery时创建. IIRC,某些旧版本的jquery无法将import识别为CommonJS导入,并向全局名称空间添加了import ed的jquery,从而允许angular使用它.
  1. Even when imported as a CommonJS module, Angular assigns itself to a global variable window.angular, so I don't need to expose it with Webpack: Does Angular assign itself to `window.angular` globally, when loaded as CommonJS module?.
  2. ProviderPlugin doesn't seem to do the trick: it doesn't expose jQuery to global namespace; instead, for every module that depends on global name jQuery, it inserts require('jquery') in it. I'm not 100% sure, but looks like Angular doesn't access jQuery from global namespace directly, instead, it tries to access window.jQuery in bindJQuery function, so this approach doesn't help: Expose jQuery to real Window object with Webpack.
  3. For the same reason as ProviderPlugin, imports-loader seems unfit: Angular wants window.jQuery, not just jQuery.
  4. With expose-loader, jquery makes it to the window object. My problem was that Babel hoists all of its imports to the top of module in the resulting code. Hence, although require(expose?jquery!jquery) was before import angular from "angular" in source files, in bundle require("angular") is at the top of the file, before jquery, so by the time Angular is imported, jquery is not yet available. I wonder, how to use Webpack loaders with ECMA6 import syntax.
  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.


详细信息:这是我的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"
      });
});

推荐答案

john-reilly 得到了这个答案:
webpack的神秘案例jQuery

Got this answer from john-reilly:
The mysterious case of webpack angular and jquery

bob-sponge 的答案不太正确-Provide插件实际上是在它要处理的模块,因此我们需要提供window.jQuery(这是angular所需要的),而不仅仅是提供jQuery.

bob-sponge's answer is not quite right - the Provide plugin is actually doing a text replacement on modules it processes, so we need to provide window.jQuery (which is what angular is looking for) and not just jQuery.

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

In your webpack.config.js you need to add the following entry to your plugins:

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

这将使用webpack ProvidePlugin ,的 webpackification(©2016 John Reilly)代码中的所有引用 window.jQuery将替换为对webpack模块的引用 包含jQuery.因此,当您查看捆绑的文件时,您会看到 检查window对象是否为jQuery的代码已变为 这个:

This uses the webpack ProvidePlugin and, at the point of webpackification (© 2016 John Reilly) all references in the code to window.jQuery will be replaced with a reference to the webpack module that contains jQuery. So when you look at the bundled file you'll see that the code that checks the window object for jQuery has become this:

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

是的; webpack在仍然为Angular提供jQuery的同时 jQuery变量放置到window上.整齐吧?

That's right; webpack is providing Angular with jQuery whilst still not placing a jQuery variable onto the window. Neat huh?

这篇关于Webpack:如何制作角度自动检测jQuery并将其用作angular.element而不是jqLit​​e?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆