Vue Playground 演练场源码解读(二)

Vue Playground 演练场源码解读(二)

在《Vue Playground 演练场源码解读(一)》中咱们学习到了:

  1. 动态获取版本,并且简单了解了下jsdelivr。
  2. 动态设置高度
  3. ?raw 是做什么的,以及jszip配合file-saver的下载项目.

在本篇中,咱们主要讲解一下:@vue/repl包中的一些源码。@vue/repl是整个playground演练场的核心, @vue/repl主页地址

接下来还是会一步步的对代码块进行拆分,先了解基础技术,才能读懂该源码的精髓。

importmap

在浏览器中直接运行 ES 模块(<script type="module">)时,模块标识符(如 import Vue from 'vue')必须是完整的 URL 或相对路径。浏览器无法像 Node.js 或构建工具(如 Webpack)那样自动解析 node_modules 中的依赖。

Import Maps 提供了一种机制,将简写的模块名(如 'vue')映射到具体的 CDN URL,从而让浏览器能正确加载依赖。

html 复制代码
<script type="importmap">
      {
        "imports":{
            "vue":"https://cdn.jsdelivr.net/npm/@vue/runtime-dom@3.5.13/dist/runtime-dom.esm-browser.js",
            "vue/server-renderer":"https://cdn.jsdelivr.net/npm/@vue/server-renderer@3.5.13/dist/server-renderer.esm-browser.js"
        },
        "scopes":{}
    }
</script>

Playground 需要允许用户动态切换 Vue 版本或添加其他依赖,而无需重新构建或预配置。

Playground 通常在 iframe 沙盒中运行,限制了文件系统访问和网络请求。使用 Import Maps 配合 CDN 资源,可以确保所有依赖都通过受控的 HTTPS 加载,避免安全风险。

这里咱们先了解下importmap的用法,后面在去讲Playground中实际去应用。

利用路由 hash 实现分享功能

这里可能有些同学不是太了解路由的模式,先解释下路由模式hash 和 history的区别:

hash模式:

https://www.baidu.com/#/home带一个#号,就是hash模式。

特点是不回携带路由去请求服务器,访问后端是https://www.baidu.com/,缺点是 URL 看起来不够"干净"。

history模式:

https://www.baidu.com/home优点是 URL 更美观,更符合传统的网址结构,缺点是需要后端服务器的支持,因为服务器需要正确处理这些路径。就是请求服务会携带路由。

回到Playground中,利用hash模式,来进行传值,就是文件内容都在hash中。get 请求中如果是字符过长会溢出 (Chrome:8182字符),使用hash模式就不会有该问题了。

分享功能 给别人查看你的代码就是这么实现的。

当然官方对hash字符还进行了一系列压缩处理,处理如下:

可以看到利用了fflate这个包实现的压缩,fflate是一个快速、轻量级且纯 JavaScript 实现的压缩库,用于处理 gzip、zlib 和 Deflate 格式的数据压缩与解压缩。

以后有需要压缩的场景可以直接使用这种方式,对压缩原理比较感兴趣的可以去看下zlibSync、unzlibSync方法

以下图函数serialize deserialize是对文件的处理:

大致就是对file的压缩以及解压。

useVueImportMap 和 useStore

useVueImportMap方法主要用来控制界面以下功能:

  1. 记录选中的vue版本vueVersion,没选中就用默认的。
  2. 记录是不是生产模式productionMode。
  3. 根据以上1、2 俩字段动态生成需要的引入依赖的importmap。

代码如下:

useStore 方法主要是全局对files的处理,以及当前选中了那个file如下图所示:

还有部分针对files编译报错提示的error, compileFile 这个方法稍后再看,先略过 这里主要是收集error信息的

js 复制代码
watchEffect(() => {
  compileFile(store, activeFile.value).then((errs) => (errors.value = errs))
})

界面展示报错信息

files是一个对象,key是文件名,value是File类实例,如下:

js 复制代码
export class File {
  compiled = {
    js: '',
    css: '',
    ssr: '',
  }
  editorViewState: editor.ICodeEditorViewState | null = null

  constructor(
    public filename: string,
    public code = '',
    public hidden = false,
  ) {}

  get language() {
    if (this.filename.endsWith('.vue')) {
      return 'vue'
    }
    if (this.filename.endsWith('.html')) {
      return 'html'
    }
    if (this.filename.endsWith('.css')) {
      return 'css'
    }
    if (this.filename.endsWith('.ts')) {
      return 'typescript'
    }
    return 'javascript'
  }
}

总结

本篇中咱们学习到了:

  1. importmap 的相关用法。
  2. 简单介绍了hash和history模式的区别。
  3. 介绍了playground分享功能利用hash模式的实现。
  4. 使用hash模式下利用fflate对数据进行压缩、解压。
  5. 介绍了核心源码useVueImportMap 和 useStore的实现逻辑
相关推荐
椒哥3 小时前
一天被问几十次"允许",我统计了 517 次,然后写了个插件
前端·javascript·github
风骏时光牛马3 小时前
生成一个AI稳定性治理及疑难问题分析标题,只需要一个标题,不需要其他的任何文本。
前端
莫西干式秃头3 小时前
用 AI + threejs 写了个浏览器里的 3D 动作游戏《武来》:砍怪、放技能、开 SU7
前端·人工智能·three.js
kyriewen3 小时前
我测了 6 种防请求竞态的写法:只有 1 种真能打
前端·javascript·程序员
孟健3 小时前
用 WorkBuddy 做个人名片网页,挂上开源设计技能后效果完全不同了
前端·人工智能·ai编程
IT_陈寒3 小时前
SpringBoot自动配置的坑,这次终于爬出来了
前端·人工智能·后端
LuHang4 小时前
从天地图切换到高德地图:一次真实的底图迁移实战
前端·vue.js·cesium
用户360055579004 小时前
Kestrel_VLLM - 27 · 寄存器常驻与融合发射:两次「少发一次」
前端
前端小万4 小时前
用"道法术器"重构你和 AI 的协作方式
前端·人工智能·程序员
鶴哥只手遮天5 小时前
Angular 22 源码级深度解析-第 06 章 模板指令全解:`ɵɵelementStart`、`ɵɵproperty`、`ɵɵadvance` 与绑定指令
前端·开源·angular.js