前言

梳理一下前端领域知识,也总结一下我对前端的认知。

假如看到这篇文章的你,是一名前端 starter,希望能帮到你更好地认识前端。

暂时解决前端入门的两大疑问:

  • 为什么一开始都是从 HTML、CSS、JS 学起,人们一提起前端就说是写 HTML、CSS 和 JS?
  • 为什么找工要会一种框架, react、vue 这些框架是怎么回事呢?

基础认识

解决第一个疑问,关于 HTML、CSS 和 JS。

前端的世界原点,大约就是在浏览器输入一行 url,然后,bingo,网页呈现!

从这原点出发,来聊一下我对前端的理解。

在浏览器地址栏输入 url,经过 DNS 域名解析,获取到这个 url 指代的网络 IP 地址,也就知道了,这个 GET 请求应该向网络上的哪台机器去请求资源。

这些资源是什么呢?HTML 文档、CSS 文件、JS 文件,或者还有一些其它资源(如图片)。
总的来说:

  • HTML 文档用来描述页面
  • CSS 文档用来修饰页面
  • JS 是对各种运行时刻动作的响应

资源文件已经备好,利用这些文件,浏览器可以布局出基础页面,且预设了应对用户的各种交互响应动作。

但是要把页面正确渲染,还需要数据,这些数据需要从后端(即服务端)获取。

浏览器网页内的 JS 如何向后端请求数据呢?

使用 Web API :XMLHttpRequestfetch,向后端接口请求数据。

为了更好的开发,封装了 axios (client 端基于 XHR 和 Promise)或其余自建工具 等网络请求库。
axios 可以自动转码 json 数据、处理响应结果、取消请求、支持客户端 XSCF 攻击防护 等等

获取到接口数据,我们就可以利用该数据和 JS 中的响应方法,渲染或更新页面节点。

此时,页面就完整了。

所以网站的基础资源就是 HTML、CSS 和 JS 文件。

各种各样的前端框架,无论代码编写方式如何( .jsx、.vue、.less ),最终都会 build 构建为 .HTML、.CSS 和 .JS,部署的话也是部署这些资源。

所以,从某种程度上 HTML、CSS 和 JS 确实可以代表前端,当然这是很久很久以前的年代了。

框架

当下,若你打算吃前端这碗饭,总会问/被问:

“一开始学什么框架比较好呢?”

“react / vue ?”

现在就来解决第二个疑问吧!react、vue 这些框架是怎么回事呢?

从 HTML、CSS 和 JS 可以拆分出两个方面:

  • 一是页面描述,HTML 和 CSS 负责
  • 二是页面更新,JS 负责

对于老大哥 jquery (一个 JS 库,用于简化 HTML 与 JS 之间的操作)来说,在这两方面分别是:

  • 页面描述的方法仍是 HTML 标签,例如 <h1>,通常说是节点。
  • 页面更新则使用指令式的 动作 语句,例如增加一个 child 元素,删除一个元素。

而现代 UI 框架,则是:

  • 在页面描述上,出于组件化思想,对 HTML 元素进行封装,把网页的视图层划分为:应用(即页面)、组件和节点。应用由多个组件构成,组件由元素节点和业务逻辑构成。其中的组件写法,目前最流行两种:JSX 和 模版 template。

  • 在页面更新上,出于数据驱动的思想,即数据更新,页面也就更新。UI 完成后,我们只需要关注数据。可以用一个公式来表示:UI = f(data),当然在前端我们更习惯于把数据 data 叫成状态 state,所以这个公式就这样写吧:UI = f(state)

    对于这个公式,UI 表示视图(页面),state 是状态,f 是框架内部的运行机制。一句话解释就是,框架内部运行机制根据状态来渲染视图。

用目前最流行也是最具代表性的 UI 框架来举例说明,分别是 svelte、react 和 vue。

对于组件中的 UI 描述:svelte 使用 template,react 使用 JSx,vue 默认使用 template(但也支持 JSx)

对于页面更新,也就是解释框架内部运行机制,其中:

  • svelte 的更新粒度在节点级别。使用预编译的方法,将状态变化可能导致节点变化编译为具体方法,并使用发布订阅的设计模式监听状态变化,当用户交互导致状态变化时,直接调用该状态对应方法改变对应视图。精确到状态的更新叫做细粒度更新。solid.JS 也是此种机制。
  • react 是应用级更新。使用虚拟 dom 树描述页面结构,当状态更新,会新生成一棵新的完整虚拟 dom 树,新旧两树同级 diff 差异,更新变化部分。所以 react 不关心具体某一状态的变化,因为只需要 diff 两棵树就可以了。
  • vue 则是组件级更新。它比较中庸,vue2 使用 虚拟 dom 和细粒度更新,只为改变状态的对应组件生成新的 dom 树,对变化节点进行更新。所以就是新生成组件级别的虚拟 dom 树,对节点级进行更新。vue3 还加上了预编译。

