浏览器执行es6模块,如何原生执行import、export语句?
发布于 作者:苏南大叔 来源:程序如此灵动~计算机代码世界更新太快,现在浏览器不用babel
编译,就可以执行es6
模块了。也就是说,如果不考虑兼容性的问题的话,在浏览器环境下,使用js
的新语法,也是可能的了。喜大普奔?(假装喜大普奔ing)。
大家好,这里是苏南大叔的“程序如此灵动”博客,这里记录苏南大叔和计算机代码的故事。本文记录谷歌浏览器原生支持import
和export
等es6 module
语句的故事。本文测试环境:win10
,chrome@100.0.4896.60
,ie11@21h2
,edge@100.0.1185.29
。
准备素材
如果大家对于es6 module
的import
和export
是怎么回事,还不是很清楚的话。可以先查看下面的文章:
这里就简述一个最简单常见的情况了: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.html
和lib.js
文件放到www
容器里面,通过浏览器访问站点的方式使用。
错误的使用姿势
浏览器里面对于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
错误二:不写type="module"
Uncaught SyntaxError: Cannot use import statement outside a module
错误三:被导入文件的路径写法
这里,还需要注意一个写法,就是import from
后面的文件路径,不支持那种不带有任何路径修饰的写法。比如:lib.js
不行,目前本文的测试中是永远不会通过的,比如至少都需要一个./
。虽然大家的意识里面,两者是同一个意思。但是,这里的测试环境下,就是不一样的结果。
Uncaught TypeError: Failed to resolve module specifier "lib.js". Relative references must start with either "/", "./", or "../".
错误四:不被浏览器认识的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
的代码需要保存为.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
的,所以上述代码并不会被执行。截图如下:
如果想测试被执行的效果,可以使用win10
电脑里面自带的ie@21h2
,就是不支持module
的,但是自带的edge@100.0.1185.29
是支持module
的。截图如下:
为啥edge
和chrome
的版本号这么相似?
只会执行一次
对于同一个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
里面的代码只会执行一次。
参考文献
- https://newsn.net/say/nginx-apache-font.html
- https://newsn.net/say/es6-module.html
- https://newsn.net/say/node-run-es6.html
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Modules
综述
chrome
里面支持es6 module
,但是不能双击html
查看效果,记得放置在容器里面。es6 module
需要保存为.mjs
文件,但是这个后缀容器一般不认识,不会发出合适的header
信息,导致浏览器无法识别。所以,保存为.js
文件,也许是更加明智的选择。
也许浏览器原生支持这种写法后,似乎就有理由放弃webpack
+babel
的组合了。但是,这真的是本文的结论么?更多文章:
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。