前言

本文来自极客前端训练营的主题公开课,非原创。

作者简介

桑世龙(狼叔),阿里巴巴前端技术专家,nodejs《狼书》作者。

快速发展的大背景

前端发展太快了,在2004年之前,大概只要会网页三剑客(一套强大的网页编辑工具,最初是Macromedia公司开发的,由Dreamweaver、Fireworks、Flash三个软件组成)就很牛了,那时候前端还比较“纯洁“。在进入以Ajax为代表的异步刷新改进用户体验的Web 2.0时代后,开始涌现出大量的库,比如Prototype、jQuery、MooTools、YUI、Ext JS、kissy等,它们都还只是对浏览器兼容性和工具类函数的封装,可是从Backbone、Angular 1.x相继出现后,前端就开始热闹起来了,出现MVC、MVVM、IOC(控制反转,Java著名框架Spring里的概念)、前端路由(类似于Express、Koa等框架的路由)、Virtual DOM(虚拟DOM,通过DOM Diff算法,减少对DOM操作)、JSON API(接口规范)、JavaScript Runtime(Coffee、Babel、TypeScrpt)等等,各种框架格式如雨后春笋一样冒出来,以前可能半年甚至更长时间才出一个框架,现在可能几周就有新的框架诞生,前端进入了空前的爆发阶段。

图解2004-2016变化


前端经历过的几个阶段

现在前端开发也复杂到了一定程度,对比之前的开发方式,可以称为现代Web开发。这里我来做一个总结,前端发展经历了4个阶段:

目前前端的发展状态

目前整个大前端还属于发展期,没有形成固定模式,所以从趋势上看是上升期,复杂、混乱、多样性的结果也导致现在的前端比较吃香,被大家戏称为“钱端”。很多同学会问,学习前端技术是采用渐进式方式,还是上来就直接学React/Vue.js等框架呢?实际上,我认为这两种方式都存在,如果有经济压力就向“钱“看,可以直接学习React/Vue.js等框架,但学会了之后,一定要把其他3个阶段补充学习完;如果没有经济压力,又有时间和耐心的话,循序渐进的学习是最好的方式。编程没有捷径,无论是哪种,都需要脚踏实地多多练习。

当你代码写多了,就会发现:

于是,前端开发变得复杂,并进入现代Web开发时代。


nodejs

对于Node.js来说,所有前端框架都是视图层(View)的展现技术而已,可以非常方便地和各种框架集成,并按照业务需求予以更好的实现。另外,所有的前端框架都采用Node.js和NPM作为辅助开发工具,使用了大量Node.js模块,但前端框架使用的模块大同小异,如果熟练掌握了Node.js和NPM,对于学习前端技术来说,你要学的只是纯前端的部分而已,复用价值非常高。

和Node.js相关的前端开发模块实在是太多了,这里简单列举一些:


由这些模块,也就引出了我们今天要聊得话题——大前端工程化实践与思考。

构建工具

先来说说构建工具。预处理器是前端高级玩法。


我经常开玩笑说以前HTML/JavaScript/CSS的时代太纯洁了,现在随便写哪样都要编译/转译。好处是可以借助高级特性,提高开发效率;缺点也是极其明显的,就是人脑要有转换思维。这其实是蛮痛苦的,本来HTML/JavaScript/CSS就不够熟练,再转一次,对于新手来说需要一个适应过程。所以这件事还是要辩证地看,福祸相依。

说起构建工具,大概都会想到Make、Ant、Rake、Gradle等,其实Node.js世界里有更多实现。


选用构建工具最主要的目的是为了自动化。对于需要反复重复的任务,例如压缩(minification)、编译、单元测试、linting等,自动化工具可以减轻你的劳动,简化你的工作。尤其是工程越复杂,自动化的价值就越大。这里的编译包含模板、CSS预处理语言、JavaScript友好语言等编译,在源码编写时用的是高级玩法。

除了编码编译外,还有测试、代码风格检查、上线前优化(合并、压缩、混淆),可以说,构建系统在整个软件工程里无处不在。

grunt

Grunt除了配置复杂外,还有一个问题就性能,可能很多同学遇不到性能问题。Grunt是读写文件的,所以在多文件、大文件处理时是有性能瓶颈的。

Grunt的设计还是挺精巧的,但配置起来让人抓狂,自然会有很多不爽的人,于是Gulp就慢慢崛起了。

Gulp

简单来讲,Gulp是一个Node.js写的构建工具,基于Stream的流式构建工具,它包含大量插件。Orchestrator是Gulp底层依赖的task相关的核心库,它定义了task执行方式和依赖,而且支持最大可能的并发,Gulp的高效即来源于此。本身Stream对大文件读写就非常棒,再加上上面说的种种特性,使得Gulp流行成为必然。

Gulp的应用场景非常广,前端项目或Node项目都可以使用,哪怕是webpack也可以和Gulp搭配使用,通过gulp-webpack模块即可。如果想深入学习Gulp,可以看一下stuq-gulp(github.com/i5ting/stuq…),文中以WeUI里Gulp用法为例,由浅入深,从用法到原理进行了阐述。

模块化

解耦是软件开发领域永恒的主题,而模块化是目前最好的解耦方式,所以从无到有、从有到成熟的演化,必然要经历很长的路。如今的发展,源于1993年HTML创建、1995年诞生JavaScript、1996年发布CSS1,之后就进入了原始而野蛮的开发阶段。从互联网诞生到2000年泡沫破灭,Web技术才算真正崛起。那时候特别纯洁,会写的人就很牛了,之后Flash也曾超级火爆。在之后就到了Web 2.0时代,开始出现Ajax,开始有了各种兼容浏览器的库,然后开始模块化,在2009年诞生了Node.js,彻底改变了JavaScript以及前端开发领域的开发方式,从浏览器端的Backbone支持MVC模式,到AngluarJS支持的MVVM,到现在的React/Vue和webpack等。

这里我尝试从更宏观的视角来进行归类,大致分5个阶段,分别是原始阶段、包管理器、模块规范、模块加载器、模块打包器。下面我来一一说明。

原始阶段

脚本加载还都比较原始,方式如下:使用多个script标签加载、手动管理顺序、手动管理加载哪些。

在Web开发里经过了很多尝试,也做过很多龌蹉的事儿,比如

如果说加载比较恶心,那么脚本顺序更恶心,而且JavaScript有个“特性”,一处报错,所有后面的都会崩溃,所以开发会很苦的维护脚本加载的顺序。

包管理器

很明显,直接进行文件操作是非常低效率的做法,对于版本、依赖都没法做更好的处理。于是就出现了Bower、NPM等包管理器,所有模块升级,依赖都有包管理负责,可以说很大程度上省去了前端的重复性工作。

模块规范

模块化加载的本质是按需加载。

模块加载器

模块加载器需要实现两个基本功能:

常见的比如RequireJS、Sea.js和SystemJS。以AMD的模块加载器RequireJS为例,通常使用RequireJS的话,我们只需要导入RequireJS即可,不需要显式导入其他的JS库,因为这个工作会交给RequireJS来做。

模块打包器

对于开发来说,只需要关注业务模块,不需要了解模块加载器和构建过程,很明显这是非常理想的,也因此产生了webpack这样的模块打包器。

Gulp作为通用构建工具,它已经非常完美了。但技术变革太快了,应用各种预处理器、前端组件化,导致前端无比复杂,而webpack的出现刚刚好,完美解决了前端工程化的问题。

webpack基本介绍

webpack是Node编写的著名模块,是打包器(bundler),不只是支持CommonJS模块,而且还支持更潮的ES6模块,是目前使用极其广泛的打包器,像前端组件化的框架(React、Vue)大多都是使用webpack的。

loader && plugins

它提供了两个极其好的机制:loaders和plugins。

loaders:webpack认为每个文件都是资源模块,针对打包构建过程中用来处理源文件的(JSX、SCSS、Less..)统称为loader。

plugins:插件可以完成更多loader不能完成的功能。插件并不直接操作单个文件,它直接对整个构建过程起作用,大多数内容功能都是基于这个插件系统运行的;当然还可以开发和使用开源的webpack插件,来满足各式各样的需求。比如知名插件autoprefixer、html-webpack-plugin、webpack-dev-middleware、webpack-hot-middleware。

webpack打包过程

浏览器加载过程

(1)通过<script>加载webpack打包后的文件

如果对比着理解webpack打包过程和浏览器加载过程,可以对前端模块化的演讲过程能够有更好的了解。从定义模块规范,到模块化系统的运行时环境(加载器),再到更高级的打包器,这个演进的过程,也让前端开发越来越简单,这才是打包器越来越火爆的原因。

理解webpack的功能


事实上从结果来看也是这样的,工程化最终目的是让开发者专注于写业务模块,其他的事情让打包器来做。从这个角度讲,webpack还是比Gulp更成功。

但是webpack学习曲线也是比较陡峭的,以点打面、不断深究,是非常好的学习方式。从基本用法、概念,到tree-shaking、code spit,再到如何打包、浏览器如何解包,到工程化,到大规模构建如何优化,考验你的是基础是否扎实、原理是否真懂、是否了解优化思路和源码。作为类似模块与Gulp进行对比,到Stream(Gulp核心),到event(Stream基类),到HTTP(Stream在HTTP里应用),到eventloop,到C++实现的libuv和v8,太可怕了,几乎把《狼书》的所有内容都涵盖了。

webpack构建大型项目

webpack封装

af-webpack是支付宝定制的webpack,把webpack-dev-server等Node.js模块直接打包进去,同时对配置做了更好的处理,以及插件化。

ykit是去哪儿开源的webpack,内置Connect作为Web server,结合dev和hot中间件,对于多项目构建提效明显,对版本文件发布有不错的实践。

easywebpack也是插件化,但对解决方案如boilerplate等做了非常多的集成,比如egg的ssr是有深入思考的,尽管我不赞同这种做法。

CRA和UMI

在Create React App(CRA)项目里使用的是react-scripts作为启动脚本,它和egg-scripts类似,也都是通过约定,隐藏具体实现细节,让开发者不需要关注构建。

UMI和CRA类似,它是一套基于蚂蚁金服技术栈总结的最佳实践,是一套零配置“约定高于配制“,开箱即用,按最佳实践进行开发的前端框架:React全家桶 + dva + jest + antd (mobile) + less + eslint。

UMI思考得相对全面,从技术选型、构建,到多端输出、性能优化、发布等方面进行了拆分,使得UMI的边界更为清晰,作为前端最佳实践没啥毛病,目前大多数前端组也都是类似的实现方式。说白了就是现有技术栈的组合,封装细节,让开发者用起来更简单。在未来,类似的封装还会有更多,毕竟框架层面创新不那么多,大家就会将精力慢慢转到应用层面。

脚手架

cli参数处理

它的问题在于包的依赖有点大,对于强迫症开发者来说接受不了。于是Yargs这类的模块应运而生,强大且依赖极少。

模板方式

git仓库做模板

核心是ownload-git-repo,然后对里面的文件进行模板处理。这种方式的灵活度非常高,是目前比较主流的方式。

未来的端渲染和构建

前后端分离,即使用JavaScript运行在客户端,通过请求获取服务端接口数据,借助如JQuery、Angular、React、Vue等前端框架操作或生成页面DOM,充分利用客户端资源,减少服务端压力,前后端分工明确,一直到现在仍是最常用的开发方式。

同构开发,如Meteor、Next.js、Nuxt.js等框架,都提供了不同的适用场景和开发方式,但目的都是为了同一套代码能同时应用于服务端和客户端。

ssr的演变过程

JSP/ASP都算,当然Node渲染模板也算,Node世界模板最为丰富。

BigPipe,虽然很老了,但分块传输优点是非常明显的,且对浏览器友好。Facebook和微博、去哪儿都是受益者。Node天然支持,对res.write很友好。

基于组件写法的SSR,比如React SSR。时代变了,SSR也要跟上。vdom + hydrate玩的可以很嗨,连BigPipe也可以结合起来。UMI SSR和Rax SSR未来可期。

真正的同构,即CSR和SSR写法一致,未来不再区分概念,在Servless里,API和渲染都是函数。

举一个项目的例子, github.com/ykfe/egg-re… 。它的写法是:


核心要点有:


在未来,我们希望所有服务都走Serverless,这样用户只需要关注React写法即可。构建是本地做的,类似于UMI。egg不需要关系,因为走的是Serverless的运行时环境。

CSR和SSR写法一致,又可以上Serverless,它的优点有:

上了Serverless之后,除了本地CLI构建外,还可以提供云构建。比如每个页面都是函数,那么多个页面如何合并呢?比如UMI典型的多页应用,通过react-loadable+react-router实现的代码按需加载,这种情况就可以先在Serverless上发布多个页面,继而在云构建上,配置多个页面,最终构建成一个多页应用。

另外,渲染层做轻,对于未来上Web IDE也是有极大便利的。可以畅想一下,未来有个流程就可以完成开发,是不是很美好?阿里将Serverless和IDE作为两大方向,确实是非常用心的考虑。

前后端协作

之后我们来聊聊前后端协作。前端本来的定义是指基于浏览器做开发的,随着浏览器应用范围越来越广,前端的界定也越来越模糊。目前前端已经涵盖PC、H5、移动端组件,几乎是所有和用户接触的带界面的都算前端,所以才有了大前端的概念,泛指所有和用户交互的终端开发。

一直以来,跨浏览器(Web View)都是开发领域折腾的方向,从Native到Hybrid,到React Native/Weex,再到Electron、PWA、小程序,你能看到大家都在往轻量级走,统一技术栈,降低成本。也就是说,端上希望统一,又以前端为开发核心,故而统称为大前端。

JavaScript已横跨三端,再说一下Node,覆盖工程化和服务端能力。很多大公司移动端和前端已经合并一个组进行管理,大前端局面已成定局。

前后端分离

前后端分离,即使用JavaScript运行在客户端,通过请求获取服务端接口数据,借助如JQuery、Angular、React、Vue等前端框架操作或生成页面DOM,充分利用客户端资源,减少服务端压力,前后端分工明确,一直到现在仍是最常用的开发方式。

BFF

BFF(API Proxy),独立的API层的出现原因有很多:

移动端兴起,大家都开始面向API开发,但却忽略了大前端不只只有移动端,还有PC Client和PC/H5 Web。主要是屏幕大小不同而导致UI/UE上有明显差别。

后端开发API的时候,不喜欢同时维护多套API。

除了沟通成本,还有对前端实现不了解而产生的误解。

简单理解,BFF就是各端的API独立提供了。但是,这样做很明显不经济。那么,是不是要把架构升级一下呢?

GraphQL

GraphQL是Facebook于2012年在内部开发的数据查询语言,在2015年开源,旨在提供RESTful架构体系的替代方案,既是一种用于API的图表化(可视化)查询语言,也是一个满足你数据查询的运行时。

传统Web应用通过开发服务给客户端提供接口是很常见的场景。而当需求或数据发生变化时,应用需要修改或者重新创建新的接口。长此以后,会造成服务器代码的不断增长,接口内部逻辑复杂难以维护。而GraphQL则通过以下特性解决这个问题:

声明式。查询的结果格式由请求方(即客户端)决定而非响应方(即服务器端)决定。你不需要编写很多额外的接口来适配客户端请求。

可组合。GraphQL的查询结构可以自由组合来满足需求。

强类型。每个GraphQL查询必须遵循其设定的类型才会被执行。

也就是说,通过以上的三个特性,当需求发生变化,客户端只需要编写能满足新需求的查询结构,如果服务端能提供的数据满足需求,服务端代码几乎不需要做任何的修改。

GraphQL通过模型定义,对前后端都非常友好,无疑是一种非常好的解决方案。当然,它也有问题,约定本身就不是件容易的事儿,另外对于前后端成本还是有的。

Serverless

Node.js成也Eventloop败也Eventloop,本身Eventloop是黑盒,开发将什么样的代码堆进去你是很难全部覆盖的,偶尔会出现Eventloop阻塞的情况,排查起来是极为痛苦的。

利用Serverless,可以有效防止Eventloop阻塞。比如加密是常见场景,但本身执行效率是非常慢的。如果加解密和你的其他任务放到一起,是很容易导致Eventloop阻塞的。

本地开发一个函数,然后通过CLI发布到Serverless云上,一切都那么简单,必然是未来趋势。

可以看下面这张图。


前端工程化未来的理解

CSR和SSR统一,同构开发,本地CLI打包构建,发布到Serverless云上,简单高效。

API基于Serverless极其简单,不需要了解Web框架,简单组成API即可,无运维,不怕高并发场景。

这里要提一下,在Serverless这种大环境下,如果API解决了,前端自然是可以做所有业务的。前端能做的事儿越来越多,未来前端应用层也会更多。

未来随着经济和业务发展,比如会有更多应用也会更多端,对前端来说是好事,因为能做的更多,价值就能够得到非常好的体现。

所以作为一个坚定的Web信仰者,我相信未来前端的前景一片大好。

 热 文 推 荐 

☞ Webpack 4 动态切割JS注入文件名

☞ 你在公司项目里面看过哪些操蛋的代码?

☞ CSS的一些你可能不知道的强大技巧

☞ 为什么视频网站的视频链接地址是blob?

☞ 搭建一个 nodejs 脚手架

你也“在看”吗?

分享狼叔关于《大前端工程化的实践与思考》相关推荐

  1. 普元云计算-聊聊前端工程化的实践与未来

    转载本文需注明出处:微信公众号EAWorld,违者必究.   目录:   一.前端过去一年的发展 二.工程化是前端实现的核心 三.EOS8前端工程化设计实践分析 四.总结与展望 一.前端过去一年的发展 ...

  2. 聊聊前端工程化的实践与未来

    转载本文需注明出处:微信公众号EAWorld,违者必究. 目录: 一.前端过去一年的发展 二.工程化是前端实现的核心 三.EOS8前端工程化设计实践分析 四.总结与展望 一.前端过去一年的发展 201 ...

  3. [上海线下活动] Web前端工程化架构实践 -- 沪江技术沙龙

    报名链接:www.huodongxing.com/event/53996- Web前端工程化历经了:2011年的Shell&(YUICompress || Google Closure Com ...

  4. 分享狼叔nodejs博客

    跟大家分享一篇文章,会帮助到大家更好的学习Node以及一些其他的东西 [全文]狼叔:如何正确的学习Node.js A:曾经有一个面试官问我,你以后的发展规划是什么? B:我很笃定的说以大前端为目标驱动 ...

  5. 从阿里前端工程化中台实践,看中台建设的舍与得

    作者|朱华军(阿大) 出品|InfoQ&阿里巴巴新零售淘系技术部 导读:随着前端技术不断从 Web 延伸至各种"端",大前端的概念早已成为业内共识.伴随着大前端的发展,与之 ...

  6. 【华为云技术分享】一统江湖大前端DOClever—你的Postman有点Low

    Mock服务器 + Excel怎么了 如果你的开发进度还在被后端开发人员牵着鼻子走,请优化自己的开发工作流,有了Mock服务器和Excel的文档说明后,相信大家的沟通效率会比以前提升很多,但仍然被沟通 ...

  7. vue学习经验分享,在这个大前端时代,你再不会vue就out啦

    主要为大家大致的介绍Vue的介绍.环境搭建要求.如何开发等经验分享 目录 vue介绍 Vue的MVVM模式介绍 Vue之HelloWorld Vue的生命周期 从Vue到页面

  8. 跟狼叔聊了一夜,终于搞明白了 Serverless 是什么

    Serverless作为近两年最火的互联网架构变革,给行业带来了极大的影响力.前端领域这个看起来与Serverless无关的领域也在悄然变化中,基于自身的业务场景,我们如何在实践中落地Serverle ...

  9. 前端18个月难度翻番?来这里把握大前端技术本质进展丨稀土开发者大会

    图片来源:pexels.com "别更新了,学不动了"向来是前端开发群体的切肤之痛: React 还没学明白,Vue 就出来了: Vue 2.0 还没上手,3.0 就发布了: No ...

最新文章

  1. ThinkPHP框架介绍
  2. 常见java考试题与面试题一
  3. boost::detail模块实现宏BOOST_DETAIL_IS_XXX_DEF的测试程序
  4. 使用GitLab CI和Docker进行容器应用自动化部署
  5. LeetCode 65. 有效数字(逻辑题,难)
  6. 【面向对象】构件与软件复用
  7. flask orm 数据库_Flask:使用ORM框架操作数据库
  8. JavaScript HTML5脚本编程——“跨文档消息传递”的注意要点
  9. HDU 6370(并查集)
  10. Ubuntu server配置远程VNC服务
  11. iOS启动动画效果实现
  12. 网关支付、银联代扣通道、快捷支付、银行卡支付分别是怎么样进行支付的?...
  13. 百度网盘无限扩容技术,外面399,无论自己用还是用做引流都可以
  14. 看完这个教程,不怕Xshell中修改字体有困难
  15. 4年老用户!从R9s Plus换到Find X3,这些体验太上头
  16. android 相机启动失败怎么回事,Android相机启动crash错误排查
  17. 基于 SPI 协议的0.96 寸OLED显示
  18. python控制步进电机驱动器_树莓派通过GPIO控制步进电机(python)
  19. 第九天 杭电OJ 1087、1203、1003
  20. android 自动签名工具下载,安卓批量签名工具使用说明

热门文章

  1. css实现平行四边形等特殊形状 文字图片倾斜
  2. 怎么将照片的kb变小?2种快捷方法你知道吗
  3. play-audio 简单命令行Android播放器
  4. 什么牌子的运动蓝牙耳机好?降噪好的运动蓝牙耳机
  5. laydate在火狐,360极速模式下,多个时间插件,只有一个可以用问题
  6. 开机出现OEM7GRUB命令框
  7. html div边框阴影
  8. android xml定义阴影,Android 边框阴影XML怎么实现,或者说怎么实现
  9. 各种卷积方式的最全讲解
  10. 【必备算法】字符串(反转问题):LeetCode题 344. 反转字符串,541. 反转字符串 II,917. 仅仅反转字母