我能使用ES6/2015模块导入在“全局”范围内设置引用吗?

34

我有这样一种情况,我试图导入一个现有的库,我将其称为troublesome(使用Webpack / Babel),它在其中具有对jQuery的全局引用,我正在尝试使用模块语法解决它。

我已经成功地将jquery通过以下方式导入到模块的“本地”作用域中:

import jQuery from 'jquery'

所以我尝试了:

import jQuery from 'jquery'    
import 'troublesome'

但也许并不奇怪,我从 troublesome.js 收到了类似于 jQuery不是一个函数 的错误信息。

我也尝试过这个:

System.import('jquery')
.then(jQuery => {
    window.jQuery = jQuery
})
import 'troublesome'

然而,事实证明System.import是所谓的“module-loader”规范的一部分,该规范已从ES6/2015规范中删除,因此Babel不提供它。有一个poly-fill,但Webpack无法管理通过调用System.import实现的动态导入。

但是...如果我在index.html中按照以下方式调用脚本文件:

<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/troublesome/troublesome.js"></script>
<script src="the-rest-of-my-js.js"></script>

jQuery的引用在troublesome.js中得到解决,事情进展顺利,但我希望避免使用脚本标记,因为webpack不能管理这些标记。

有人能推荐一种处理这种情况的好方法吗?

更新

在@TN1ck的指导下,我最终能够找到一个以Webpack为中心的解决方案,使用imports-loader

该解决方案的配置看起来像这样:

  //...
  module: {
    loaders: [
      //...
      {
        test: require.resolve('troublesome'),
        loader: "imports?jQuery=jquery,$=jquery"
      }
    ]
  }

你只是想让 jquerytroublesome 中可用吗? - Ray Toal
2
你尝试过将jQuery分配给window对象吗?所以window.jQuery = jQuery? - kyrisu
1
jQuery需要以正确的格式才能像那样导入。换句话说,您可能需要修改本地的jQuery并将其导出为ES6模块。 - colecmc
6个回答

16

使用 Shimming 模块是最佳方案:http://webpack.github.io/docs/shimming-modules.html

以下为网页引用:

插件 ProvidePlugin

该插件可将模块作为变量在每个模块中使用。只有在使用该变量时才需要该模块。

例如:无需编写 require("jquery"),即可在每个模块中使用 $ 和 jQuery 变量。

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

要将其与您的webpack-config一起使用,只需将此对象添加到名为plugins的配置中的数组中:

// the plugins we want to use 
var plugins = [
   new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
   })
];

// this is your webpack-config
module.exports = {
    entry: ...,
    output: ...,
    module: ...,
    plugins: plugins
}

感谢@TN1ck,我通过imports-loader实现了所需的效果,但是ProvidePlugin也属于同一解决方案家族,所以你指引我朝着正确的方向前进,真的很值得赞扬。 - tony_k
希望您能提供如何在Webpack中使用它的说明?我应该把它粘贴到哪里? - Jikku Jose
@JikkuJose 在某个时候,你的webpack配置应该看起来像这样:module.exports = { entry: xxx, output: ... }。只需将 plugins: [new webpack.ProvidePlugin({$: 'jquery, ...})] 添加到字典中即可。有关如何使用webpack的更多信息,请查看Pete Hunt的指南 - TN1ck

2

对于es6/2015,我已经完成了以下操作。

import {jsdom} from 'jsdom';
import jQuery from 'jquery';
var window = jsdom(undefined, {}).defaultView;
var $ = jQuery(window);
//window.jQuery = $; //probably not needed but it's there if something wrong
//window.$ = $;//probably not needed but it's there if something wrong

然后您可以像平常一样使用它。
var text = $('<div />').text('hello world!!!').text();
console.log(text);

希望这有所帮助。

0
  1. 运行 npm install import-loader
  2. import 'troublesome' 替换为 import 'imports?jQuery=jquery,$=jquery!troublesome

在我看来,这是您问题的最简单解决方案。它类似于您在问题中编写的答案 @TN1ck,但不会更改您的 webpack 配置。有关更多阅读,请参见:https://github.com/webpack/imports-loader


0

Shimming是可以的,而且有多种解决方法,但根据我的答案所述,最简单的方法实际上只是恢复使用require来加载需要全局依赖库的库 - 然后只需确保您的window.赋值在该require语句之前,并且它们都在其他导入之后,您的排序应该保持不变。问题是由Babel提升导入的方式引起的,以便它们在任何其他代码之前都得到执行。


0
jQuery导入您的模块并不意味着它可以在'troublesome'中使用。相反,您可以为'troublesome'创建一个薄包装模块,提供jQuery和任何其他所需的“全局变量”。

troublesome-module.js:

// Bring jQuery into scope for troublesome.
import jQuery from 'jquery';
// Import any other 'troublesome'-assumed globals.

// Paste or have build tool interpolate existing troublesome.js code here.

然后在你的代码中,你应该能够

import 'troublesome-module';

0

我曾经在使用jspm和dygraphs时遇到过类似的问题。我解决它的方法是使用动态加载,就像你尝试使用System.import一样,但重要的部分是在设置全局命名空间变量后,在promise onfulfillment处理程序(then)中再次使用System.import链接每个连续的“部分”。在我的情况下,我实际上必须在then处理程序之间分别进行几个导入步骤。

它不能与jspm一起工作的原因,可能也是为什么它对你也不起作用的原因是import ... from ...语法在任何代码之前都会被评估,而且肯定在异步的System.import之前。

在你的情况下,它可能很简单:

import jQuery from 'jquery';

window.jQuery = jQuery;
System.import('troublesome').then(troublesome => {
 // Do something with it...
});

还要注意的是,System模块加载器建议已被从最终的ES6规范中删除,并且正在起草新的加载器规范


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