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

时间:2021-11-05 14:50:20

I have this situation where I am trying to import an existing library, which I'll call troublesome (using Webpack/Babel FWIW) and it has a global reference to jQuery in it which i am trying to resolve using module syntax.

我有这种情况,我试图导入一个现有的库,我称之为麻烦(使用Webpack / Babel FWIW),它有一个jQuery的全局引用,我试图使用模块语法解决。

I have successfully imported jquery into the 'local' scope of a module, via:

我已成功将jquery导入模块的“本地”范围,通过:

import jQuery from 'jquery'

so I tried:

所以我试过了:

import jQuery from 'jquery'    
import 'troublesome'

but perhaps not surprisingly, I get something like jQuery is not a function kicked back from troublesome.js

但也许并不奇怪,我得到的东西就像jQuery不是一个从troublesome.js踢回来的功能

I have tried this as well:

我也试过这个:

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

but, it turns out that System.import is part of the, so-called, 'module-loader' spec, which was pulled from the es6/2015 spec, so it isn't provided by Babel. There is a poly-fill, but Webpack wouldn't be able to manage dynamic imports accomplished via calls to System.import anyway.

但是,事实证明System.import是所谓的“模块加载器”规范的一部分,该规范是从es6 / 2015规范中提取的,所以它不是由Babel提供的。有一个poly-fill,但Webpack无法管理通过调用System.import完成的动态导入。

but... if I call out the script files in index.html like so:

但是......如果我在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>

the reference to jQuery is resolved in troublesome.js and things are good, but I would prefer to avoid the script tag route as webpack doesn't manage those.

在troublesome.js中解决了对jQuery的引用并且事情很好,但是我宁愿避免脚本标记路由,因为webpack不管理这些。

Can anyone recommend a decent strategy for dealing with scenarios like this?

任何人都可以推荐一个体面的策略来处理这样的场景吗?

update

with some guidance from @TN1ck, I was eventually able to identify one Webpack-centric solution, using the imports-loader

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

The configuration for this solution looks something like this:

此解决方案的配置如下所示:

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

6 个解决方案

#1


16  

Shimming modules is the way to go: http://webpack.github.io/docs/shimming-modules.html

填充模块是要走的路:http://webpack.github.io/docs/shimming-modules.html

I quote from the page:

我从页面引用:

plugin ProvidePlugin

This plugin makes a module available as variable in every module. The module is required only if you use the variable.

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

Example: Make $ and jQuery available in every module without writing require("jquery").

示例:在每个模块中都可以使用$和jQuery,而无需编写require(“jquery”)。

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

To use this with your webpack-config just add this object to an array called plugins in the config:

要在webpack-config中使用它,只需将此对象添加到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
}

#2


2  

For es6/2015 I done the following.

对于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

Then you can use it as normal

然后你可以照常使用它

var text = $('<div />').text('hello world!!!').text();
console.log(text);

Hope this helps.

希望这可以帮助。

#3


0  

Importing jQuery into your module does not make it available for 'troublesome'. Instead, you could create a thin wrapper module for 'troublesome' that provides jQuery and any other required "globals".

将jQuery导入到您的模块中并不会使其“麻烦”。相反,您可以为“麻烦”创建一个瘦包装模块,它提供了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.

Then in your code you should be able to

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

import 'troublesome-module';

#4


0  

I've had a similar issue using jspm and dygraphs. The way i solved it was to use dynamic loading like you attempted using System.import but the important part was to chain-load each consecutive "part" using System.import again inside the promise onfulfillment handler (then) after setting the global namespace variable. In my scenario I actually had to have several import steps separated between then handlers.

我使用jspm和dygraphs有类似的问题。我解决它的方法是使用动态加载,就像你尝试使用System.import一样,但重要的部分是在设置全局命名空间变量后,在promise onfulfillment handler(然后)内再次使用System.import对每个连续的“part”进行链式加载。在我的场景中,我实际上必须在当时的处理程序之间分隔几个导入步骤。

The reason it didn't work with jspm, and probably why it didn't work for you as well is that the import ... from ... syntax is evaluated before any code, and definitely before System.import which of async.

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

In your case it could be as simple as:

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

import jQuery from 'jquery';

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

Also note that the System module loader recommendation has been left out of the final ES6 specification, and a new loader spec is being drafted.

另请注意,系统模块加载程序建议已被排除在最终的ES6规范之外,并且正在起草新的加载程序规范。

#5


