使用Webpack将jQuery暴露给真实的Window对象

119

我希望将 jQuery 对象暴露给全局的 window 对象,以便在浏览器的开发者控制台中访问。现在,在我的 webpack 配置中,我有以下行:

plugins: [
                new webpack.ProvidePlugin({
                    $: 'jquery',
                    jQuery: 'jquery'
                })
            ]

这些代码将jQuery的定义添加到我的webpack模块中的每个文件中。 但是,当我构建项目并像这样在开发者控制台中尝试访问jQuery时:

window.$;
window.jQuery;

它表示这些属性未定义......

有没有办法解决这个问题?


1
我也可以设置this: 'window'吗?因为许多库假定this变量是Window对象。 - Abhinav Singi
8个回答

137

你需要使用 expose-loader

npm install expose-loader --save-dev

你可以在需要时执行此操作:

require("expose?$!jquery");

或者您可以在配置文件中这样做:

loaders: [
    { test: require.resolve('jquery'), loader: 'expose?jQuery!expose?$' }
]

更新: 自webpack 2起,您需要使用expose-loader代替expose:

module: {
    rules: [{
        test: require.resolve('jquery'),
        use: [{
            loader: 'expose-loader',
            options: '$'
        }]
    }]
}

13
ProvidePlugin 应主要用于第三方库依赖全局变量存在的情况。 - Johannes Ewald
8
这正是我一直在寻找的,而且要补充一点的是,对于加载器,你也可以用一行代码实现:{test: /jquery\.js$/, loader: 'expose?jQuery!expose?$'} - Fernando
8
你可以添加一个首要脚本,执行 $ = require('jquery'); window.jQuery = $; window.$ = $;,这样就不需要使用 expose-loader - herman
1
根据expose-loader GitHub页面所述,webpack 2的语法如下:module: { rules: [{ test: require.resolve('jquery'), use: [{ loader: 'expose-loader', options: 'jQuery' },{ loader: 'expose-loader', options: '$' }] }] }。这是我能够暴露jQuery的唯一方法,并且它使用了新的module.rules语法。 - Gavin Sutherland
@GavinSutherland 我已经更新了答案。我没有编写Webpack 2的编辑,但现在我已经纠正了它。 - Matt Derrick
显示剩余5条评论

93
ProvidePlugin通过相应的导入替换另一个源中的符号,但不会将该符号暴露在全局命名空间中。一个典型的例子就是jQuery插件。它们大多数都希望全局定义了jQuery。使用ProvidePlugin可以确保jQuery是依赖项(例如在之前已经加载),并且代码中出现的jQuery会被替换为webpack原始等价物require('jquery')
如果您有外部脚本依赖于符号在全局命名空间中(比如说一个外部托管的JS、在Selenium中调用Javascript或者简单地在浏览器控制台中访问该符号),则应使用expose-loader
简而言之: ProvidePlugin管理构建时对全局符号的依赖关系,而expose-loader管理运行时对全局符号的依赖关系。

2
感谢您的解释。 - Foton
从官方文档中了解 ProvidePlugin 在 webpack 中的使用示例:https://webpack.js.org/plugins/provide-plugin/#usage-jquery - James Gentes

40

看起来 window 对象在所有模块中都是公开的。

为什么不直接导入/引入 JQuery 并放置:

window.$ = window.JQuery = JQuery;

在需要/引入任何使用window.JQuery的模块之前,您需要确保此操作已发生。这可能是在一个引入模块中或在使用它的模块中。


最简单的解决方案,无需添加新的依赖项。谢谢! - fatihpense
当其他嵌套模块使用该变量时,这种方法将无法正常工作,只会显示“未定义”。 - aboutqx
4
使用 require 时有效,但不适用于 import - aboutqx
@aboutqx 不太确定你的意思。我的回答假设JQuery已经被导入/需要,并分配给一个名为JQuery的变量。 - mhess
2
@mhess 当你使用 import 时,可能会遇到错误,因为 import 语句会被移到文件的顶部,而 require 语句则保持在它们放置的位置。所以只有在窗口变量未设置时,运行顺序才会因 import 而改变。 - aboutqx
请确保您未添加任何与jquery相关的DefinePlugin,以便使此工作正常。 - James Tan

19

这个方法一直在我这里奏效,包括在 webpack 3 中。 window.$ = window.jQuery = require("jquery");


2
最佳解决方案!2018 - jmp

11

以上方法都对我没有用。(而且我真的不喜欢 expose-loader 语法)。相反,

我在 webpack.config.js 中添加了以下内容:

var webpack = require('webpack');
module.exports = {
   plugins: [
       new webpack.ProvidePlugin({
           $: 'jquery',
       })     
   ]
}

所有模块都可以通过$符号在jQuery中访问。

您可以通过向webpack捆绑的任何模块添加以下内容将其暴露给窗口:

window.$ = window.jQuery = $

1
这对我来说可行,使用webpack-stream在后台运行。 - klewis

1

Webpack v2更新

按照Matt Derrick的描述,安装expose-loader:

npm install expose-loader --save-dev

然后在你的 webpack.config.js 中插入以下片段:

module.exports = {
    entry: {
        // ...
    },
    output: {
        // ...
    },
    module: {
        loaders: [
                { test: require.resolve("jquery"), loader: "expose-loader?$!expose-loader?jQuery" }
        ]
    }
};

来自expose-loader文档

我现在无法在Webpack的任何版本中让它正常工作。不确定发生了什么变化,但我能让jQuery或$被识别的唯一方法是执行window.jQuery = require('jquery') - trpt4him

0

在我的情况下有效

{ test: require.resolve("jquery"), loader: "expose?$!expose?jQuery" } 

0

Webpack v2 更新

在升级到 webpack 5 后,您可能会面临此警告。

[DEP_WEBPACK_RULE_LOADER_OPTIONS_STRING] DeprecationWarning: Using a string as loader options is deprecated (ruleSet[1].rules[7].use[0].options)

只需将选项更改为

options: {
 exposes: ["$", "jQuery"],
}

将会长成这个样子:

module: {
rules: [{
    test: require.resolve('jquery'),
    use: [{
        loader: 'expose-loader',
        {
           exposes: ["$", "jQuery"],
        }
    }]
  }]
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接