浏览器将如何处理ES6的import/export语法?

10
我思考了很多天这个问题,现在决定向专家请教。浏览器将如何处理新的import/export语法?我的意思是:模块是否会异步加载?只引用我的主文件或入口文件,浏览器会延迟加载所需的模块。也许我对这种新架构有什么误解或误解吗?非常感谢!祝好!

如果需要依赖代码才能运行,它如何异步运行? - dandavis
你看过 SystemJS 这个项目吗?https://github.com/systemjs/systemjs - chrmod
2个回答

9

这是现在标准化的,所有主要现代浏览器都支持。

模块将异步加载吗?

是的,有两个选项可用;详见下文。

只需引用我的主文件或入口文件,浏览器就会延迟加载所需的模块。

不算“懒惰”,但是是的。

启用它

规范中的详细信息在此处在此处(可能还有其他地方)。

要实现此行为,您需要使用type="module"来指定脚本是一个模块

<script src="main.js" type="module"></script>

或者用于内联脚本
<script type="module">
// ...module code here
</script>

那意味着脚本按照JavaScript规范中模块的定义进行解析和处理,而不是按照脚本的定义进行解析和处理,这意味着它可以有导入(和导出)。
导入相对于脚本的URL进行解析(对于通过单独资源(如上面的main.js)加载的模块,就像CSS一样),或者相对于文档进行解析(对于像上面的内联模块)。
因此,例如,如果我在http://example.com/index.html中有这个:
<script src="./handy/stuff/nifty.js" type="module"></script>

...而nifty.js包含

import Thingy from "./thingy.js";

然后浏览器会查找 http://example.com/handy/stuff/thingy.js,而不是 http://example.com/thingy.js。就像 CSS 导入一样。
请注意,该模块指示符上的 ./ 是必需的,只有 from "thingy.js" 是行不通的。这是因为裸指示符被禁止,因为它们可能最终具有特殊含义。(例如,在 Node.js 中,这是指定内置模块和安装在 node_modules 中的模块的方式。)模块指示符必须是完整的 URL,或以 /./../ 开头的相对 URL。
异步加载模块,有两个可用选项。本规范中的此图表最能说明问题(请参阅规范获取最新版本):

enter image description here

如您所见,对于type="module"的脚本来说,如果在script标签上没有放置任何特殊的标志属性,那么该模块的所有依赖项将会被解析,然后在HTML解析完成后运行该脚本。如果加上async属性,它可能会在HTML解析完成之前更早地运行(例如,如果所有脚本都在缓存中)。 (defer对于模块无效。)

@Alex29 - 现在它已经在所有主要的现代浏览器上运行了。 :-) - T.J. Crowder

1
根据 Mozilla 网站上 this 的帖子,这取决于实现方式:
由于系统未指定加载方式,并且您可以通过查看源代码中的导入声明来提前确定所有依赖项,因此 ES6 的实现可以在编译时完成所有工作并将所有模块捆绑到单个文件中以便通过网络传输!
这可能会在未来发生变化,因为它仍未完全标准化,但您可以确信不需要为每个模块添加脚本标记。一些模块加载器今天会为您捆绑所有文件,但当未来到来时,这可能不再是情况,因为在 HTTP2 中没有性能优势。
您可以在此处阅读有关 import 的 ES6 规范 here

3
考虑到使用HTTP2,编译时打包可能不必要。 - chrmod
谢谢。我真的不知道还没有标准化。有任何初步想法吗?因为我听说过HTTP2,但我不知道它如何帮助解决模块之间的依赖关系。只是好奇。无论如何,谢谢。 - Alex29

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