我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

计算机代码世界更新太快,现在浏览器不用babel编译,就可以执行es6模块了。也就是说,如果不考虑兼容性的问题的话,在浏览器环境下,使用js的新语法,也是可能的了。喜大普奔?(假装喜大普奔ing)。

苏南大叔:浏览器执行es6模块,如何原生执行import、export语句? - nodejs-module
浏览器执行es6模块,如何原生执行import、export语句?(图9-1)

大家好,这里是苏南大叔的“程序如此灵动”博客,这里记录苏南大叔和计算机代码的故事。本文记录谷歌浏览器原生支持importexportes6 module语句的故事。本文测试环境:win10chrome@100.0.4896.60ie11@21h2edge@100.0.1185.29

准备素材

如果大家对于es6 moduleimportexport是怎么回事,还不是很清楚的话。可以先查看下面的文章:

这里就简述一个最简单常见的情况了:
lib.js:

export default function() {
    console.log("苏南大叔的测试代码");
}

主体test.html引用代码:

import aa from './lib.js';
aa();

最正确的使用姿势

先说一下最正确的使用姿势:

<script type="module">
import aa from './lib.js';
aa();
</script>

然后把test.htmllib.js文件放到www容器里面,通过浏览器访问站点的方式使用。

苏南大叔:浏览器执行es6模块,如何原生执行import、export语句? - 最正确的使用方式
浏览器执行es6模块,如何原生执行import、export语句?(图9-2)

错误的使用姿势

浏览器里面对于es6模块化的js,也不是无条件支持的。下面是一些错误的使用方式范例:

错误一:直接双击.html文件

Access to script at 'file:///<path>/lib.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https

苏南大叔:浏览器执行es6模块,如何原生执行import、export语句? - 直接双击
浏览器执行es6模块,如何原生执行import、export语句?(图9-3)

错误二:不写type="module"

Uncaught SyntaxError: Cannot use import statement outside a module

苏南大叔:浏览器执行es6模块,如何原生执行import、export语句? - type-module
浏览器执行es6模块,如何原生执行import、export语句?(图9-4)

错误三:被导入文件的路径写法

这里,还需要注意一个写法,就是import from后面的文件路径,不支持那种不带有任何路径修饰的写法。比如:lib.js不行,目前本文的测试中是永远不会通过的,比如至少都需要一个./。虽然大家的意识里面,两者是同一个意思。但是,这里的测试环境下,就是不一样的结果。

Uncaught TypeError: Failed to resolve module specifier "lib.js". Relative references must start with either "/", "./", or "../".

苏南大叔:浏览器执行es6模块,如何原生执行import、export语句? - 错误的路径表示方式
浏览器执行es6模块,如何原生执行import、export语句?(图9-5)

错误四:不被浏览器认识的header

可以简单的保存相关文件为.js。那么,本错误并不会被显示。

Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "application/octet-stream". Strict MIME type checking is enforced for module scripts per HTML spec.

苏南大叔:浏览器执行es6模块,如何原生执行import、export语句? - wrong-mime
浏览器执行es6模块,如何原生执行import、export语句?(图9-6)

因为根据以往经验来说,es6的代码需要保存为.mjs文件。而这个格式是属于自定义格式,服务器往往会识别为application/octet-stream,而不是需要的application/javascript。这种情况下,浏览器是不会执行的这种类型的代码的。

这里还是以nginx为例,配置一下mime.types

application/javascript  mjs;

相关经验:

兼容性检测 nomodule

对于古老版本的浏览器,不支持type="module"属性的浏览器,可以通过下面的方法执行别的js。比如:

<script nomodule src="nomodule.js"></script>
这种情况下,nomodule.js会被下载,只不过不会被执行罢了。

或者:

<script nomodule>
alert("this browser not support es6 module");
</script>

在本文中,最新版本的chrome@100.0.4896.60是支持module的,所以上述代码并不会被执行。截图如下:

苏南大叔:浏览器执行es6模块,如何原生执行import、export语句? - chrome-nomodule-test
浏览器执行es6模块,如何原生执行import、export语句?(图9-7)

如果想测试被执行的效果,可以使用win10电脑里面自带的ie@21h2,就是不支持module的,但是自带的edge@100.0.1185.29是支持module的。截图如下:

苏南大叔:浏览器执行es6模块,如何原生执行import、export语句? - ie不支持module
浏览器执行es6模块,如何原生执行import、export语句?(图9-8)

苏南大叔:浏览器执行es6模块,如何原生执行import、export语句? - edge支持module
浏览器执行es6模块,如何原生执行import、export语句?(图9-9)

为啥edgechrome的版本号这么相似?

只会执行一次

对于同一个mjs(或者说设置type='module'.js),它只会执行一次,无论加载了几次。

<script type="module" src="1.mjs"></script>
<script type="module" src="1.mjs"></script>
<script type="module">
   import "./1.mjs";
</script>

如上1.mjs里面的代码只会执行一次。

参考文献

综述

chrome里面支持es6 module,但是不能双击html查看效果,记得放置在容器里面。es6 module需要保存为.mjs文件,但是这个后缀容器一般不认识,不会发出合适的header信息,导致浏览器无法识别。所以,保存为.js文件,也许是更加明智的选择。

也许浏览器原生支持这种写法后,似乎就有理由放弃webpack+babel的组合了。但是,这真的是本文的结论么?更多文章:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   es6