Javascript 在 webpack 中管理 jQuery 插件依赖
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28969861/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Managing jQuery plugin dependency in webpack
提问by booleanhunter
I'm using Webpack in my application, in which I create two entry points - bundle.js for all my JavaScript files/codes, and vendors.js for all libraries like jQuery and React. What do I do in order to use plugins which have jQuery as their dependencies and I want to have them also in vendors.js? What if those plugins have multiple dependencies?
我在我的应用程序中使用 Webpack,我在其中创建了两个入口点 - bundle.js 用于我的所有 JavaScript 文件/代码,以及 vendor.js 用于所有库(如 jQuery 和 React)。我该怎么做才能使用以 jQuery 作为依赖项的插件,并且我希望它们也包含在 vendor.js 中?如果这些插件有多个依赖项怎么办?
Currently I'm trying to use this jQuery plugin here - https://github.com/mbklein/jquery-elastic. The Webpack documentation mentions providePluginand imports-loader. I used providePlugin, but still the jQuery object is not available. Here is how my webpack.config.js looks like-
目前我正在尝试在这里使用这个 jQuery 插件 - https://github.com/mbklein/jquery-elastic。Webpack 文档中提到了providePlugin和 import-loader。我使用了 providePlugin,但 jQuery 对象仍然不可用。这是我的 webpack.config.js 的样子-
var webpack = require('webpack');
var bower_dir = __dirname + '/bower_components';
var node_dir = __dirname + '/node_modules';
var lib_dir = __dirname + '/public/js/libs';
var config = {
addVendor: function (name, path) {
this.resolve.alias[name] = path;
this.module.noParse.push(new RegExp(path));
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jquery: "jQuery",
"window.jQuery": "jquery"
}),
new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js', Infinity)
],
entry: {
app: ['./public/js/main.js'],
vendors: ['react','jquery']
},
resolve: {
alias: {
'jquery': node_dir + '/jquery/dist/jquery.js',
'jquery.elastic': lib_dir + '/jquery.elastic.source.js'
}
},
output: {
path: './public/js',
filename: 'bundle.js'
},
module: {
loaders: [
{ test: /\.js$/, loader: 'jsx-loader' },
{ test: /\.jquery.elastic.js$/, loader: 'imports-loader' }
]
}
};
config.addVendor('react', bower_dir + '/react/react.min.js');
config.addVendor('jquery', node_dir + '/jquery/dist/jquery.js');
config.addVendor('jquery.elastic', lib_dir +'/jquery.elastic.source.js');
module.exports = config;
But in spite of this, it still throws an error in the browser console:
但尽管如此,它仍然在浏览器控制台中抛出错误:
Uncaught ReferenceError: jQuery is not defined
未捕获的 ReferenceError:未定义 jQuery
Similarly, when I use the imports-loader, it throws an error,
同样,当我使用导入加载器时,它会抛出一个错误,
require is not defined'
要求未定义'
in this line:
在这一行:
var jQuery = require("jquery")
However, I could use the same plugin when I don't add it to my vendors.js file and instead required it in the normal AMD way as how I include my other JavaScript code files, like-
但是,当我不将它添加到我的 vendor.js 文件中,而是以正常的 AMD 方式需要它时,我可以使用相同的插件,就像我如何包含其他 JavaScript 代码文件一样,例如-
define(
[
'jquery',
'react',
'../../common-functions',
'../../libs/jquery.elastic.source'
],function($,React,commonFunctions){
$("#myInput").elastic() //It works
});
But this is not what I want to do, as this would mean that jquery.elastic.source.js is bundled along with my JavaScript code in bundle.js, and I want all my jQuery plugins to be in the vendors.js bundle. So how do I go about achieving this?
但这不是我想要做的,因为这意味着 jquery.elastic.source.js 与我在 bundle.js 中的 JavaScript 代码捆绑在一起,我希望我所有的 jQuery 插件都在 vendor.js 捆绑包中。那么我该如何实现这一目标呢?
回答by Johannes Ewald
You've mixed different approaches how to include legacy vendor modules. This is how I'd tackle it:
您已经混合了如何包含遗留供应商模块的不同方法。这就是我解决它的方式:
1. Prefer unminified CommonJS/AMD over dist
1. 更喜欢未缩小的 CommonJS/AMD dist
Most modules link the distversion in the mainfield of their package.json. While this is useful for most developers, for webpack it is better to alias the srcversion because this way webpack is able to optimize dependencies better (e.g. when using the DedupePlugin).
大多数模块dist在main其package.json. 虽然这对大多数开发人员很有用,但对于 webpack 最好为src版本设置别名,因为这样 webpack 能够更好地优化依赖项(例如,在使用 时DedupePlugin)。
// webpack.config.js
module.exports = {
...
resolve: {
alias: {
jquery: "jquery/src/jquery"
}
}
};
However, in most cases the distversion works just fine as well.
但是,在大多数情况下,该dist版本也能正常工作。
2. Use the ProvidePluginto inject implicit globals
2. 使用ProvidePlugin注入隐式全局变量
Most legacy modules rely on the presence of specific globals, like jQuery plugins do on $or jQuery. In this scenario you can configure webpack, to prepend var $ = require("jquery")everytime it encounters the global $identifier.
大多数遗留模块依赖于特定全局变量的存在,就像 jQuery 插件在$或jQuery. 在这种情况下,您可以配置 webpack,以在var $ = require("jquery")每次遇到全局$标识符时进行前置。
var webpack = require("webpack");
...
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
3. Use the imports-loaderto configure this
3.使用imports-loader进行配置this
Some legacy modules rely on thisbeing the windowobject. This becomes a problem when the module is executed in a CommonJS context where thisequals module.exports. In this case you can override thiswith the imports-loader.
一些传统的模块依赖于this作为window对象。当模块在 CommonJS 上下文中执行时,这会成为一个问题,其中thisequals module.exports。在这种情况下,您可以this使用import-loader覆盖。
Run npm i imports-loader --save-devand then
运行npm i imports-loader --save-dev然后
module: {
loaders: [
{
test: /[\/\]node_modules[\/\]some-module[\/\]index\.js$/,
loader: "imports-loader?this=>window"
}
]
}
The imports-loader can also be used to manually inject variables of all kinds. But most of the time the ProvidePluginis more useful when it comes to implicit globals.
导入加载器也可用于手动注入各种变量。但大多数情况下,ProvidePlugin当涉及到隐式全局变量时,它更有用。
4. Use the imports-loaderto disable AMD
4.使用imports-loader禁用AMD
There are modules that support different module styles, like AMD, CommonJS and legacy. However, most of the time they first check for defineand then use some quirky code to export properties. In these cases, it could help to force the CommonJS path by setting define = false.
有些模块支持不同的模块样式,例如 AMD、CommonJS 和 legacy。然而,大多数时候他们首先检查define然后使用一些古怪的代码来导出属性。在这些情况下,通过设置define = false.
module: {
loaders: [
{
test: /[\/\]node_modules[\/\]some-module[\/\]index\.js$/,
loader: "imports-loader?define=>false"
}
]
}
5. Use the script-loaderto globally import scripts
5.使用script-loader全局导入脚本
If you don't care about global variables and just want legacy scripts to work, you can also use the script-loader. It executes the module in a global context, just as if you had included them via the <script>tag.
如果您不关心全局变量而只想让遗留脚本工作,您也可以使用脚本加载器。它在全局上下文中执行模块,就像您通过<script>标签包含它们一样。
6. Use noParseto include large dists
6.noParse用于包含大的 dist
When there is no AMD/CommonJS version of the module and you want to include the dist, you can flag this module as noParse. Then webpack will just include the module without parsing it, which can be used to improve the build time. This means that any feature requiring the AST, like the ProvidePlugin, will not work.
当没有 AMD/CommonJS 版本的模块并且您想要包含 时dist,您可以将此模块标记为noParse. 然后 webpack 将只包含模块而不解析它,这可以用来缩短构建时间。这意味着任何需要AST 的功能,如ProvidePlugin,都将不起作用。
module: {
noParse: [
/[\/\]node_modules[\/\]angular[\/\]angular\.js$/
]
}
回答by arcseldon
For global access to jquery then several options exist. In my most recent webpack project, I wanted global access to jquery so I added the following to my plugins declarations:
对于对 jquery 的全局访问,存在几个选项。在我最近的 webpack 项目中,我想要全局访问 jquery,因此我将以下内容添加到我的插件声明中:
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
This then means that jquery is accessible from within the JavaScript source code via global references $ and jQuery.
这意味着可以通过全局引用 $ 和 jQuery 从 JavaScript 源代码中访问 jquery。
Of course, you need to have also installed jquery via npm:
当然,你还需要通过 npm 安装 jquery:
$ npm i jquery --save
For a working example of this approach please feel free to fork my app on github
有关此方法的工作示例,请随时在github上 fork 我的应用程序
回答by sanfilippopablo
I don't know if I understand very well what you are trying to do, but I had to use jQuery plugins that required jQuery to be in the global context (window) and I put the following in my entry.js:
我不知道我是否非常了解您要做什么,但我必须使用需要 jQuery 处于全局上下文(窗口)中的 jQuery 插件,并且我将以下内容放入我的entry.js:
var $ = require('jquery');
window.jQuery = $;
window.$ = $;
The I just have to require wherever i want the jqueryplugin.min.jsand window.$is extended with the plugin as expected.
在我刚有需要的地方,我想的jqueryplugin.min.js和window.$扩展与插件如预期。
回答by HarlemSquirrel
I got things working nicely while exposing $and jQueryas global variables with Webpack 3.8.1 and the following.
在使用 Webpack 3.8.1 及以下版本公开$和jQuery作为全局变量时,我让事情很好地工作。
Install jQuery as a project dependency. You can omit @3.2.1to install the latest version or specify another version.
将 jQuery 安装为项目依赖项。您可以省略@3.2.1安装最新版本或指定其他版本。
npm install --save [email protected]
Install expose-loaderas a development dependency if not installed already.
expose-loader如果尚未安装,请安装为开发依赖项。
npm install expose-loader --save-dev
Configure Webpack to load and expose jQuery for us.
配置 Webpack 为我们加载和公开 jQuery。
// webpack.config.js
const webpack = require('webpack')
module.exports = {
entry: [
// entry bits
],
output: {
// output bits
},
module: {
rules: [
// any other rules
{
// Exposes jQuery for use outside Webpack build
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: 'jQuery'
},{
loader: 'expose-loader',
options: '$'
}]
}
]
},
plugins: [
// Provides jQuery for other JS bundled with Webpack
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
]
}
回答by ashwini
In your webpack.config.js file add below:
在您的 webpack.config.js 文件中添加以下内容:
var webpack = require("webpack");
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
],
Install jQuery using npm:
使用 npm 安装 jQuery:
$ npm i jquery --save
In app.js file add below lines:
在 app.js 文件中添加以下几行:
import $ from 'jquery';
window.jQuery = $;
window.$ = $;
This worked for me. :)
这对我有用。:)
回答by KhaledMohamedP
Add this to your plugins array in webpack.config.js
将此添加到 webpack.config.js 中的 plugins 数组中
new webpack.ProvidePlugin({
'window.jQuery': 'jquery',
'window.$': 'jquery',
})
then require jquery normally
然后通常需要jquery
require('jquery');
If pain persists getting other scripts to see it, try explicitly placing it in the global context via (in the entry js)
如果让其他脚本看到它的痛苦持续存在,请尝试通过(在条目 js 中)将其显式放置在全局上下文中
window.$ = jQuery;
回答by Cam Tullos
I tried some of the supplied answers but none of them seemed to work. Then I tried this:
我尝试了一些提供的答案,但似乎没有一个有效。然后我尝试了这个:
new webpack.ProvidePlugin({
'window.jQuery' : 'jquery',
'window.$' : 'jquery',
'jQuery' : 'jquery',
'$' : 'jquery'
});
Seems to work no matter which version I'm using
无论我使用哪个版本似乎都有效
回答by SharpCoder
This works in webpack 3:
这适用于webpack 3:
in the webpack.config.babel.js file:
在 webpack.config.babel.js 文件中:
resolve: {
alias: {
jquery: "jquery/src/jquery"
},
....
}
And use ProvidePlugin
并使用ProvidePlugin
new webpack.ProvidePlugin({
'$': 'jquery',
'jQuery': 'jquery',
})
回答by Fabricio
The best solution I've found was:
我发现的最佳解决方案是:
https://github.com/angular/angular-cli/issues/5139#issuecomment-283634059
https://github.com/angular/angular-cli/issues/5139#issuecomment-283634059
Basically, you need to include a dummy variable on typings.d.ts, remove any "import * as $ from 'jquery" from your code, and then manually add a tag to jQuery script to your SPA html. This way, webpack won't be in your way, and you should be able to access the same global jQuery variable in all your scripts.
基本上,您需要在typings.d.ts 上包含一个虚拟变量,从您的代码中删除任何“import * as $ from 'jquery”,然后手动将标签添加到您的SPA html 的jQuery 脚本中。这样,webpack 不会妨碍您,您应该能够在所有脚本中访问相同的全局 jQuery 变量。
回答by JPRLCol
This works for me on the webpack.config.js
这在 webpack.config.js 上对我有用
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
}),
in another javascript or into HTML add:
在另一个 javascript 或 HTML 添加:
global.jQuery = require('jquery');

