写点什么

前端之变(三):变革与突破

用户头像
微言码道
关注
发布于: 刚刚

本周,我将继续就前端之变阐述自己的思考,这一次讲到前端之变的重点:变革与突破


这是前端之变系列的第三篇文章,前两篇分别是:


  1. 前端之变(一):技术的变与不变

  2. 前端之变(二):不变的前端


同样,在具体说到前端究竟发生了哪个改变前,我们要理解变化的本质原因是什么

前端之困:被限于浏览器的支持中

回到上一篇我讲的不变前端中,我在文章中明显的指出了,前端的变化会有一个分界线,在这个分界线之前,前端有一个最大的困境,就是:


前端技术始终被限制在浏览器的范围之内,无法突破


无论是 HTML,CSS 或是 JS,它们的能力永远限制在浏览器这个容器内,当然前些年流行的 JQuery,Boostarp 这一类的技术框架也是这样,如果认真分析,会发现它们的能力始终在浏览器之内。


我们可以逐一分析前端的核心技术来窥视这种能力限制。


HTML


html 主要是来展现内容的技术,最简单的一个 HTML 如下:


<!DOCTYPE html><html><head><title>html示例</title></head><body>  <h1>Hello,Html</h1></body></html>
复制代码


如果我们把 HTM 与非前端的一些技术框架,比如后端的 FreeMarker 脚本技术相类比


<html><head>  <title>freemarker示例</title></head><body>  <h1>Welcome ${user}!</h1>  <p>Our latest product:  <a href="${latestProduct.url}">${latestProduct.name}</a>!</body></html>
复制代码


显而易见,如果我们抛开 JS 的能力,单纯就 HTML 来说,它的不足与限制非常明显


  • 本身不具备动态渲染能力,简单的变量,if,for 循环完全做不到。

  • 难以将一个复杂的页面拆成不同的小页面来实现。一个页面就是一个 HTML,甚至在一个 HTML 中引入另一个 HTML 中这种简单的事都做不到(不依赖 JS)


根本原因在于,浏览器只提供了根据 HTML 内容渲染出页面展现用户的能力,浏览器并未向 HTML 提供任何动态能力,如基本的 if,else,for 等能力支持。HTML 不可能脱离浏览器而发展出任何类似的能力。


这也是为什么前些年,页面是由后端技术把持的原因所在,单纯的 HTML 能力实在太差,就算结合 JS 的动态能力,也根本无法应对复杂页面。大而划小,分而治之在那个时候对前端来说是压根不可能做到的事情。


JavaScript


当然,浏览器是用另一种方案来解决这个问题的,也就是 JavaScript,由于 HTML 本身只能做内容展现,其能力实在有限,解决方案是,提供一种脚本语言,这就是 JavaScript 的来源。


JavaScript 最初的设想非常简单,提供一些浏览器客户行为支持,以避免昂贵的服务端渲染,比如提交数据前验证数据是否完整,准确等。基于这种简单的设想,JavaScript 的设计也非常简单,就做成了一个简单的脚本式语言,没有块级作用域、模块、子类型等现代语言的一些特性。


出于这种最初的设计的原因,JavaScript 于是始终表现的不像一个现代语言,其各种设计与语言特性,用好听的词来形容就是:"别树一帜"。


我们可以将 Java 与 Swift 去比较,也可以与 OC,Kotlin 去比较,因为它们很像,都属于同一阵营。但与 JavaScript 相比,没有任何必要,因为没法比较。


事实上,JavaScript 连一种基本的能力在很长的时间内都不具备:


在一个 JS 中引入另一个 JS


终于在 ES6 的时代,JavaScript 设计与引入了 modules 的概念,支持 import 了。


但如我在上一篇文章所讲,真正来说,现在互联网的主流还是 ES5,而不是 ES6。


原因在于:浏览器不支持


CSS


再来说,CSS 是样式。CSS 的能力与 HTML 基本一致,就是简单的样式定义


body {  background-color: lightblue;}
h1 { color: white; text-align: center;}
复制代码


与 HTML 一样,在 CSS 的世界中


  • 没有任何动态能力,if,for 等基本语法不被支持

  • 谈不上将复杂的样式大而划小,分而治之。当然你可以将一个 CSS 拆成很多小 CSS,但第一它们相互之间无法引用,只能统一被 HTML 引用,更者也谈不上相互之间存在任何继承,接口或抽象实现等概念,比如定义一个基本色,在其它 CSS 中引用这个基本色,这个在 CSS 中居然都无做到,因为 CSS 没有变量的概念


所以,我们可以明显看出,在『前』前端的时代,前端各种技术发展的能力始终受限于浏览器的支持。被困于浏览器之中。浏览器因为安全的问题,甚至连读取本地操作系统文件的能力都不会提供给这些技术。


