「软件设计思想杂谈🤔」“切图仔”也能懂编译原理?框架源码也许没那么难。聊聊 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源码大概由几部分组成?每个部分的作用是什么?用的什么样的方式去实现的?虽然不能说是精通,但是也是极大的提升了我对编码的看法(😂但是还是会写出屎),总之我的体感上是学习源码能让我更好的管理我编写的代码

相关推荐
禅思院2 小时前
路由性能高可用架构实战方案
前端·架构·前端框架
IT_陈寒2 小时前
React状态更新总是不及时?你可能漏了这步批处理机制
前端·人工智能·后端
恋猫de小郭2 小时前
AI Agent 开发究竟是啥?如何用 AI 开发 Agent ?深入浅出给你一套概念
android·前端·ai编程
前端双越老师2 小时前
我开发 AI Agent 项目踩过的 5个坑
前端·agent·全栈
晓得迷路了2 小时前
栗子前端技术周刊第 134 期 - React Router v8、TypeScript 7 RC、React Native 0.86...
前端·javascript·react.js
Carson带你学Android2 小时前
Android 17 正式发布:AI 终于成了系统能力
android·前端·ai编程
Mike_jia3 小时前
ZbxTable:Zabbix开源报表神器,从运维数据到决策洞察的最后一公里
前端
LinXunFeng12 小时前
Obsidian - 使用 Share Note 分享笔记并自部署
前端·笔记·github
乘风gg16 小时前
为什么AI 时代来临,大部分人吃不到红利
前端·ai编程·claude