ES6:从 URL 导入模块

Posted

技术标签:

【中文标题】ES6:从 URL 导入模块【英文标题】:ES6: import module from URL 【发布时间】:2016-04-09 00:23:13 【问题描述】:

是否可以在 ES6 中从外部 url 导入 javascript 模块?

我试过(使用 babel-node):

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

【问题讨论】:

【参考方案1】:

2018 更新:模块加载器规范现在是 ES 规范的一部分 - 您所描述的内容在浏览器中使用 <script type="module"> 和使用 Node.js 以及 Deno if 的自定义 --loader 是允许和可能的你很喜欢。


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

【讨论】:

浏览器插件:browserify-cdnjs 等等,import 语法不是 ES6 中的原生模块加载器吗? @slebetman 指定加载模块的语法(即importexport 语法)并指定如何 加载它是两个独立的任务——浏览器和节点。例如,Node.js 会使用不同的机制——所以它不能成为语言的一部分。一般来说 - 与环境交互不是规范感兴趣的任务。 正确,底层机制可能不同,但是导入语法应该是导入模块吧?显然,我们目前没有本机工作的语法示例,但大概在未来的某个时候浏览器会支持它。 @slebetman Chrome 和 Firefox 在标志下支持它。该规范由github.com/ModuleLoader/es6-module-loader(systemjs 的一个子集)填充。调用 System.register 的文件可能会工作 - 其他文件目前可能不会。还有script type='module' 用于在浏览器中编写模块代码。这都是猜测。【参考方案2】:

您也可以使用scriptjs,在我的情况下需要更少的配置。

var scriptjs = require('scriptjs');

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

【讨论】:

【参考方案3】:

TL;DR:

目前,没有

长答案:

有两种不同的规范:ES6 定义了导出/导入的语法。 还有 Loader Spec 实际定义了如何这个模块将被加载。

抛开规范不谈,对我们开发者来说重要的部分是:

JavaScript 加载器允许 Node.js 和浏览器等宿主环境按需获取和加载模块。它提供了一个可挂钩的管道,允许 Browserify、WebPack 和 jspm 等前端打包解决方案挂钩到加载过程中。

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

(...)

主要目标是让这个过程在 Node 和 Browser 环境之间尽可能地保持一致。例如,如果一个 JavaScript 程序想要即时将.coffee 文件翻译成 JavaScript,加载器定义了一个可以使用的“翻译”钩子。这允许程序参与加载过程,即使某些细节(特别是从主机定义的存储中获取特定模块的过程)在环境之间会有所不同。

所以我们依赖宿主环境(节点、浏览器、babel 等)为我们解析/加载模块并为进程提供挂钩。

【讨论】:

这个答案:“否”在 2018/2019 年无效【参考方案4】:

2022 年更新,目前看来至少在最新的 Chrome、Firefox 和 Safari 中有效,只要服务器为 js 文件提供了content-type: application/javascript; charset=utf-8 的响应头。

用普通网络服务器试试这两个文件:

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>

你好.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 说再见了。我现在有点太兴奋了!

【讨论】:

这很令人兴奋。请注意,截至 2022 年 1 月,它在 Stackblitz 项目 stackblitz.com/edit/js-y9xn5f 或 Codesandbox 中不起作用 - 但在我的本地开发环境中可以正常工作。 这被 webpack 阻止了。 Webpack 认为这是一个动态导入,它想在编译时打包 js。我之所以认为它巨大而令人兴奋是因为有了这个功能,我们对 webpack 的依赖将大大减少。【参考方案5】:

规范描述了import 中的模块说明符 是如何被解析的:

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

上面写着 URL 是允许的,绝对和相对的(以 /./../ 开头),它确实区分静态和动态导入。在正文中,还有一个“示例”框显示了有效说明符的示例:

https://example.com/apples.mjs http:example.com\pears.js (becomes http://example.com/pears.js as step 1 parses with no base URL) //example.com/bananas ./strawberries.mjs.cgi ../lychees /limes.jsx data:text/javascript,export default 'grapes'; blob:https://whatwg.org/d0360e2f-caee-469f-9a2f-87d5b0456f6f

【讨论】:

以上是关于ES6:从 URL 导入模块的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 ES6 模块导入来导入路径

d3 4.x 的 es6 模块导入失败

如何使用 es6 导入加载 emscripten 生成的模块?

ES6(Module模块化)

ES6 模块,啥算作第一次导入?

如何模拟 ES6 模块的导入?