各种webpack shim方法的混淆

7

我有点困惑于webpack允许暴露在npm中不可用或不放入捆绑包的变量的各种方式。我能够通过使用以下方法来暴露google可视化图表脚本的全局变量google

resolve: {
    extensions: ['.js', '.json'],
    alias: {
      'google': path.resolve(__dirname, 'vendor', 'google.js')
    }
  }

与之结合
  plugins: [
    new webpack.ProvidePlugin({
      'google': 'google'
    })
  ]

然而,查看webpack文档,还有一些其他的方式可以进行“shim”,看起来它们可能会做类似的事情。有imports-loaderexports-loaderscript-loader。我知道我已经链接了文档,但我仍然觉得它们对这四个加载器应该何时使用的描述有点不清楚。
此外,看看这个例子,这个require没有被分配给一个变量吗?它应该去哪里?这种语法的背后是什么文档?
require("imports?$=jquery!./file.js")

有人能够给我提供一些这些工具应该在什么情况下使用的例子吗?
2个回答

4

scripts-loader

我自己从未使用过这个,但是我认为它的想法很简单。如果你想向某些模块/文件注入脚本、函数或其他内容,而这些模块/文件不在你的控制范围内,那么可能可以使用这个。

imports-loader & exports-loader

在我曾经参与开发的一个应用中,我们必须使用tinymce,而在其早期版本中,this始终依赖于window,因为它是作为全局脚本构建的,而不是作为CommonJS或ES模块。

因此,为了解决这个问题,我们不得不使用import-loader来将window注入到脚本中。下面是在webpack.config.js中的样子:

{ test: require.resolve('tinymce/tinymce'), use: ['imports?this=>window', 'exports?tinymce'] }

这里说的是将this替换为window,同时我们在这里使用了exports-loader以便将全局变量tinymce作为默认导出命名为tinymce,这样我们就可以将其作为应用中的正常模块使用。

值得庆幸的是,这些问题在最新版本中已经被修复了。

ProvidePlugin

根据我的经验,当一个库依赖于另一个库存在全局作用域中时,这种方法非常有用。例如,jQuery插件会使用以下其中之一:$window.$jQuerywindow.jQuery

  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    'window.$': 'jquery',
    'window.jQuery': 'jquery',
  }),

因此,这个插件的作用是确保当webpack看到其中一种变体时,它会将jQuery对象提供给它。
imports-loader的区别在于,您可能不知道哪个脚本使用了哪个变体。因此,您可以让webpack处理这个问题,而imports-loader则更具体。
我希望这有助于您更好地理解它们之间的区别,另外这是新的文档页面,我认为比您检查的那个更好 https://webpack.js.org/guides/shimming/

什么是 ! 语法? - 1252748
Webpack 添加了一个选项,可以使用自己的语法重载 require() 函数,以允许内联使用加载器。这就是为什么这里有奇怪的语法 require("imports?$=jquery!./file.js"),它只是在说将 $ 作为 jQuery 导入到 file.js 中。 - ahmedelgabri
哦,这就是为什么文档中只有 require(....) 而不是像 const module = require('module') 这样的写法吗?你能举个例子来展示如何使用内联语法吗? - 1252748
将其存储在变量中与否与加载程序无关,这取决于您想要对require()import的脚本做什么。这已经非常简单了,例如require("imports?$=jquery!./file.js"),假设file.js是一个依赖于jQuery作为$的jQuery插件,那么您可以确保它获取到jQuery作为$ - ahmedelgabri
您还可以查看@arturkin下面的示例。 - ahmedelgabri

4

importsexports 载入器非常容易理解。如果您使用其中之一或两者,您的模块将被包装到另一个带有导出和导入的函数中。

例如,我正在使用 paho-mqtt 模块,它旨在像全局的 <script src=""> 一样在页面上使用:

import Paho from 'imports-loader?this=>window!exports-loader?Paho!paho-mqtt';

//and this is transformed by webpack to something like:
(function(window){

    //wow you can use `window here`, `this` in the global context === window.


   // original module code here
   // that exposes global var `Paho`


   module.exports = Paho;

})(this);

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