主流浏览器陆续都已经开始支持es modules,此外一些Bundless的工具,比如snowpack、vite等。此外给予浏览器的ESM也可以实现一些前端微服务,本文主要介绍一下什么是浏览器中的ESM
- import & export
- import.map
- import.meta
- 浏览器中esm的兼容问题
一、import & export
首先我们来看主流浏览器对于ES modules的支持情况:
从上图可以看出来,主流的Edge, Chrome, Safari, and Firefox (+60)等浏览器都已经开始支持es modules。
对于es modules,我们并不陌生,什么是es modules也不是本文的重点,一些流行的打包构建工具比如babel、webpack等早就支持es modules。
我们来看一个最简单的es modules的写法:
//main.js
import a from 'a.js'
console.log(a)
//a.js
export let a = 1
上述的es modules就是我们经常在项目中使用的es modules,这种es modules,在支持es6的浏览器中是可以直接使用的。
我们来举一个例子,直接在浏览器中使用es modules
<html lang="en">
<body>
<div id="container">my name is {name}</div>
<script type="module">
import Vue from 'https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.esm.browser.js'
new Vue({
el: '#container',
data:{
name: 'Bob'
}
})
</script>
</body>
</html>
上述的代码中我们直接可以运行,我们根据script的type="module"可以判断浏览器支不支持es modules,如果不支持,该script里面的内容就不会运行。
我们再来看一种调用方式,我们也可以通过script标签来直接引入相对路径或者绝对路径的模块。
//html
<script type="module" src="/index.js"></script>
//index.js
import Vue from 'https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.esm.browser.js'
new Vue({
el: '#container',
data:{
name: 'Bob'
}
})
二、import.map
上述的调用中我们通过绝对路径或者相对路径的形式来import,这种方式跟我们在之前的代码中有点区别,我们希望的是通过:
import Vue from 'vue'
这种简单的方式来引入一个npm包,就像我们在之前bundle时书写格式一致,那么浏览器中如何支持这种写法呢,答案就是使哟过import.map。import.map的提案可以参考:github.com/WICG/import…
我们直接来看例子:
//html
<script type="importmap">
{
"imports":{
"vue":"https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.esm.browser.js"
}
}
</script>
<script type="module" src="/index.js"></script>
//index.js
import Vue from 'vue'
new Vue({
el: '#container',
data:{
name: 'Bob'
}
})
通过importmap,我们可以直接在业务代码中使用:
import Vue from 'vue'
三、import.meta
在浏览器中我们有全局上下文window,在node中我们有全局上下文global,同理可以引入一个对象作为某一个module的上下文元数据。该对象就是import.meta对象,这个对象在模块中用于存取上下文数据,可读也可以写。
(1)import.meta.url
import.meta.url返回当前模块的 URL 路径。
<script type="module" src="/index.js"></script>
//index.js
console.log(import.meta.url) //输出http://localhost:8080/index.js
(2) import.meta.scriptElement
import.meta.scriptElement返回是浏览器特有的元属性,返回加载模块的那个
此外值得注意的是import.meta不仅仅是可读的,也是可写的,整体作为模块的元数据,比如在snowpack中会往import.meta中写入以下数据:
四、浏览器中esm的兼容问题
对于不支持es modules或者部分支持es modules的浏览器,我们可以通过systemjs来兼容。systemjs就是对于浏览器es modules的polyfill。
直接来看通过systemjs来实现es modules的使用方法:
//html
<script type="systemjs-importmap">
{
"imports":{
"vue":"https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.esm.browser.js"
}
}
</script>
<script type="module" src="/index.js"></script>
//index.js
System.register(['vue'], ()=>{
let Vue
return {
setters: [ v=> Vue]
}
});
new Vue({
el: '#container',
data:{
name: 'Bob'
}
})