由于浏览器提供的能力有限,这就造成了前端始终难以发展现能与其它现代语言相比的语言设计与框架,比如


  • 面向对象的能力特性,继承,封装,多态在前端技术中不知道如何实现

  • 很像将一些设计原则应用到前端,如单例,工厂,观察者等

  • 谈不上在应对复杂软件时的核心解决方案:『大而划小,分而治之』


当然,这些已经成为过去式,由于一个本质的突破,就是


突然有一天,前端发现自己的技术不再受到浏览器的限制

突破,与浏览器说拜拜

终于,在越过一条明显的分界线后,前端技术的发展出现了突破:


虽然在最终产物阶段,仍受限于浏览器,但在编码阶段,技术的发展与能力与浏览器再无关联


由于不再受到浏览器的限制,前端的技术开始突飞猛进,五花八门,包括但不限于:


  • 由于 JavaScript 比较糟糕,出现了 TypeScript 这样的与 Java 现代化语言非常相近的技术替代 JavaScript

  • 在 HTML 方向,出现了 React,Vue 等组件式的框架

  • 为应对复杂样式的需要,演进出了具备编程能力的样式,如 less,sass 等


我们还是从前端的三个核心技术逐一分析


HTML


React 与 Vue 等类似框架在编码阶段彻底取代了单纯的 HTML,一个简单的 React 的页面可能是这样:


const numbers = [1, 2, 3, 4, 5];const listItems = numbers.map((number) =>  <li>{number}</li>); ReactDOM.render(  <ul>{listItems}</ul>,  document.getElementById('root'));
复制代码


就算从上面简单的代码也可以看出,与 HTML 相比,React 等这些技术能做到


  • 支持基本的编程能力,if,for 等都可以使用

  • 支持组件化能力,把一个大的页面拆成不同的组件与页面。



比如在 PCX 中,对于聊天,聊天分很多种类,比如文本,图片,语音,在 React 中,你可以将这个复杂的页面大而划小,分而治之



如上图所示:每一种消息类别 ,使用一个独立的子类来实现。


这种就完全具备了现代化语言的能力。在以前的 HTML+JS 的时代,完全没有办法做到。


JavaScript


在『后』前端的阶段,并不能说 JavaScript 是被 TypeScript 取代了,现状只能说是 TypeScript 更流行,越来越受到欢迎。但 JavaScript 仍然大量存在,仍然是不可替代的。


TypeScript 虽然最终仍然被翻译成 JavaScript,它也无法取代 JavaScript,但相比 JavaScript,TypeScript 对前端仍然具有里程碑的意义,从某种程度上说:


TypeScript 使得前端第一次也具有了面向对象的语言


export class SessionRepository extends ISessionRepository {

protected getRepository():IRepository{ return BaseRepository.getInstance().getRepository(); } /** * 删除一个会话 * @param sessionId */ public async deleteSession(sessionId:string):Promise<boolean>{ const deleteSQL = "delete from session_ where identifier = $sessionId"; return this.getRepository().executeUpdate(deleteSQL,{ $sessionId:sessionId }); }
}
复制代码


上面的 TS 代码来自于我在 20 年的 PCX 中的代码片段。


我们可以完全看到,相比于 JavaScript,TypeScript 更像 Java。如果让一个后端 Java 人员和一个前端 JavaScript 人员同时来学习,Java 人员会学习的更快,因为 TypeScript 是类似 Java 的面向对象的语言。


理所当然的,包括面向对象的五大基本原则:


  • 单一职责原则

  • 里氏替换原则

  • 开闭原则

  • 依赖倒转原则

  • 接口隔离原则


以及大家熟悉的二十多种设计模式,如工厂模式,观察者模式,命令模式等,在 TypeScript 都可以没有障碍的使用。


但在 JavaScript 的语言中,至少我不太清楚要怎么才能做到。


CSS


在『后』前端时代,由于突破了浏览器的限制,自然出现了更好的 css 的替代者。


比如 less


其实 less 总体上与 css 基本一致,它也并未提供任何新的 css 样式,它的区别只是在单纯的静态 CSS 样式基础上,添加了一些动态能力,比如变量,函数等


