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 指定加载模块的语法(即import
和export
语法)并指定如何 加载它是两个独立的任务——浏览器和节点。例如,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 导入模块的主要内容,如果未能解决你的问题,请参考以下文章