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/[email protected]/dist/runtime-dom.esm-browser.js",
            "vue/server-renderer":"https://cdn.jsdelivr.net/npm/@vue/[email protected]/dist/server-renderer.esm-browser.js"
        },
        "scopes":{}
    }
</script>

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

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

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

利用路由 hash 实现分享功能

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

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编译报错提示的errorcompileFile 这个方法稍后再看,先略过 这里主要是收集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. 简单介绍了hashhistory模式的区别。
  3. 介绍了playground分享功能利用hash模式的实现。
  4. 使用hash模式下利用fflate对数据进行压缩、解压。
  5. 介绍了核心源码useVueImportMap 和 useStore的实现逻辑
相关推荐
海螺先生几秒前
Cursor 高阶使用指南:AI 辅助开发的深度整合
前端
我在北京coding1 分钟前
Uncaught ReferenceError: process is not defined
前端·javascript·vue.js
Hilaku2 分钟前
我为什么觉得 React 正在逐渐失去吸引力?
前端·react.js·前端框架
用户52709648744904 分钟前
🎨 Stylelint:让你的 CSS 代码优雅如诗
前端
日升4 分钟前
AI 组件库-MateChat 组件大全与主题定制
前端·ai编程·trae
龚思凯7 分钟前
TypeScript 中 typeof 的全面解析:从基础用法到高级技巧
前端·typescript
itslife9 分钟前
实现 render 函数 - 初始化更新队列
前端·react.js·前端框架
baozj10 分钟前
一次表单数据复用引发的 Bug:理解 Vue 中的 data 为何是函数
前端·javascript·vue.js
LRH12 分钟前
JS基础 - instanceof 理解及手写
前端·javascript
leefirm12 分钟前
node 切换版本,每次打开都是切换前的版本怎么办?Node.js 版本管理神器 NVM 完全使用指南
前端