Vue Playground 演练场源码解读(二)
在《Vue Playground 演练场源码解读(一)》中咱们学习到了:
- 动态获取版本,并且简单了解了下
jsdelivr
。 - 动态设置高度
?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
方法主要用来控制界面以下功能:
- 记录选中的
vue
版本vueVersion
,没选中就用默认的。 - 记录是不是生产模式
productionMode
。 - 根据以上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'
}
}
总结
本篇中咱们学习到了:
importmap
的相关用法。- 简单介绍了
hash
和history
模式的区别。 - 介绍了
playground
分享功能利用hash
模式的实现。 - 使用
hash
模式下利用fflate
对数据进行压缩、解压。 - 介绍了核心源码
useVueImportMap 和 useStore
的实现逻辑