Webpackを使用してAngular 1.4プロジェクトをビルドしています。このプロジェクトは、angularディレクティブにラップされたいくつかのjQueryプラグインを使用します。これらのディレクティブは内部的にangular.element
を使用します。これはおそらく、angle.elementがjqLiteではなく実際のjQueryであることを意味します。
angularでjQueryを自動検出し、jqLiteの代わりに使用するようにします。エントリポイントモジュールapp.js
:require('jquery')
でローカルにjqueryを要求し、require(expose?$!expose?jQuery!jquery)
でjQueryをグローバルに公開しようとしました。
それでも、私が何をするにしても、angular.element
はjqLiteを指します。
私の研究の結果、いくつかの発見がありました。
window.angular
に自身を割り当てるため、Webpackでexpose
する必要はありません。 Does Angular CommonJSモジュールとしてロードされた場合、自身をグローバルに `window.angular`に割り当てますか? 。require('jquery')
を挿入します。私は100%確信していませんが、Angularはグローバル名前空間からjQuery
に直接アクセスしないように見えますが、代わりにbindJQuery
関数でwindow.jQuery
にアクセスしようとするので、このアプローチは役に立ちません: WebpackでjQueryを実際のWindowオブジェクトに公開 。imports-loader
は不適切と思われます。Angularは、jQuery
だけでなく、window.jQuery
を必要とします。expose-loader
を使用すると、jqueryはウィンドウオブジェクトになります。私の問題は、Babelがすべてのインポートをモジュールの最上部に引き上げることでした結果のコード。したがって、ソースファイルではrequire(expose?jquery!jquery)
はimport angular from "angular"
の前にありましたが、バンドルではrequire("angular")
がファイルの先頭、jqueryの前にあるため、Angularがインポートされるまでに、jqueryはまだ利用できません。私は、ECMA6インポート構文でWebpackローダーを使用する方法を疑問に思います。import
構文の代わりにrequire
構文を使用することが提案されました:require(jquery)
ではなくimport "jquery"
またはimport $ from "jquery"
:(Petr Averyanov: Webpackローダー構文の使用方法/ exports/expose)ECMAScript 6インポート? )。 jqueryソースコードは 特別なラッパーでラップ で、jqueryの必要性を特定します(AMD/require、CommonJS、または<script>
ステートメントでグローバルに)。それに基づいて、jqueryファブリックに特別な引数noGlobal
を設定し、noGlobal
の値に基づいてwindow.jQuery
を作成するかどうかを決定します。 jquery 2.2.4の時点では、import "jquery"
noGlobal === true
およびwindow.jQuery
は作成されていません。 IIRC、jqueryの一部の古いバージョンは、import
をCommonJSインポートとして認識せず、import
ed jqueryをグローバル名前空間に追加し、angularが使用できるようにしました。詳細:ここに私の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 angular and jquery)の神秘的なケース
bob-sponge の答えは正しくありません-Provideプラグインは、処理するモジュールで実際にテキスト置換を行っているため、window.jQuery
(angularが探しているもの)であり、jQuery
だけではありません。
あなたの
webpack.config.js
プラグインに次のエントリを追加する必要があります。
new webpack.ProvidePlugin({
"window.jQuery": "jquery"
}),
これはwebpack ProvidePlugin を使用し、webpackification(©2016 John Reilly)の時点で、window.jQueryへのコード内のすべての参照は、jQueryを含むwebpackモジュールへの参照に置き換えられます。バンドルされたファイルを見ると、
window
のjQuery
オブジェクトをチェックするコードが次のようになっていることがわかります。
jQuery = isUndefined(jqName) ?
__webpack_provided_window_dot_jQuery : // use jQuery (if present)
!jqName ? undefined : // use jqLite
window[jqName]; // use jQuery specified by `ngJq`
そのとおり; webpackは、jQueryでAngularを提供しながら、まだnot
jQuery
変数をwindow
。きちんとした?
ES6の例では、angularに必要なcommonJsを使用する必要があるようです。
import $ from "jquery"
window.$ = $;
window.jQuery = $;
var angular = require("angular");
以下は元の答えです
より簡単なソリューションを目指したいです。 angularが認識できるように、jQueryをウィンドウ全体に設定するだけです。
var $ = require("jquery")
window.$ = $;
window.jQuery = $;
var angular = require("angular");
またはあなたの場合(OUT DATED):
import $ from "jquery"
window.$ = $;
window.jQuery = $;
import angular from "angular";
これが役立つことを願っています:)
あなたのケースでは ProvidePlugin を使用したほうが良いでしょう。プラグインセクションのwebpack設定に次の行を追加するだけで、jqueryがアプリで使用可能になります。
new webpack.ProvidePlugin({
"$": "jquery",
"jQuery": "jquery"
})
そこで、実際に@BobSpongeの回答と@Bobのヒント/コメントをマッシュアップしたソリューションを提供します。だからオリジナルではなく、(Babel/ES6、BTWを使用していないプロジェクトで)私のために働くものを示し、それがなぜ働くのかを説明しようとしています...
(最後の)トリックは、実際に エクスポーズローダー を使用することです。
彼らのページで説明したように、module.loaders
:
{ test: require.resolve("jquery"), loader: "expose?$!expose?jQuery" },
さらに、plugins
リストには、次のものがあります。
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.
}),
コード内でこれらの変数のグローバルな出現を実際に見つけ、各モジュールにローカルな変数にそれらを必要とします。私がするように、(RequireJSからWebpackへの)既存のプロジェクトの移行を容易にします。
そして、重要なことは(と思う)、アプリケーションのエントリポイントで、必要な順序でそれらを必要とします。私の場合、ベンダーバンドルを作成したので、これがこのバンドルの順序です。
require('jquery');
require('lodash');
// [...]
var angular = require('angular');
// Use the angular variable to declare the app module, etc.
Webpackはrequire
sを見る順序でライブラリを関連するバンドルに追加します(プラグイン/ローダーを使用してそれらを並べ替える場合を除く)。ただし、インポートは分離されているため(グローバルリークはありません)、AngularはjQueryライブラリを表示できませんでした。したがって、expose
が必要です(window.jQuery = require('jquery');
代わりに、動作しませんでした。おそらく手遅れです。)
この日本語の記事があります webpackでjQLiteではなくjQueryを使用したい+ AngularJS 同じ問題について話しているようです(日本語はまだわかりません)。私はグーグルを使って英語に翻訳しました。クレジットは cither に送られます。
彼はこれを解決する4つの方法を提供します。
ウィンドウに直接割り当てます(実際にはクールではありません)
window.jQuery = require('jquery');
var angular = require('angular');
console.log(angular.element('body'));
//[body, prevObject: jQuery.fn.init[1], context: document, selector: "body"]
expose-loader を使用します(OK、しかしそれほどクールではありません)
npm install --saveDev expose-loader
webpack.config.js
module.exports = {
entry: "./index",
output: {
path: __dirname,
filename: "bundle.js"
},
module: {
loaders: [{
test: /\/jquery.js$/,
loader: "expose?jQuery"
}]
}
};
使用法:
require('jquery');
var angular = require('angular');
console.log(angular.element('body'));
//[body, prevObject: jQuery.fn.init[1], context: document, selector: "body"]
expose-loader (より良い)を使用します
npm install --saveDev expose-loader
webpack.config.js
module.exports = {
entry: "./index",
output: {
path: __dirname,
filename: "bundle.js"
},
module: {
loaders: [{
test: /\/angular\.js$/,
loader: "imports?jQuery=jquery"
}, {
test: /\/jquery.js$/,
loader: "expose?jQuery"
}]
}
};
使用法:
var angular = require('angular');
console.log(angular.element('body'));
//[body, prevObject: jQuery.fn.init[1], context: document, selector: "body"]
ProvidePlugin (最適なソリューション)を使用します
これは実際には スタッズの受け入れられた答え ここと同じです
module.exports = {
entry: "./index",
output: {
path: __dirname,
filename: "bundle.js"
},
plugins: [
new webpack.ProvidePlugin({
"window.jQuery": "jquery"
})
],
};
使用法:
var angular = require('angular');
console.log(angular.element('body'));
//[body, prevObject: jQuery.fn.init[1], context: document, selector: "body"]
私たちがまったく同じ問題を抱えていたので、ここでこれを共有すると思いました。プロジェクトでexpose-loader
ソリューションを使用して成功しました。 jqueryをProvidePlugin
に直接注入するwindow
も良い考えだと思います。