0  

  1. run npm install import-loader.
  2. 运行npm install import-loader。

  3. replace import 'troublesome' with import 'imports?jQuery=jquery,$=jquery!troublesome.
  4. 用import'import替换import'麻烦'?jQuery = jquery,$ = jquery!麻烦。

In my opinion, this is the simplest solution to your question. It is similar to the answer you wrote in your question @TN1ck, but without altering your webpack config. For more reading, see: https://github.com/webpack/imports-loader

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

#6


0  

Shimming is fine and there are various ways of resolving this, but as per my answer here, the simplest is actually just to revert to using require for the loading of the library that requires the global dependency - then just make sure your window. assignment is before that require statement, and they are both after your other imports, and your ordering should remain as intended. The issue is caused by Babel hoisting imports such that they all get executed before any other code.

Shimming很好,并且有各种方法可以解决这个问题,但根据我的回答,最简单的实际上只是恢复使用require来加载需要全局依赖的库 - 然后只需确保你的窗口。赋值在该require语句之前,并且它们都在您的其他导入之后,并且您的排序应保持原样。这个问题是由Babel提升导入引起的,因此它们都会在任何其他代码之前执行。

#1


16  

Shimming modules is the way to go: http://webpack.github.io/docs/shimming-modules.html

填充模块是要走的路:http://webpack.github.io/docs/shimming-modules.html

I quote from the page:

我从页面引用:

plugin ProvidePlugin

This plugin makes a module available as variable in every module. The module is required only if you use the variable.

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

Example: Make $ and jQuery available in every module without writing require("jquery").

示例:在每个模块中都可以使用$和jQuery,而无需编写require(“jquery”)。

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

To use this with your webpack-config just add this object to an array called plugins in the config:

要在webpack-config中使用它,只需将此对象添加到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
}

#2


2  

For es6/2015 I done the following.

对于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

Then you can use it as normal

然后你可以照常使用它

var text = $('<div />').text('hello world!!!').text();
console.log(text);

Hope this helps.

希望这可以帮助。

#3


0  

Importing jQuery into your module does not make it available for 'troublesome'. Instead, you could create a thin wrapper module for 'troublesome' that provides jQuery and any other required "globals".

将jQuery导入到您的模块中并不会使其“麻烦”。相反,您可以为“麻烦”创建一个瘦包装模块,它提供了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.

Then in your code you should be able to

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

import 'troublesome-module';

#4


0  

I've had a similar issue using jspm and dygraphs. The way i solved it was to use dynamic loading like you attempted using System.import but the important part was to chain-load each consecutive "part" using System.import again inside the promise onfulfillment handler (then) after setting the global namespace variable. In my scenario I actually had to have several import steps separated between then handlers.

我使用jspm和dygraphs有类似的问题。我解决它的方法是使用动态加载,就像你尝试使用System.import一样,但重要的部分是在设置全局命名空间变量后,在promise onfulfillment handler(然后)内再次使用System.import对每个连续的“part”进行链式加载。在我的场景中,我实际上必须在当时的处理程序之间分隔几个导入步骤。

The reason it didn't work with jspm, and probably why it didn't work for you as well is that the import ... from ... syntax is evaluated before any code, and definitely before System.import which of async.

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

In your case it could be as simple as:

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

import jQuery from 'jquery';

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

Also note that the System module loader recommendation has been left out of the final ES6 specification, and a new loader spec is being drafted.

另请注意,系统模块加载程序建议已被排除在最终的ES6规范之外,并且正在起草新的加载程序规范。

#5


0  

  1. run npm install import-loader.
  2. 运行npm install import-loader。

  3. replace import 'troublesome' with import 'imports?jQuery=jquery,$=jquery!troublesome.
  4. 用import'import替换import'麻烦'?jQuery = jquery,$ = jquery!麻烦。

In my opinion, this is the simplest solution to your question. It is similar to the answer you wrote in your question @TN1ck, but without altering your webpack config. For more reading, see: https://github.com/webpack/imports-loader

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

#6


0  

Shimming is fine and there are various ways of resolving this, but as per my answer here, the simplest is actually just to revert to using require for the loading of the library that requires the global dependency - then just make sure your window. assignment is before that require statement, and they are both after your other imports, and your ordering should remain as intended. The issue is caused by Babel hoisting imports such that they all get executed before any other code.

Shimming很好,并且有各种方法可以解决这个问题,但根据我的回答,最简单的实际上只是恢复使用require来加载需要全局依赖的库 - 然后只需确保你的窗口。赋值在该require语句之前,并且它们都在您的其他导入之后,并且您的排序应保持原样。这个问题是由Babel提升导入引起的,因此它们都会在任何其他代码之前执行。