管理webpack中的jQuery插件依赖项

本文翻译自:Managing jQuery plugin dependency in webpack

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. 我在我的应用程序中使用Webpack,我在其中创建了两个入口点 - 所有JavaScript文件/代码的bundle.js,以及jQuery和React等所有库的vendors.js。 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? 我怎么做才能使用jQuery作为依赖项的插件,我想在vendors.js中也有它们? What if those plugins have multiple dependencies? 如果这些插件有多个依赖项怎么办?

Currently I'm trying to use this jQuery plugin here - https://github.com/mbklein/jquery-elastic . 目前我正在尝试使用这个jQuery插件 - https://github.com/mbklein/jquery-elastic The Webpack documentation mentions providePlugin and imports-loader. Webpack文档提到了applyPlugin和imports-loader。 I used providePlugin, but still the jQuery object is not available. 我使用了providePlugin,但仍然没有jQuery对象。 Here is how my webpack.config.js looks like- 以下是我的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, 同样,当我使用imports-loader时,它会抛出一个错误,

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- 但是,当我不将它添加到我的vendors.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. 但这不是我想要做的,因为这意味着jquery.elastic.source.js与我在bundle.js中的JavaScript代码捆绑在一起,我希望我的所有jQuery插件都在vendors.js包中。 So how do I go about achieving this? 那么我该如何实现这一目标呢?


#1楼

参考:https://stackoom.com/question/1xYNp/管理webpack中的jQuery插件依赖项


#2楼

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 over dist

Most modules link the dist version in the main field of their package.json . 大多数模块将dist版本链接到package.jsonmain字段中。 While this is useful for most developers, for webpack it is better to alias the src version because this way webpack is able to optimize dependencies better (eg when using the DedupePlugin ). 虽然这对大多数开发人员都很有用,但对于webpack来说,最好为src版本添加别名,因为这样webpack能够更好地优化依赖关系(例如,在使用DedupePlugin )。

// webpack.config.js

module.exports = {
    ...
    resolve: {
        alias: {
            jquery: "jquery/src/jquery"
        }
    }
};

However, in most cases the dist version works just fine as well. 但是,在大多数情况下, dist版本也可以正常工作。


2. Use the ProvidePlugin to inject implicit globals 2.使用ProvidePlugin注入隐式全局变量

Most legacy modules rely on the presence of specific globals, like jQuery plugins do on $ or jQuery . 大多数遗留模块依赖于特定全局变量的存在,比如jQuery插件对$jQuery In this scenario you can configure webpack, to prepend var $ = require("jquery") everytime it encounters the global $ identifier. 在这种情况下,您可以配置webpack,以在每次遇到全局$ identifier时添加var $ = require("jquery")

var webpack = require("webpack");

    ...

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

3. Use the imports-loader to configure this 3.使用imports-loader配置this

Some legacy modules rely on this being the window object. 一些遗留模块依赖this作为window对象。 This becomes a problem when the module is executed in a CommonJS context where this equals module.exports . 当模块在CommonJS上下文中执行时,这将成为一个问题,其中this等于module.exports In this case you can override this with the imports-loader . 在这种情况下,您可以使用imports-loader覆盖this

Run npm i imports-loader --save-dev and 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. imports-loader也可用于手动注入各种变量。 But most of the time the ProvidePlugin is more useful when it comes to implicit globals. 但是大多数情况下,当涉及到隐式全局变量时, ProvidePlugin会更有用。


4. Use the imports-loader to disable AMD 4.使用imports-loader禁用AMD

There are modules that support different module styles, like AMD, CommonJS and legacy. 有些模块支持不同的模块样式,如AMD,CommonJS和legacy。 However, most of the time they first check for define and then use some quirky code to export properties. 但是,大多数情况下,他们首先检查define ,然后使用一些古怪的代码来导出属性。 In these cases, it could help to force the CommonJS path by setting define = false . 在这些情况下,通过设置define = false可以帮助强制CommonJS路径。

module: {
    loaders: [
        {
            test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
            loader: "imports-loader?define=>false"
        }
    ]
}

5. Use the script-loader to 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 noParse to include large dists 6.使用noParse包含大型dists

When there is no AMD/CommonJS version of the module and you want to include the dist , you can flag this module as noParse . 如果没有AMD / CommonJS版本的模块并且您想要包含dist ,则可以将此模块标记为noParse Then webpack will just include the module without parsing it, which can be used to improve the build time. 然后webpack将包含模块而不解析它,这可用于改善构建时间。 This means that any feature requiring the AST , like the ProvidePlugin , will not work. 这意味着任何需要AST的功能(如ProvidePlugin )都不起作用。

module: {
    noParse: [
        /[\/\\]node_modules[\/\\]angular[\/\\]angular\.js$/
    ]
}

#3楼

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.js and window.$ is extended with the plugin as expected. 我只需要在任何我想要的地方jqueryplugin.min.jswindow.$按照预期扩展插件。


#4楼

For global access to jquery then several options exist. 对于jquery的全局访问,存在几个选项。 In my most recent webpack project, I wanted global access to jquery so I added the following to my plugins declarations: 在我最近的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分享我的应用程序


#5楼

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;

#6楼

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. 基本上,你需要在typings.d.ts上包含一个虚拟变量,从你的代码中删除任何“import * as $ from jquery”,然后手动将标签添加到你的SPA html的jQuery脚本中。 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. 这样,webpack将不会妨碍您,并且您应该能够在所有脚本中访问相同的全局jQuery变量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值