Я использую Webpack для создания проекта Angular 1.4. В проекте используется несколько плагинов jQuery, которые завернуты в директивы Angular. Эти директивы внутренне используют angular.element
, вероятно, подразумевая, что angular.элемент - это реальный jQuery, а не jqLite.
Я хочу, чтобы Angular автоматически обнаруживал jQuery и использовал его вместо jqLite. Я попытался локально найти jquery в моем модуле точки входа app.js
: require('jquery')
и разоблачить jQuery глобально с помощью require(expose?$!expose?jQuery!jquery)
.
Тем не менее, что бы я ни делал, angular.element
относится к jqLite.
Мои исследования привели к нескольким выводам:
- Даже если импортировано как модуль CommonJS, Angular присваивает себя глобальной переменной
window.angular
, поэтому мне не нужноexpose
его с помощью Webpack: Does Angular присваивается `window.angular` глобально при загрузке в качестве модуля CommonJS?. - ProviderPlugin, похоже, не выполняет трюк: он не предоставляет jQuery для глобального пространства имен; вместо этого для каждого модуля, который зависит от глобального имени jQuery, он вставляет
require('jquery')
в него. Я не уверен на 100%, но выглядит как Angular не получает доступ кjQuery
из глобального пространства имен напрямую, вместо этого он пытается получить доступ кwindow.jQuery
вbindJQuery
, поэтому этот подход не помогает: Открыть jQuery для реального объекта Window с помощью Webpack. - По той же причине, что и 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. - Было предложено использовать синтаксис
import
вместо синтаксисаrequire
с jquery:import "jquery"
илиimport $ from "jquery"
, а неrequire(jquery)
: (Петр Аверьянов: Как использовать синтаксис загрузчиков Webpack (импорт/экспорт/публикация) с помощью импорта ECMAScript 6?). Исходный код jquery обернут специальной оболочкой, которая idenitizes как требуется jquery (с AMD/require, CommonJS или глобально с оператором<script>
), Исходя из этого, он устанавливает специальный аргументnoGlobal
для jquery fabric и либо создаетwindow.jQuery
, либо нет, основываясь на значенииnoGlobal
. Начиная с jQuery 2.2.4, послеimport "jquery"
noGlobal === true
иwindow.jQuery
не создается. IIRC, некоторые более старые версии jquery не распозналиimport
как импорт CommonJS и добавилиimport
ed jquery в глобальное пространство имен, что позволило использовать Angular.
Подробности: здесь 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"
});
});