2

现在前端非常火热,相关的技术更是层出不穷,前端人也在不停地学学学。那么有没有什么“偷懒”的方式,帮助我们更加有效地完成编码的KPI呢?本人从事前端开发工作多年,负责公司多个大型项目前端架构设计与落地实践,本文就和大家聊一聊前端的“项目实践之道”与“变化之道”。

在进入正题之前,我们先回顾一下前端的发展史。前端在最早期的阶段,又被称为“切图仔”——写一些简单的静态页面,然后交给后端组装起来;后面随着业务的发展,产生了更复杂的业务需求,jQuery,bootstrap等相继问世帮助我们更快地开发;而随着外部对前端业务需求的加强,页面变得越来越复杂,原有模式的开发变得越来越吃力。这时诞生了MVVM概念,angular、react、Vue框架相继出现,这使得整个前端的发展进入到一个新时代。那么,如何在发展的浪潮中找到前端的“道”呢?

首先来看一则小故事:

行者问老和尚:“您得道前,做什么?”老和尚说:“砍柴担水做饭。”行者问:“那得道后呢?”老和尚说:“砍柴担水做饭。”行者又问:“那何谓得道?”老和尚回答说:“得道前,砍柴时惦记着挑水,挑水时惦记着做饭;得道后砍柴即砍柴,担水即担水,做饭即做饭。”

不难看出,老和尚得的“道”指的是同一时间专注做一件事。做前端也是同理。在得道前,我们觉得前端工作复杂,原因在于同一时间考虑了好几项功能,一不留神就把所有东西都写出来,但代码的质量并不高。

一、何为前端工程化之道?
最重要的工作是对代码层次有效地拆解,我们可以简单地将其划分为项目的框架、组件、服务、业务页面四个部分。框架分为基础框架和业务框架,搭建业务框架,目的在于提供整体的解决方案让其它区块(层)更加纯粹;善用组件库【基础组件(含样式)、业务组件】,减少重复的轮子;服务即为统一的方法集或者对于某一模型层的统一处理;而业务页面的重点在于专注业务本身。此外,还有模块化,微服务等等。我们默认层与层之间是互相信赖的,当我们在做其中某一项工作的时候,可以当作其他部分不存在,仅着手于我们需要的。

此外,我们也可以从另一个角度将层区分为:数据层(包括封装了对数据的一些基础处理)、逻辑层(项目较大,逻辑层可能会被拆成多层)和视图层。

在拆解项目的过程中,划分目录结构很关键。当然,现在的CLI在目录结构上帮我们拆好了一部分,比如下面这个vue-cli给我们生成的结构:
图片描述

它在创建项目的时候会自动帮我们创建目录结构,简化了我们初始化项目时的工作。但这个项目结构仔细来看过于简单,更接近demo的状态,因而我们需要再对这个结构进行改进。我们需要建立一个业务框架,规划更健全的目录结构,同时包一层方法库(如权限、请求)并提供统一处理函数及全局拦截相关的处理,搭配好必要的全家桶套餐等。

二、前端工程化之目录结构拆分实践
下图是我们某一个项目的结构。它相对复杂,包括PC端和移动端两部分,共用的部分就在common文件里。它包括assets(图片、资源信息)、components(一些公共的组件)、过滤器、mixin(一些用于合并的模块)、service(公共服务)、stores(数据存储)、utils(预处理函数,工具)。
图片描述

PC文件夹里有一些特有的静态资源、文件、插件。Mobile这个文件夹也是一样的道理。这个项目里的components更倾向于通用业务组件,plugin则倾向于放一些引发效果变化的插件;router是一些路由信息;views是一些业务的组件。通过这样的分层,写业务的同学可以在views里去写;即便是一个人负责所有部分,他也能够在各个环节都保持专注。

三、实例:个推部分产品架构设计实践
个推拥有较为丰富的产品线,其中有的产品线下不同产品的主要功能模块近似,但这些产品之间又相互独立。所以,如果我们逐个开发单个产品,代码会被重复拷贝多次,若其中一个需要修改,则其他的都要做相应的调整。那么我们如何解决这个问题呢?

这里先介绍几个具体的概念。
产品:每个具体的APP就是一款产品。
项目代码:包括广义的gulp/src/cloud等,与狭义的src文件夹。

基于这些,我们想到了一个方法:源代码作为独立的一部分,对于不同产品使用不同配置及特殊组件,然后打包成不同的产品。

这是根据以上设计模式画的示意图。

图片描述
我们内部有一个组件库,包括基础组件和样式组件。

个性化的部分
首先把这些模块拆分为一个个小的组件,这里我们用三角形、圆形和方形表示;然后结合原来的基础组件,组成部分功能组件;接下来通过功能组件的堆积,形成各个具体的业务功能。因而整体上,个性化部分(业务功能的不断自我调用)相当于一个模块了,可以组装到某个产品中,它的最终形式是由相关的配置决定的。此外,view里的插槽的区块,是由产品来定义插槽中业务组件的最终展现形式。

公共的部分
数据层会提供一些支撑服务,主要是账号服务,与临时存储相关。我们也针对数据层进行了划分:API call借鉴RPC思维,形成通用发请求的方法;Model call是比较早期的一种模式,会把具体的请求服务分装好;get json是针对某一部分没有封装成后端接口源数据的文件。

视图层主要有两部分,不同产品的配色不同,文案也不同。

以上就是我们整体的一个架构。

四、关于架构模块划分的一些TIPS
下面给大家介绍一下我们需要的一些工具:1、自写node小程序用于检查一些权限,比肉眼更精准;2、自建CLI,基于项目实践流程,将一些固化的工作写成工具集成到自有的CLI里面。随着项目演进,我们将apps文件夹拆成了独立的仓库管理,并写了一个脚本,让其和主程序软链,从而直接可以运行。

前面,我们也提到了组件库。除了业务框架的细分,我们还需要对组件进行分类,包括:样式库、公共函数库、js的插件、业务组件、模块化。

至于组件库的范围,我们可以分为全范围级别组件库、产品线级别组件库、项目自有组件库、专项组件库。

五、前端的变化之道
因为现在前端很火热,所以相关的一切皆在变化,包括技术栈、业务、设计思路、架构等等。不仅如此,业务需求、开发人员、项目复杂度、实现思路等等也在变化,这些变化有可能有意无意地导致我们的代码正在慢慢“变坏”。

我们发现代码写得越大,坏得越快,因为接触的点太多。因而,当代码出现了“坏味道”的时候,我们需要尽快地把它们校验出来。有一个效应叫“破窗效应”——即一个地方有很多窗户,其中一块玻璃被打破了,如果你不去管它,之后你会发现越来越多的玻璃被打破。因而代码出现了问题需要立即解决,否则问题经过多年积累,到最后我们会发现项目已经改不动了,只能弃船逃跑,新起炉灶。

上一个实践的优势,有可能成为下一个实践的劣势。早期我们发现二级菜单中的几个列表业务功能非常接近,我们将其合起来求同存异,很容易管理。后来,功能近似的二级菜单越来越多,所有的二级模块混在一起,差异内容也积少成多,我们再想改的时候便异常痛苦。对此,我们的一个解决思路是,当我们发现代码实践方式有些“别扭”的时候,就要做一些重构和修正方案。但这不是一蹴而就的,也不是到某个点为止,而是需要一直去做。

还有一个不得不提的变化,是官网内的一些项目,即从SSR到SSR。在前后端未分离的时候,需要ASP、PHP、JSP之类的服务端静态页面渲染。后来前端工程的能力越来越强,可以实现浏览器端渲染;再到如今,诞生了vue的SSR。现在我们可能会用SPA的方式开发,其缺点是SPA对于官网而言可能会比较“重”,或者说我们更加习惯目前的开发方式,难以适应jQuery时代的开发。但是另一方面,多页面也存在一定好处——每个页面都非常独立,可以更好地SEO,用户也可以享受更快的到达时间。所以,从SSR到SSR,看上去好像倒退了,但实际上这是一个螺旋上升的过程。

此外,外部也在发生着一些变化。比如,angular到6了,Webpack 4发布了,Node之父推新产品了等等…

六:结语
市场变化太快,虽然技术很重要,但思想比技术更重要。技术是学不完的,但思想可以类比,甚至是可以创新的。基于新的思路,也许你也能写出新的算法,新的技术。


个推
1.5k 声望2.4k 粉丝

个推(每日互动股份有限公司,股票代码:300766)成立于2010年,是专业的数据智能服务商,致力于用数据让产业更智能。个推深耕开发者服务,并以海量的数据积累和创新的技术理念,构建了移动开发、用户增长、品牌...


引用和评论

0 条评论