【发布时间】:2017-10-04 15:57:03
【问题描述】:
我一直在试验最近添加到浏览器中的新 native ECMAScript module support。终于能够从 JavaScript 中直接、干净地导入脚本了,真是令人高兴。
/example.html ????
<script type="module">
import {example} from '/example.js';
example();
</script>
/example.js
export function example() {
document.body.appendChild(document.createTextNode("hello"));
};
但是,这只允许我导入由单独的 external JavaScript 文件定义的模块。我通常更喜欢内联一些用于初始渲染的脚本,因此它们的请求不会阻塞页面的其余部分。使用传统的非正式结构的库,可能看起来像这样:
/inline-traditional.html ????
<body>
<script>
var example = {};
example.example = function() {
document.body.appendChild(document.createTextNode("hello"));
};
</script>
<script>
example.example();
</script>
但是,天真地内联模块文件显然是行不通的,因为它会删除用于将模块标识给其他模块的文件名。 HTTP/2 服务器推送可能是处理这种情况的规范方式,但它仍然不是所有环境中的选项。
是否可以使用 ECMAScript 模块执行等效转换?
<script type="module"> 有什么方法可以在同一个文档中导入另一个导出的模块?
我想这可以通过允许脚本指定文件路径来工作,并且表现得好像它已经从路径下载或推送了一样。
/inline-name.html ????
<script type="module" name="/example.js">
export function example() {
document.body.appendChild(document.createTextNode("hello"));
};
</script>
<script type="module">
import {example} from '/example.js';
example();
</script>
或者可能通过完全不同的参考方案,例如用于本地 SVG 参考:
/inline-id.html ????
<script type="module" id="example">
export function example() {
document.body.appendChild(document.createTextNode("hello"));
};
</script>
<script type="module">
import {example} from '#example';
example();
</script>
但是这些假设都没有真正起作用,而且我还没有看到一个替代方案。
【问题讨论】:
-
也许有更好的方法来实现这一点——可能使用 Service Worker?
-
我不认为自制不符合规范的
inline-module可以被认为是 ES 模块的良好开端。 Webpack/Rollup 包在生产环境中仍然是不可或缺的——尤其是如果你害怕阻塞请求的话。是的,Service Worker 看起来是一个可行的解决方案——但它仍然应该发出请求以提供数据……顺便说一句,这可能会阻塞。 -
@estus 我想象使用服务工作者来获取内联的
<script>标签并使用它们来填充缓存,以避免额外的请求。如果实现足够聪明,这些甚至可以使用标准的type="module"并添加主体。 -
我可能是唯一一个喜欢代码 sn-ps 的 ????name tags 的人。
-
@JeremyBanks 您是否尝试过将外部脚本嵌入为 data-uris?
标签: javascript html ecmascript-6 es6-modules