@width: 10px;@height: @width + 10px;
#header { width: @width; height: @height;}
.class { //通过函数来计算 width: percentage(@width); // returns `50%` color: saturate(@base, 5%); background-color: spin(lighten(@base, 25%), 8);}
复制代码

更多

即然突破了浏览器,那自然整体技术发展也不会只局限在 HTML,JS 以及 CSS 三个维度了,因为没有了浏览器的限制,在编码阶段,前端出现了更多的突破性的技术,最典型的代表就是:npm 依赖管理


其实,区分你是在『前』前端阶段,还是在『后』前端阶段的一个最简单的识别手段就是:


你是否使用了 npm 依赖管理


因为:


在『前』前端阶段,这个是绝无可能做到的。npm 依赖管理需要大量的读取及分析本地文件,在这个基础之上才能做到


{  "name": "taoofcode",  "version": "1.0.0",  "private": true,  "description": "微言码道",  "author": "lingen.liu",  "keywords": [    "gatsby"  ],  "license": "0BSD",  "dependencies": {    "@fika/gatsby-source-cockpit": "^1.1.2",    "@material-ui/core": "^4.11.2",    "@material-ui/icons": "^4.11.2",    "@material-ui/lab": "^4.0.0-alpha.57",    "@mdx-js/mdx": "^1.6.22",    "@mdx-js/react": "^1.6.22",    "@types/react-helmet": "^6.1.0",    "gatsby": "^2.26.1",    "gatsby-image": "^2.8.0",    "gatsby-plugin-css-modules-typings": "^1.0.1",    "gatsby-plugin-google-analytics": "^2.9.0",    "gatsby-plugin-less": "^4.4.0",    "gatsby-plugin-manifest": "^2.9.1",    "gatsby-plugin-material-ui": "^2.1.10",    "gatsby-plugin-mdx": "^1.7.1",    "gatsby-plugin-react-helmet": "^3.7.0",    "gatsby-plugin-sharp": "^2.11.2",    "gatsby-plugin-sitemap": "^2.9.0",    "gatsby-remark-prismjs": "^3.10.0",    "gatsby-source-filesystem": "^2.8.1",    "gatsby-transformer-remark": "^2.13.1",    "gatsby-transformer-sharp": "^2.9.0",    "prismjs": "^1.22.0",    "react": "^16.13.1",    "react-dom": "^16.13.1",    "react-helmet": "^6.1.0"  }}
复制代码


现在,你通过 npm 来申明与管理你的各种依赖了。


这会令你想到什么?在其它方向都有自己的依赖管理


  • 后端是使用 maven 或 gradle 来进行依赖管理

  • iOS 最流行的是 cocoapods

  • Android 是 gradle 来管理依赖


看到没,前端终于和其它技术方向站在同一起跑线上了。

转换技术

我在前面的文章也说过,前端其实并未改变,它仍然主要是由 HTML,JS 以及 CSS 组成。


在『后』前端阶段,编码已经发生了极大的改变,但最终产物仍然是这三个,并未改变。


那究竟它是怎么做到的?


那就是依赖--转换技术


由于突破了浏览器的限制,使得一切皆有可能,那当然也可以添加翻译这个能力。因此前端出现了一些翻译转换技术,它们的作用就是将前端各种花式的新技术的玩意转换成 HTML,CSS,JS 三个东西。


也就是,事实上,不管前端有了多少新技术,概念,最终仍然依赖于转换技术,仍然需要转换成 HTML,JS 以及 CSS。


也就是:


  • React,Vue 这些代码只存在于编码阶段,最终它是 HTML+JS

  • TypeScript 只存在于编码阶段,最终它是 JavaScript

  • Less,Sass 也同样只存在于编码阶段,最终它是 CSS


是不是很有意思的现象?


主流的转换技术包括:


  1. babel -- 这是将 es6 及以上的一些新特性转换成 es5 的语法

  2. Webpack -- 它远比 babel 复杂,babel 只做一件事,webpack 则是做一堆事,它会使用 ts-loader 去转换 typescript,使用 less-loader 去转换 less,也会使用 balbel 去转换 es6 以上的语法。它有很多插件。


当然 webpack 也有一些同等级的技术,但论流行度,还是以 Webpack 为主。


所以,现在前端开发,基本不可能脱离 webpack,有些整合的框架或技术,比如 gatsby,你从代码中看不到 Webpack 的存在,但这不代表它不存在,而是被 gatsby 给隐藏到后面去了。它在 Webpack 之上,构建了一套自己的规则,使得开发人员不用关心 WebPack 的配置而已。


另外,create-react-app 也是这种方式。

进击的前端

事实上,如果我们认真分析,就会发现,前端的技术已经不止单纯在前端范围,它呈现出一种进攻的姿态,如今在移动端,后端及桌面端开发都能见到前端技术的身影。


这又是怎么一回事?


下一篇继续:前端之变(四):进击的前端

发布于: 刚刚阅读数: 2
用户头像

微言码道

关注

WHATEVER IT TAKES 2018.07.15 加入

全栈式技术开发

评论

发布
暂无评论
前端之变(三):变革与突破