Webpack:如何制作角度自动检测jQuery并将其用作angular.element而不是jqLite? [英] Webpack: how to make angular auto-detect jQuery and use it as angular.element instead of jqLite?
问题描述
我正在使用Webpack构建Angular 1.4项目.该项目使用了多个jQuery插件,这些插件被包装到angular指令中.这些指令在内部使用angular.element
,可能暗示angular.element是真正的jQuery,而不是jqLite.
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并使用它而不是jqLite.我试图在我的入口点模块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
都指向jqLite.
Still, whatever I do, angular.element
refers to jqLite.
我的研究得出了一些发现:
My research resulted in several findings:
- 即使将其作为CommonJS模块导入,Angular也会将其自身分配给全局变量
window.angular
,所以我不需要使用Webpack对其进行expose
:使用Webpack将jQuery暴露给真实的Window对象. - 出于与ProviderPlugin相同的原因,
imports-loader
似乎不合适:Angular需要window.jQuery
,而不仅仅是jQuery
. - 使用
expose-loader
,jquery使其进入窗口对象.我的问题是Babel将所有导入都提升到了所得代码中的模块顶部.因此,尽管在源文件中require(expose?jquery!jquery)
在import angular from "angular"
之前,但捆绑包require("angular")
在文件的顶部,在jquery之前,因此在导入Angular时,jquery尚不可用.我想知道如何将Webpack加载程序与ECMA6导入语法一起使用. - 有人建议在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 === true
和window.jQuery
时创建. IIRC,某些旧版本的jquery无法将import
识别为CommonJS导入,并向全局名称空间添加了import
ed的jquery,从而允许angular使用它.
- Even when imported as a CommonJS module, Angular assigns itself to a global variable
window.angular
, so I don't need toexpose
it with Webpack: Does Angular assign itself to `window.angular` globally, when loaded as CommonJS module?. - 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 accessjQuery
from global namespace directly, instead, it tries to accesswindow.jQuery
inbindJQuery
function, so this approach doesn't help: Expose jQuery to real Window object with Webpack. - For the same reason as ProviderPlugin,
imports-loader
seems unfit: Angular wantswindow.jQuery
, not justjQuery
. - 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, althoughrequire(expose?jquery!jquery)
was beforeimport angular from "angular"
in source files, in bundlerequire("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. - There was a suggestion to use
import
syntax instead ofrequire
syntax with jquery:import "jquery"
orimport $ from "jquery"
, notrequire(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 argumentnoGlobal
for jquery fabric and either createswindow.jQuery
or not, based on the value ofnoGlobal
. As of jquery 2.2.4, uponimport "jquery"
noGlobal === true
andwindow.jQuery
is not created. IIRC, some older versions of jquery didn't recognizeimport
as CommonJS import and addedimport
ed 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 forjQuery
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 thewindow
. Neat huh?
这篇关于Webpack:如何制作角度自动检测jQuery并将其用作angular.element而不是jqLite?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!