Webpack和外部Libs:ProvidePlugin vs entry vs global import?

时间:2016-10-06 05:48:38

标签: javascript reactjs ecmascript-6 webpack

1。 ProvidePlugin()

看起来像是一种常用的方法。关于它有一个gist,展示了如何将 whatwg-fetch polyfill包含到Webpack构建中。 StackOverflow上的大量答案使用herehere

new webpack.ProvidePlugin({
  '$': 'jquery',
  'jQuery': 'jquery',
  'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
})

优点

  • 有效。 (如果我遗漏了某些内容,请更新此列表)

缺点

  • 需要在Webpack配置中跟踪全局库。

2。 entry: [...]

当我在this gist中发现它时,我对这种方法感到有些惊讶,但它的效果也一样。

entry: [
    'babel-polyfill',
    'whatwg-fetch',
    'jquery',
    'webpack-hot-middleware/client',
    path.join(process.cwd(), 'app/app.js')
],

优点

  • 有效。
  • 我可以完全放弃ProvidePlugin()

缺点

  • 需要在Webpack配置中跟踪全局库。

3。顶级import

这个非常简单,请参阅此app.js示例。该文件是React应用程序的入口点。

/**
 * app.js
 */

import 'whatwg-fetch';
import 'babel-polyfill';
import 'jquery';

优点

  • 它的效果也一样。
  • 轻松添加/删除。无需触摸Webpack配置。

缺点

  • 看起来这种方法不仅适用于jQuery插件,例如 bootstrap.js

观察:在所有这三种方法中,我都没有注意到包大小的任何变化。

是否有一种推荐的使用Webpack(和React)处理全局库的方法?这些解决方案中的任何一个都会在服务器端渲染的情况下引发问题吗?

谢谢!

2 个答案:

答案 0 :(得分:18)

我不建议将库公开为全局,除非你真的需要它,即模块系统的要点是明确声明依赖,例如。

// app.js
import $ from 'jquery';
$.ajax(...);

如果您确实需要全局jQuery,因为第三方脚本需要在您的页面上或者可能在控制台中进行调试,那么这里有一些关于您列出的方法的信息:

ProvidePlugin

ProvidePlugin不会在全局上公开jQuery,而是真正用于修复错误依赖全局模块存在的第三方模块,所以我不建议这样做,例如。

// app.js
$.ajax(...);

有效地转化为:

// app.js
require('jquery').ajax(...);

进入&顶级导入

这些方法不适用于常规的UMD模块,例如jQuery,因为jQuery足够聪明,在被commonjs / amd / es6识别加载器加载时不会在全局上暴露自己。

然而,这两种方法适用于具有副作用的模块,例如babel-polyfill / whatwg-fetch,因为它们不会导出任何内容,它们本身会改变全局环境。

因此,我对jQuery的建议是使用旨在公开全局模块导出的expose-loader,例如。

// webpack.config.js
{
    module: {
        loaders: [
            test: require.resolve('jquery'),
            loader: 'expose-loader?jQuery!expose-loader?$'
        ]
    }
}

然后,您仍然需要在应用代码中导入它:

// app.js
import $ from 'jquery';
$.ajax(...)

但是如果绝对必要,它可以在全局上访问页面上的其他脚本:

// console
window.$
window.jQuery

注意:从技术上讲,在使用公开加载程序时,只需import 'jquery'一次进入入口点,然后依赖其他模块中的全局。

正如我所说,如果您不需要公开模块,即使您恰好在其他模块中使用它,也不建议公开模块。

答案 1 :(得分:0)

如果您在使用ProvidePlugin时在一页中包含多个包(入口点),只需找出提供的库将被覆盖。示例是针对RoR和Webpacker的,但我认为没关系。

例如,您的布局中有

  javascript_pack_tag 'application',
                      'metronic'

在配置中,您可以:

  environment.plugins.append('Provide', new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
      "window.jQuery": "jquery",
      "window.$": "jquery",
      _: 'underscore',
      Handlebars: 'handlebars'
  }));

如果在application.js中需要使JQuery发生变化的库,那么即使您使用暴露加载程序公开JQuery,也将在metronic.js和浏览器中释放所有这种变化。

如果我错了,请纠正我,ProvidePlugin可能只是在每个入口点导入libs。