所以这些框架,就是一种新的用户界面构建方法。只不过从命令式的声明写法变成了描述式,我们只需要关注状态数据即可,极大提高了前端开发者体验。

ToDo

  • 总结 react hooks
  • 总结 数据状态管理方案
  • 总结 基础且重要的 CSS
  • 总结 移动端尺寸适配

工程化

工程化本来是个蛮久以后才讲的题(因为我还没有怎么涉及。。),但是既然问到了,那么我也就理理我目前粗浅的了解吧

前端项目研发的生命周期大致可以分为这三阶段,让我们分步阐述其中的工程化。

  • 项目搭建
  • 开发调试
  • 构建发布

项目搭建

项目搭建,简单来说就是初始化一个项目代码模板。这个初始代码模版,是一套开发和构建约定,开箱即用,帮开发者解决了例如热重载、lint 校验、构建指令等问题,开发者可以专注于自己的视图/业务逻辑编写。

如何引导获取一个初始化项目呢?使用 cli 命令行工具。

目前开发一个命令行工具,node 端的常用工具有:

  • commander ,node 命令行工具,可以自定义指令和任务执行
  • enquirer,命令行提示,获取用户输入的一种友好方式

跟随命令行提示一步一步走下来会获得一份模版代码的 clone,这份代码就是初始开发的脚手架了。

这份模板代码包含了一套开发工具的约定。

  • 一方面是技术栈的约定,开发者可以自行增添不同的技术选型。在 package.json 里通常是 dependencies 字段下的包。
  • 一方面是调试、测试或构建等方面的约定。在 package.json 里通常是 devDependencies 字段下的包。

这里主要讲一讲构建。什么叫构建呢?其实就是把开发者写的原始代码,如 ts、jsx、vue、less、scss等等非浏览器原生的代码文件,经过各种步骤最终生成一份可在浏览器环境直接运行的 html、js、css文件集。

为了做到这件事,我们需要用到如下工具,当然还有其它(前端轮子是真的多)

  • 打包工具:webpackrollupesbuild

    有这么多打包工具,没必要死磕传说中的老大哥 webpack 哈哈哈,不过了解一下它的最近更新也是很有意思的,例如 webpack5 的新特性 Module Federation 可以用来做打包提速方案

  • 转译工具:babel(使用 AST 作为中间介质,es5 -> es6+),tsc(typescript 的 ts->js 工具)

    注:以上工具的功能划分也不是那么绝对,应该说他们不只能做到这些事。

还有任务管理工具,面对各种不同的处理任务,我们需要一个工具来调度这些任务,这就是 Gulp,或者更古老一点的 Grunt 了。

这里其实是开发模板的人头秃,对于业务开发者来说,这就是一套合理的默认约定,业务开发者只需要专注代码编写即可。

对于(没进厂务工)的野生开发者(如现在快乐的我)来说,也有 vue-cli、nuxt、next、umi 等优秀的开源工具使用。但也只是默认约定,假如有个性化需求,那么就自己钻研下文档整一整吧。

开发调试

调试的环境分两种,一个是 local,一个是 remote。我们通常开发调试使用的都是 local 的浏览器环境。至于 remote 远端环境,则是属于(厂内人员的)进阶需求,这里不细讲。

而开发中的调试,这在开发服务器的职责范围内。

什么是开发服务器呢?简单来说,在我们运行项目代码,输入类似 yarn dev 这样的启动指令时,其实就启动了一个本地开发服务器。这个服务器类似于大家基本都用过的 tomcat/apache,浏览器打开 localhost: port/index.html向该服务器请求资源(html、js、css 、图片等),你的项目就可以进行正常页面呈现了。

同时,开发服务器不只是运行 html 代码,还需要做到一些其它功能以提高开发体验,例如热更新

关于热更新,有走 bundle (打包)路线的开发服务器(如使用 webpack 驱动),需要在修改后,再编译打包一遍,浏览器才会更新,对于大型项目来说,等到更新时间可能很长。还有走 no-bundle 路线的开发服务器(vite),则去掉了打包这一步骤,可以极速刷新。

同时,为了资源请求和快速刷新,开发服务器需要做很多优化处理。例如 vite 基于浏览器原生 esmodule 加载,在去掉打包这一步骤的同时,需要加载大量的小模块,造成了大量的并发 http 请求,这就是需要优化的点。而 vite 的开发者尤大就使用了依赖预打包和 http 缓存来解决这个问题。

构建发布

构建其实在上面的项目搭建已经讲了,简单来说就是使用一系列工具把代码转化为浏览器能识别的 html、js、css文件。

至于发布,大厂通常有自己的一套云发布流程。这方面的工程化,主要是和集团部署平台的 API 交互,以减少开发者的操作复杂度。

又到了野生快乐开发者部分。我通常走的是快乐白嫖路线,例如 github 的 action 功能,自己编写一个 workflow 文件,在每次指定分支 push 更新的时候,都会按照编写的文档,依次进行 build,最后发布到 github page。

参考