Webpack: jak sprawić, by jQuery automatycznie wykrywał kąty i używać go jako angular.element zamiast jqLite?


Używam Webpack do tworzenia projektu Angular 1.4. Projekt wykorzystuje kilka wtyczek jQuery, które są opakowane w dyrektywy kątowe. Dyrektywy te używają wewnętrznie
angular.element
, prawdopodobnie sugerując, że angular.element jest prawdziwym jQuery, a nie jqLite.
Chcę, aby kątowy automatycznie wykrywał jQuery i używał go zamiast jqLite. Próbowałem wymagać jquery lokalnie w moim module
app.js
:
require ('jquery')
i udostępniać jQuery globalnie za pomocą
require (expose? $! Expose? jQuery! jquery)
.
A jednak cokolwiek robię,
angular.element
odnosi się do jqLite.
Moje badania doprowadziły do ​​kilku wniosków:
  • Nawet przy imporcie, gdy moduł kątowy CommonJS przypisuje samą zmienną globalną okno.Andicular , więc nie potrzebuję
    Expose
    It ze WebPack: Czy Angular przypisuje się globalnie do `window.angular 'po załadowaniu jako moduł CommonJS https://coderoad.ru/36101119/ .
  • ProviderPlugin nie wydaje się działać: nie zapewnia jQuery globalnej przestrzeni nazw; zamiast tego dla każdego modułu, który zależy od globalnej nazwy jQuery, wstawia do niego
    require ('jquery')
    . Nie jestem w 100% pewien, ale wygląda na to, że Angular nie uzyskuje dostępu do
    jQuery
    bezpośrednio z globalnej przestrzeni nazw, zamiast tego próbuje uzyskać dostęp do
    window.jQuery
    w funkcji
    bindJQuery
    , więc to podejście nie pomaga: wystawiaj jQuery na rzeczywisty obiekt okna za pomocą webpacka https://coderoad.ru/29080148/ .
  • Z tego samego powodu co ProviderPlugin,
    import-loader
    wydaje się bezużyteczny: Angular chce
    window.jQuery
    , a nie tylko
    jQuery
    .
  • Z
    expose-loader
    jquery dostaje się do obiektu okna.
    Mój problem polegał na tym, że Babel wypychał wszystkie swoje importy na górę modułu w wynikowym kodzie. Dlatego chociaż
    require (expose Jquery! Jquery)
    był przed
    importem angular z „angular”
    w plikach źródłowych, pakiet
    require („angular”)
    znajduje się na początku pliku, przed jquery, więc zanim Angular zostanie zaimportowany, jquery nie będzie jeszcze dostępne. Zastanawiasz się, jak używać programów ładujących Webpack ze składnią importu ECMA6 [/code]
  • Pojawiła się sugestia, aby użyć składni
    import
    zamiast składni
    require
    z jquery:
    import "jquery"
    lub
    import $ from " jquery ”
    , a nie
    require (jquery)
    : (Petr Averyanov: jak używać składni programu ładującego webpack (import/eksport/ekspozycja) z importami ECMAScript 6 https://coderoad.ru/36150641/Źródło ). jQuery. zapakowane w specjalną powłokę https://github.com/jquery/jque ... 23L41który określa, jak wymagane jest jquery (przy użyciu instrukcji AMD/require, CommonJS lub globalnie przy użyciu instrukcji
    & < script & >
    ). Na tej podstawie ustawia specjalny argument
    noGlobal
    dla tkaniny jquery i albo tworzy
    window.jQuery
    , albo nie jest oparty na wartości
    noGlobal
    . Od wersji jquery 2.2.4,
    import "jquery"
    noGlobal === true
    i
    window.jQuery
    nie są generowane. IIRC, niektóre starsze wersje jquery nie rozpoznawały
    import
    jako CommonJS import i dodały
    import
    ed jquery do globalnej przestrzeni nazw, co pozwoliło mu na użycie go przez angular.

Szczegóły: Oto mój 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"
});
});

Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Otrzymałem tę odpowiedź od

Jonah-Reilly
https://stackoverflow.com/users/761388/john-reilly
:
Tajemniczy przypadek webpacka angular i jquery
http://blog.johnnyreilly.com/2 ... .html
odpowiedź spongebob
https://stackoverflow.com/users/1554165/bob-sponge
nie do końca poprawne - wtyczka Provide faktycznie zastępuje tekst w przetwarzanych przez siebie modułach, więc musimy dostarczyć
window.jQuery
(którego szuka angular), a nie tylko
jQuery . 

W swoim
webpack.config.js
musisz dodać
następujący wpis w twoich wtyczkach:

new webpack.ProvidePlugin({
"window.jQuery": "jquery"
}),
To używa pakietu webpack

ProvidePlugin
https://github.com/webpack/doc ... lugin
i w tej chwili
Webpakacja (© 2016 John Reilly), wszystkie linki w kodzie
Okno.jQuery zostanie zastąpione linkiem do modułu
webpack zawierający jQuery. Więc kiedy spojrzysz na połączony plik, zobaczysz
że kod sprawdzający obiekt
window
pod kątem
jQuery
stał się
lubię to:

jQuery = isUndefined(jqName) ?
__webpack_provided_window_dot_jQuery :// use jQuery (if present)
!jqName ? undefined :// use jqLite
window[jqName];// use jQuery specified by `ngJq`
Prawda; webpack dostarcza Angular jQuery, ale nadal

nie

umieszcza zmienną
jQuery
w
window
. Schludnie, co?
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


!! Aktualizacja
>
Oczywiście w przykładzie ES6 nadal musisz używać commonJs require for angular.
import $ from "jquery"window.$ = $;
window.jQuery = $;var angular = require("angular");

poniżej znajduje się oryginalna odpowiedź
Chcę znaleźć prostsze rozwiązanie. Po prostu ustaw jQuery jako okno globalne, aby angular mógł je rozpoznać:
var $ = require("jquery")window.$ = $;
window.jQuery = $;var angular = require("angular");

lub w twoim przypadku (

przestarzały

):
import $ from "jquery"window.$ = $;
window.jQuery = $;import angular from "angular";

Mam nadzieję, że to pomoże :)
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

W twoim przypadku lepiej jest użyć

ProvidePlugin
http://webpack.github.io/docs/ ... in... Po prostu dodaj te linie do konfiguracji swojego webpacka w sekcji wtyczek, a jquery będzie dostępne w Twojej aplikacji:
new webpack.ProvidePlugin({
"$": "jquery",
"jQuery": "jquery"
})
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Daję więc decyzję, która faktycznie reprezentuje Masha z @BobSponge Answers i @ BOB's Tips/Comments. Więc nic nie jest oryginalne, wystarczy pokazać, co działa dla mnie (w projekcie, który nie używa Babel/ES6, BTW) i próbuje wyjaśnić, dlaczego to działa ...
(Ostatnią) sztuczką jest naprawdę użycie

ekspozycja ładowarki
https://github.com/webpack/expose-loader
.
Jak wyjaśniono na ich stronie, musimy wprowadzić
module.loaders
:
{ test: require.resolve("jquery"), loader: "expose?$!expose?jQuery" },

Ponadto na liście
plugins
mam:
new webpack.ProvidePlugin( {
$: 'jquery',
jQuery: 'jquery',
_: 'lodash',
// [...] some other libraries that put themselves in the global scope.
//angular: 'angular',// No, I prefer to require it everywhere explicitly.
}),

który faktycznie znajduje globalne wystąpienia tych zmiennych w kodzie i wymaga ich w zmiennych lokalnych dla każdego modułu. Ułatwia to migrację istniejącego projektu (z RequireJS do Webpack), tak jak ja ...
Myślę, że możemy obejść się bez tej wtyczki, jeśli wolisz być wyraźny w imporcie.
I, co ważne (tak mi się wydaje), na początku aplikacji wymagam ich w takiej kolejności, w jakiej chcę. W moim przypadku zrobiłem dostawcę pakietu, więc jest to zamówienie w tym pakiecie.
require('jquery');require('lodash');
// [...]var angular = require('angular');
// Use the angular variable to declare the app module, etc.

WebPack doda biblioteki do odpowiedniego pakietu w kolejności, w jakiej widzi wymagać S (chyba że używasz wtyczki/ładowarki, która je ponownie).
Ale import jest izolowany (brak globalnego wycieku), więc Angular nie mógł zobaczyć biblioteki jQuery. Stąd potrzeba
expose
. (Próbowałem zamiast tego
window.jQuery = require ('jquery');
, ale to nie zadziałało, może być za późno.)
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jest jeden japoński artykuł, w którym

chcę używać jQuery a nie jQLite w webpacku + AngularJS,
http://qiita.com/cither/items/ ... %25A8
który wydaje się mówić o tym samym problemie (nawiasem mówiąc, jeszcze nie znam japońskiego). Użyłem google do tłumaczenia na język angielski, kredyty idą do

cytrus
http://qiita.com/cither
za tę dobrą odpowiedź.
Oferuje cztery sposoby rozwiązania tego problemu:
  • Przypisz bezpośrednio do okna (niezbyt fajne)
    window.jQuery = require('jquery');var angular = require('angular');console.log(angular.element('body'));//[body, prevObject: jQuery.fn.init[1], context: document, selector: "body"]
  • Posługiwać się expose-loader https://github.com/webpack/exp ... bpack(dobrze, ale nie tak fajnie)
    npm install --saveDev expose-loader
    webpack.config.js
    module.exports = { entry: "./index", output: { path: __dirname, filename: "bundle.js" }, module: { loaders: [{ test:/\/jquery.js$/, loader: "exposejQuery" }] }};
    za pomocą:
    require('jquery');var angular = require('angular');console.log(angular.element('body'));//[body, prevObject: jQuery.fn.init[1], context: document, selector: "body"]
  • Posługiwać się Odsłoń ładowarkę https://github.com/webpack/exp ... bpack(to jest lepsze)
    npm install --saveDev expose-loader
    webpack.config.js
    module.exports = { entry: "./index", output: { path: __dirname, filename: "bundle.js" }, module: { loaders: [{ test:/\/angular\.js$/, loader: "importsjQuery=jquery" }, { test:/\/jquery.js$/, loader: "exposejQuery" }] }};
    za pomocą:
    var angular = require('angular');console.log(angular.element('body'));//[body, prevObject: jQuery.fn.init[1], context: document, selector: "body"]
  • Posługiwać się ProvidePlugin https://webpack.github.io/docs ... lugin(najlepszym rozwiązaniem) W rzeczywistości jest taki sam jak Jest zwyczajowy, aby odpowiedzieć tutaj studiów. https://stackoverflow.com/a/38785528/1092815
    module.exports = { entry: "./index", output: { path: __dirname, filename: "bundle.js" }, plugins: [ new webpack.ProvidePlugin({ "window.jQuery": "jquery" }) ],};
    za pomocą:
    var angular = require('angular');console.log(angular.element('body'));//[body, prevObject: jQuery.fn.init[1], context: document, selector: "body"]

Pomyślałem, że podzielę się tym tutaj, ponieważ mieliśmy dokładnie ten sam problem. W naszym projekcie z powodzeniem wykorzystaliśmy rozwiązanie
expose-loader
. Przypuszczam, że
ProvidePlugin
, który wstrzykuje jquery bezpośrednio do
window
, również jest dobrym pomysłem.

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się