ES6: 从 URL 导入模块

105

在ES6中是否可以从外部URL导入JavaScript模块?

我尝试过(使用babel-node):

import mymodule from 'http://...mysite.../myscript.js';
// Error: Cannot find module 'http://...mysite.../myscript.js'
6个回答

51

2018年更新:模块加载器规范现在已成为 ES 规范的一部分 - 您所描述的可以使用浏览器中的 <script type="module">,以及在 Node.js 中使用自定义的 --loader 或者 Deno(如果您喜欢)。


模块加载器规范和导入/导出语法是分开的。因此,这是模块加载器的一个属性(不是 ES 规范的一部分)。如果您使用支持插件的模块加载器,例如 SystemJS


Browserify 插件:browserify-cdnjs - CodingIntrigue
3
等等,ES6中的import语法不是本地模块加载器吗? - slebetman
1
@slebetman 指定加载模块的语法(即 importexport 语法)以及指定如何加载它是两个不同的任务 - 浏览器和 node.js 例如会使用不同的机制 - 因此它不能成为语言的一部分。总的来说 - 与环境交互不是规范感兴趣的任务。 - Benjamin Gruenbaum
正确的,底层机制可能是不同的,但导入语法应该是导入模块的对吧?显然我们目前没有本地运行语法的实例,但可以假设在未来某个时候浏览器会支持它。 - slebetman
@slebetman 在某个时候,浏览器将拥有本地模块加载器,但目前还没有规范说明它将如何加载。也许它会加载外部URL,也许不会。在有人编写出来之前无法确定。 - CodingIntrigue
1
@slebetman Chrome和Firefox在标志下支持它。规范由https://github.com/ModuleLoader/es6-module-loader(systemjs的子集)填充。调用`System.register`的文件可能会起作用-其他文件目前可能不起作用。还有`script type ='module'`,用于在浏览器中编写模块代码。这主要是猜测。 - Benjamin Gruenbaum

29

2022年更新,目前最新版本的Chrome、Firefox和Safari似乎都可以正常工作,只要服务器为js文件提供响应头content-type: application/javascript; charset=utf-8

使用普通Web服务器尝试这两个文件:

index.html

<!DOCTYPE html>
<html lang="en-US">
<head>
   <meta charset="utf-8">
   <title>Hello World</title>
   <script type="module" src="./hello.js"></script>
</head>
<body>
</body>
</html>

hello.js

import ip6 from 'https://cdn.jsdelivr.net/gh/elgs/ip6/ip6.js';

const el = document.createElement('h1');
const words = "::1";
const text = document.createTextNode(ip6.normalize(words));
el.appendChild(text);

document.body.appendChild(el);

这是一个非常重要的事情!因为现在我们可以告别Webpack了。我现在有点太兴奋了!


1
这很令人兴奋。截至2022年1月,它在Stackblitz项目https://stackblitz.com/edit/js-y9xn5f或Codesandbox上无法工作 - 但在我的本地开发环境中可以正常工作。 - abulka
1
这被Webpack阻止了。Webpack认为这是一个动态导入,并且希望在编译时捆绑js。我认为它很重要和令人兴奋的原因是,有了这个功能,我们将大大减少对Webpack的依赖。 - user1663023

12
你也可以使用 scriptjs,在我的情况下需要较少的配置。
var scriptjs = require('scriptjs');

scriptjs('https://api.mapbox.com/mapbox.js/v3.0.1/mapbox.standalone.js', function() {
    L.mapbox.accessToken = 'MyToken';
});

5

TL;DR:

目前为止,不可以

长话短说:

有两个不同的规范:ES6定义了导出/导入语法。而Loader规范则是实际定义这些模块如何加载的。

滔滔不绝的规范之外,对于我们开发者来说,重要的部分是:

JavaScript Loader允许宿主环境(例如Node.js和浏览器)按需获取和加载模块。它提供了可钩子化的管道,以允许像Browserify、WebPack和jspm等前端打包解决方案插入加载过程中。

这种区分提供了开发者可以在所有JavaScript环境中使用的单一格式,并为每个环境提供了单独的加载机制。例如,Node Loader将从文件系统中加载其模块,使用自己的模块查找算法,而Browser Loader将获取模块并使用浏览器提供的打包格式。

(...)

主要目标是在Node和Browser环境之间尽可能地使这个过程保持一致。例如,如果一个JavaScript程序想要动态地将.coffee文件转换成JavaScript,Loader就定义了一个“translate”钩子来使用。这允许程序参与加载过程,即使一些细节(特别是从它的主机定义的存储获取一个特定模块的过程)在不同的环境下是不同的。

因此,我们依赖于宿主环境(node、browser、babel等)为我们解析/加载模块并提供挂钩点。


19
抱歉,您提供的翻译请求缺少上下文和相关背景信息,我无法确定应该如何正确翻译。请提供更多信息或补充说明,以便我可以更好地理解并提供精确的翻译。 - user1028880

2
该规范描述了如何解析import中的模块说明符

https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier

它说允许URL,包括绝对和相对路径(以/./../开头),并且不区分静态和动态导入。在文本的后面,有一个“示例”框,显示有效规范器的示例:
  • https://example.com/apples.mjs
  • http:example.com\pears.js (作为步骤1解析没有基本URL变成 http://example.com/pears.js)
  • //example.com/bananas
  • ./strawberries.mjs.cgi
  • ../lychees
  • /limes.jsx
  • data:text/javascript,export default 'grapes';
  • blob:https://whatwg.org/d0360e2f-caee-469f-9a2f-87d5b0456f6f

0

以下是一个纯JavaScript的示例,演示如何导入Google代码并将任何页面上的元素替换为Google翻译按钮(可以在浏览器调试控制台中运行,适用于您想要的任何站点)

importScriptURI("https://translate.google.com/translate_a/element.js"); 
document.getElementsByTagName("h1")[0].innerHTML='<div id="google_translate_element"></div>';
setTimeout(()=>{ new google.translate.TranslateElement({pageLanguage: 'en'},'google_translate_element');},1000);

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

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