Я использую 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-loaderjquery делает это объекту окна.. Моя проблема заключалась в том, что 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 и добавилиimported 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"
});
});