Webpack ProvidePlugin vs externals?

时间:2014-04-26 01:39:52

标签: backbone.js requirejs amd webpack

我正在探索将WebpackBackbone.js一起使用的想法。

我已经按照快速入门指南了解了Webpack的工作原理,但我不清楚如何加载依赖库,如jquery / backbone / underscore。

它们是否应该在<script>外部加载,或者这是Webpack可以像RequireJS的垫片一样处理的东西吗?

根据webpack doc: shimming modulesProvidePluginexternals似乎与此相关(某处的bundle!加载器也是如此),但我无法弄清楚何时使用哪个。

由于

3 个答案:

答案 0 :(得分:146)

这两种可能性:您可以包含<script>的库(即使用CDN中的库)或将它们包含在生成的包中。

如果您通过<script>标记加载,则可以使用externals选项在您的模块中编写require(...)

来自CDN的库示例:

<script src="https://code.jquery.com/jquery-git2.min.js"></script>

// the artifial module "jquery" exports the global var "jQuery"
externals: { jquery: "jQuery" }

// inside any module
var $ = require("jquery");

包中包含库的示例:

copy `jquery-git2.min.js` to your local filesystem

// make "jquery" resolve to your local copy of the library
// i. e. through the resolve.alias option
resolve: { alias: { jquery: "/path/to/jquery-git2.min.js" } }

// inside any module
var $ = require("jquery");

ProvidePlugin可以将模块映射到(免费)变量。因此,您可以定义:“每次我在模块中使用(免费)变量xyz时,您(webpack)都应将xyz设置为require("abc")。”

没有ProvidePlugin的示例:

// You need to require underscore before you can use it
var _ = require("underscore");
_.size(...);

ProvidePlugin的示例:

plugins: [
  new webpack.ProvidePlugin({
    "_": "underscore"
  }) 
]

// If you use "_", underscore is automatically required
_.size(...)

要点:

  • 来自CDN的图书馆:使用<script>代码和externals选项
  • 来自filesystem的库:将库包含在bundle中。 (可能修改resolve选项以查找库)
  • externals:将全局变量作为模块提供
  • ProvidePlugin:将模块作为模块内的自由变量提供

答案 1 :(得分:21)

值得注意的是,如果将ProvidePluginexternals属性结合使用,它将允许您将jQuery传递到您的webpack模块闭包中而无需显式{ {1}}它。这对于使用引用require的许多不同文件重构遗留代码非常有用。

$

现在在index.js

//webpack.config.js
module.exports = {
  entry: './index.js',
  output: { 
    filename: '[name].js' 
  },
  externals: {
    jquery: 'jQuery'
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
    })
  ]
};

将有一个编译输出,如下所示传递到console.log(typeof $ === 'function'); 闭包中:

webpackBootstrap

因此,您可以看到/******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function($) { console.log(typeof $ === 'function'); /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1))) /***/ }, /* 1 */ /***/ function(module, exports, __webpack_require__) { module.exports = jQuery; /***/ } /******/ ]) 正在引用CDN中的全局/窗口$,但正被传递到闭包中。我不确定这是否是预期的功能或幸运的黑客,但它似乎适用于我的用例。

答案 2 :(得分:11)

我知道这是一篇很老的帖子,但我认为在这种情况下提及webpack脚本加载器可能会很有用。来自webpack文档:

“script:在全局上下文中执行一次JavaScript文件(如在脚本标记中),不解析需求。”

http://webpack.github.io/docs/list-of-loaders.html

https://github.com/webpack/script-loader

我发现这在迁移将JS供应商文件和应用程序文件连接在一起的旧构建过程时特别有用。一句警告是,脚本加载器似乎只能通过重载require()来工作,并且在我在webpack.config文件中指定时无法正常工作。尽管如此,许多人认为重载require是不好的做法,但它可以非常有用于在一个包中同步供应商和应用程序脚本,同时暴露JS Globals,而不必将其整合到其他webpack包中。例如:

require('script!jquery-cookie/jquery.cookie');
require('script!history.js/scripts/bundled-uncompressed/html4+html5/jquery.history');
require('script!momentjs');

require('./scripts/main.js');

这将使$ .cookie,History和moment在这个包内外全局可用,并将这些供应商库与main.js脚本及其所有require d文件捆绑在一起。

此外,这项技术很有用:

resolve: {
  extensions: ["", ".js"],
  modulesDirectories: ['node_modules', 'bower_components']
},
plugins: [
  new webpack.ResolverPlugin(
    new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
   )
]
正在使用Bower的

将查看每个main d库package.json中的require文件。在上面的示例中,History.js没有指定main文件,因此需要该文件的路径。