Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

深入浅出浏览器中的ES modules #66

Open
forthealllight opened this issue Nov 19, 2020 · 0 comments
Open

深入浅出浏览器中的ES modules #66

forthealllight opened this issue Nov 19, 2020 · 0 comments

Comments

@forthealllight
Copy link
Owner

forthealllight commented Nov 19, 2020


    主流浏览器陆续都已经开始支持es modules,此外一些Bundless的工具,比如snowpack、vite等。此外给予浏览器的ESM也可以实现一些前端微服务,本文主要介绍一下什么是浏览器中的ESM

  • import & export
  • import.map
  • import.meta
  • 浏览器中esm的兼容问题

一、import & export

    首先我们来看主流浏览器对于ES modules的支持情况:

Lark20201119-151747

    从上图可以看出来,主流的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的提案可以参考:https://github.com/WICG/import-maps。

    我们直接来看例子:

//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返回是浏览器特有的元属性,返回加载模块的那个<script>元素,相当于document.currentScript属性

    此外值得注意的是import.meta不仅仅是可读的,也是可写的,整体作为模块的元数据,比如在snowpack中会往import.meta中写入以下数据:

Lark20201119161252

四、浏览器中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'
    }
 })
@forthealllight forthealllight changed the title 深入浅出浏览器中的ES module 深入浅出浏览器中的ES modules Nov 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant