「软件设计思想杂谈🤔」“切图仔”也能懂编译原理?框架源码也许没那么难。聊聊 Vue 的编译(上)

Hi!这里是JustHappy ,作为一个标准的"切图仔",如何轻松的拿捏Vue或者React的框架源码呢?一行一行的看?一处一处的打断点?太磨人了,我们换种方式,直击重点!今天我们从编译原理 ,也就是编译器的角度聊聊吧!

编译原理真的那么高大上吗?

仔细回想,其实从大学第一节C语言课开始我们就接触了"编译原理",众所周知,C语言是一门"高级语言",是计算机所不能直接读懂的语言,对于一个.c的文件我们需要对其进行如下操作:预处理 → 编译 → 汇编 → 链接 ...... 好的,你成功的睡着了...

所谓"编译原理"并不是什么新兴概念,几乎从软件工程诞生的最开始时候就有了

它只是:把一种东西 变成另一种东西

其实很常见例如:

C代码 ----> 机器码
TypeScript ----> JavaScript
Vue模板 ----> Render函数

本质都是同一个事情。

哈哈还不清楚没事,至少我们已经知道这不是啥"高不可攀"的东西,而且我们这次只讲 "编译",是不是轻松很多呢?

所以话不多说,我们开始吧!

简单的来说编译就只有几个步骤,为了缩短篇幅,我们直接就着Vue讲吧🚀🚀

.vue.js,需要几个步骤

众所周知,我们的浏览器是只能处理JavaScript、Css和Html的,而我们在编写Vue的时候是写在一个.vue文件中的,就像下面这样一个简单的组件:

html 复制代码
<template>
    <div>Hello {{ name }}</div>
</template>

<script setup> 
    const name = 'JustHappy' 
</script>

问题来了。浏览器认识这个东西吗?显然不认识。

浏览器只认识:

  • HTML
  • CSS
  • JavaScript

所以在浏览器运行之前。

一定有人把它翻译成浏览器认识的代码,这个翻译的人,就是:Vue Compiler

如何读懂.vue 文件呢? Webpack loader给你解决

我们都知道.vue文件是Vue 自己设计出来的文件格式。

比较官方的概念是Single File Component

顾名思义:"一个组件 一个文件"

把原本分散的:

HTML CSS JavaScript

全部塞进同一个文件里。对于开发者来说确实舒服了:

组件逻辑在这里 模板在这里 样式也在这里

维护起来非常方便。

但是浏览器读不懂啊?于是就需要 Webpack loader

其实Webpack loader就干一件事:让 webpack 可以识别任意后缀的文件

其大致原理就是将下面这个.vue 文件 拆解 为 "HTML 、CSS 、JavaScript"

(注意:是以 JS module 的形式拆解)

html 复制代码
<template>
    <div>Hello {{ name }}</div>
</template>

<style scoped> 
    .red { color: red; } 
</style>

<script setup> 
    const name = 'JustHappy' 
</script>

以上例子在经过 vue-loader 后大致会变成下面这样

js 复制代码
import { render } from './App.vue?type=template'
import script from './App.vue?type=script'
import './App.vue?type=style'

script.render = render

export default script

具体 Loader 的原理可以参照 www.webpackjs.com/loaders/

如何编译?为什么要这么编译?

经过上面我们把 .vue 文件拆开来之后会发现,其实对于 JS、CSS 部分的处理都比较简单。

JS 本来就是 JavaScript。

CSS 本来就是 CSS。

最多做一些语法糖转换或者兼容性处理。

而对于 template 中的内容,我们就不能直接把它当成 HTML 了。

哈哈,HTML 可不能写:

html 复制代码
<div v-if="isLogin">
  用户中心
</div>

// 或者

<li v-for="item in list">
  {{ item }}
</li>

这些都属于 Vue 自己扩展出来的语法。

这种为了某个特定领域而设计的语言,我们一般称为:

DSL(Domain Specific Language) 领域专用语言

而 Vue Template 就是一种专门用于描述界面的 DSL。

既然是一门语言,那么编译器就必须先「看懂」它。

但是计算机其实不擅长直接处理字符串

例如对于:

html 复制代码
<div class="app">
  <span>{{ msg }}</span>
</div>

编译器首先会把它转换成一种更容易处理的数据结构。

这个过程叫:parse 解析。

那么完成这个过程的代码就可以叫做: parser 解析器。

解析后的结果大致会变成:

json 复制代码
{
  type: 'Root',
  children: [
    {
      type: 'Element',
      tag: 'div',
      props: [
        {
          name: 'class',
          value: 'app'
        }
      ],
      children: [
        {
          type: 'Element',
          tag: 'span',
          children: [
            {
              type: 'Interpolation',
              content: 'msg'
            }
          ]
        }
      ]
    }
  ]
}

这个结构在软件工程中称为:

AST(Abstract Syntax Tree) 抽象语法树

名字听起来很唬人,其实本质上就是:把字符串 变成对象

这样编译器后续就不需要对着一大坨字符串做分析了,而是可以像操作普通 JavaScript 对象一样去遍历、查找和修改节点。

接下来 Vue Compiler 会在 AST 的基础上继续处理,我们下篇再聊...

我们为什么要学习源码?

难道说是为了卷吗?我想不是的,在学习Vue源码之前,我也是认为这是"卷",而且学的迷迷糊糊的。不过大体上过了一遍,也就是脑袋里有个印象,Vue源码大概由几部分组成?每个部分的作用是什么?用的什么样的方式去实现的?虽然不能说是精通,但是也是极大的提升了我对编码的看法(😂但是还是会写出屎),总之我的体感上是学习源码能让我更好的管理我编写的代码

相关推荐
尾善爱看海7 小时前
Vue 面试收官篇:SSR、性能优化落地、30 道高频面试题精讲(附标准答案)
前端·javascript·vue.js·面试·vue
weixin_BYSJ19877 小时前
【计算机毕设】基于SpringBoot与Vue的文物保护档案管理系统08621
vue.js·spring boot·spring cloud·微服务·架构·django·课程设计
Bs_MoneyMagnet7 小时前
基于springboot+vue的个人健康管理系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·vue3·springboot3·计算机毕业设计
驳是7 小时前
一个组件,提升 react-router 开发的幸福感
前端·preact
GreenTea7 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
星云API技术支持8 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
京东云开发者8 小时前
81.8 秒的视频,我们改了 15 个版本:一次纯 Codex 驱动的 AI-native 视频实践
前端·aigc
Csvn8 小时前
TypeScript 大型项目架构:从单体 tsconfig 到分层可扩展的工程
前端
Bs_MoneyMagnet10 小时前
基于springboot+vue的心理咨询预约与随访平台的设计与实现 源码+文档
vue.js·spring boot·后端·spring·毕业设计·旅游·计算机毕业设计
计算机魔术师10 小时前
Dario Amodei 发文呼吁为前沿 AI 降速并提出三点计划
前端