Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前端构建大型应用 #13

Open
godbasin opened this issue Aug 25, 2018 · 0 comments
Open

前端构建大型应用 #13

godbasin opened this issue Aug 25, 2018 · 0 comments

Comments

@godbasin
Copy link
Owner

与其说是构建大型应用,或许更多地是常用的应用构建吧。很多时候我们的项目在搭建的时候通常都不会定位为大型项目,但我们还是需要考虑到拓展性,或者说是在当项目开始变得较难维护的时候,要进行调整的一些方面。

项目设计

在项目开始之前,我们需要做一系列的规划,像项目的定位(to B/C)、大小,像框架和工具的选型,还有很重要的一点是,项目和团队规范。

框架选择

通常来说,框架选择是准备项目的第一步。

说到框架,目前主流三大框架 Angular、React 和 Vue,先从个人理解来看看这三个框架。

Angular

这里的 Angular 是指 Angular 2.0+ 版本,v1.0 我们通常称之为 AngularJS,目前已经不更新了,建议大家还是使用 Angular。

Angular 相对 React 和 Vue,最初的设计是针对大型应用来进行的。要是你认识 JAVA 的话,像依赖注入这一套你会觉得很熟悉。当然到了 v2.0 以上的版本由于加入了很多的语法糖,看起来 AngularJS 和 Angular 相差很远,但是最核心的依赖注入模式还是相似的。

关于 Angular 各个版本的对比,大家可以参考下《谈谈Angular--从Angular1到Angular4》 以及《重新认识Angular》

项目中使用 Angular,最大的体验感受则是项目有完备的结构和规范,新加入的成员能很快地通过复制粘贴完成功能的开发。身边有人说过,好的架构设计,能让高级程序员和初入门的程序员写出相似的代码,这样对于整体管理和项目的维护有非常好的体验。

至于 Vue 和 React,它们更多是小巧的模板框架,也可以通过灵活搭配路由、状态管理等工具,达到大型应用的管理。目前来说,社区也有比较好的解决方案,官方也有出相关的脚手架来快速构建应用。

很多人说 Angular 难上手,其实主要在于开始的项目搭建、以及 Angular 独有的一套设计方案的理解。但是依赖注入的设计方式,我们几乎不用考虑很多数据和状态管理的问题。当然脏检查的方式曾经也带来性能问题,后面在加入树状的模块化、Zone.js 之后,即使没有虚拟 DOM,性能也是有大大的提升。

React

本人接触的 React 项目不是很多,但是 jsx、虚拟 DOM、函数式编程的设计,带来的震撼和冲击还是很大的。

React 相对 Angular 最大的优势是轻量,或许其实这么比较不大对,因为 React/Vue 和 Angular 不一样,Angular 是整套的解决方案,而 React/Vue 则是项目搭建中灵魂使用的前端模板工具。

Angular = React + react-router + Redux/Flux/Mobx = Vue + vue-router + Vuex/Redux

虚拟 DOM 主要解决了什么,它的原理又是怎样的,这些会涉及到浏览器的页面渲染原理,包括 DOM Tree、CSS Ruler Tree、Rendering Tree、Repaint、Reflow等等,你需要去理解虚拟 DOM 为何能带来性能的提升。

类似这样的,你会在使用 React 的时候,接触到很多好的设计,去引领你进行更深入的思考。函数式编程的方式,也会不同程度地拓展你的思考方式,遇到问题的时候,能有更多的解决办法。

至于社区建设,其实三大主流开源框架的社区都相当完善了。

Vue

如果你熟悉 Angular 以及 React,你会发现 Vue 的使用,其实很多地方像是两个的结合体。

Vue 最大的特点是上手简单,不管是框架的设计和文档,都对新手极其友好。但是这并不代表它只是个简单的框架,当你需要实现一些更加深入的自定义功能时,你会发现它其实也有很好的功能支持。如果你还认为它只是把 Angular 和 React 的优势结合,在你深入使用甚至阅读源码的时候,你会慢慢发现里面的一些自己的思考,真的是个很棒的框架。

如果说你是个新手,那么 Vue 会是较好的选择。相比另外两个框架,Vue 最初的社区缺陷现在也早已不再是问题了,相关的脚手架、配套工具也都很完善。

开源框架?

使用开源框架的好处是,有着完整详细的文档,同时有问题也能通过 issues 和 Stack Overflow 来查找。

更多时候,我们选择一个框架,需要考虑项目大小、定位。**技术选型更多的在于团队,你要考虑这个团队的能力、大家对各个框架的熟悉程度、是否有强烈的倾向。**或者有能力的团队,也可以选择相对小众的框架。

当然也有些小伙伴喜欢自己造轮子,不过你们要记得,造轮子是要负责任的,你需要提供友好的文档和 API 给他人,不然对项目的维护来说,简直就是毁灭性的体验。

还有在生产环境,尽量使用 release 版本吧。那段将 Angular2-beta 升级到 Angular4-rc 版本的日子,真的不堪回想。

有些人喜欢捣鼓新东西,个人的体验是,我们尽量在对这些新技术有较好地把握之后,再尝试一点点加入我们的项目里。项目尤其是工程项目,大多数是解决某些问题,我们需要在满足业务和项目维护性的同时,来做一些新的尝试。

项目代码结构

个人认为,好的项目代码结构会大大提升项目的维护性。同时我们可以提供友好的说明,以便其他成员理解项目和快速定位。

这里贴出个人比较偏好的结构:

# Angular
│
├── src/                              # 项目代码存放位置
│   │
│   ├── app/                          # app相关代码
│   │   ├── modules/                  # 业务模块
│   │   ├── shared/                   # 公用组件/服务等
│   │   └── container/                # Angular应用入口文件(路由、启动模块等)
│   │
│   ├── assets                        # 相关资源
│   ├── environments/                 # 环境相关配置
│   │
│   ├── index.html                    # 主页面
│   └── main.ts                       # angular启动文件
│
├── dist/                             # 存放编译打包生成文件
├── e2e/                              # e2e测试相关文件
├── .gitignore                        # Git上传相关配置
├── package.json                      # npm相关配置
├── README.md                         # 说明文档
└── xxx.json/xxx.js/.xxxx             # 其他配置文档
# Vue
│
├── src/                              # 项目代码存放位置
│   │
│   ├── app/                          # app相关代码
│   │
│   ├── components/                   # 公用组件
│   ├── router/                       # 路由配置
│   ├── store/                        # store
│   │
│   ├── index.html                    # 主页面
│   ├── main.js                       # 启动文件|
│   └── ...                           # 其他文件
│
├── dist/                             # 存放编译打包生成文件
├── config/build/                     # 项目构建相关配置
├── .gitignore                        # Git上传相关配置
├── package.json                      # npm相关配置
├── README.md                         # 说明文档
└── xxx.json/xxx.js/.xxxx             # 其他配置文档

其实有一点比较重要,就是公共组件、工具等同类的文件,放置一起维护会比较好。而且还有个小 tips,我们可以在搭建项目的时候,在 README.md 里面描述下该项目下的代码和文件结构。

代码流程规范

代码规范其实是团队合作中最重要的地方,使用相同的代码规范,会大大减少我们接手别人代码时候卧槽的次数。

好的写码习惯很重要,命名习惯、适当的注释,会对代码的可读性有很大的提升。但是习惯是每个人都不一样,所以在此之上,我们需要有这样统一的代码规范。

一些工具可以很好地协助我们,像 Eslint、Tslint等,加上代码的打包工具协助,可以把一些规范强行标准化,来获取代码的统一性。还有像 prettier 这样的工具,能自动在打包的时候帮我们进行代码规范化。

除了这些简单的什么驼峰啊、全等啊、单引双引等基础的规范,其实更重要的是流程规范。最基础的是改动公共库或是公共组件的时候,需要进行 code review。通常我们使用 Git 维护代码,这样在合并或是版本控制上有更好的体验。

但其实最重要的还是沟通,沟通是一个团队里必不可少同时很容易出问题的地方,要学会沟通方式、表达方式。

大型应用优化

说到大型应用,其实像页面加载性能、构建打包等地方,我们都可以适当进行优化。

路由管理

路由管理其实主要是当我们的项目变大方便管理,同时为了项目体验问题而引入的解决方案。毕竟我们产品设计都比较成熟,对用户来说刷新页面会丢掉页面状态,这样的体验是在是太糟糕了。

我们在规划项目路由的时候,会推动我们对项目业务、功能区块化有更加深入的认识和理解。同时对我们的项目结构规划也有很大的帮助,我们可以根据路由来放置我们的代码文件,有了这样的约定,我们在维护他人代码的时候,便能迅速地定位到对应的位置。

路由管理现在很多框架都有配套的工具库,已经有很多完善的解决方案了,这里不多说。

抽象和组件化

在我们开始写重复的代码、或是进行较多的复制粘贴的时候,大概我们需要考虑对组件进行适当的抽象了。

好的抽象能大量减少重复代码,同时对项目整体有更深入的理解。坏的抽象会增加项目的复杂度,同时降低了代码的可读性和维护性。所以关键在于适度,好的办法是结合产品和业务来进行抽象,例如一个播放器组件、日历组件、快速导航栏、快捷菜单等组件封装,便于多次使用。

而组件的抽象相关,可以参加《 一个组件的自我修养》

同时,我们也需要把一些相同的方法抽离,封装成通用的工具库,像常用的时间转换、字符串处理、http 请求等,都可以单独拎出来维护。

状态和数据管理

我们的应用里,多数会面临组件的某些状态和数据相互影响、相互依赖的问题。

现在也有比较成熟的解决方案和状态管理工具,像 Vuex、Redux、Mobx 等,我们需要结合自身的框架和业务场景来使用。像父子组件的交互、应用内无直接管理的数据状态共享、事件的传递等,也都需要结合实际适当地使用。

代码打包

当我们的应用变得很大,为了提升首屏加载的体验,我们需要对代码进行分块打包。

一般来说,不同的框架有不同的异步加载解决方案,同时可以结合打包工具(Webpack等)进行分块打包。我们可以把首屏相关的东西打包到 bundle,其他模块分块打包到 chunk,来在需要的时候再进行加载。

路由异步加载

通常情况下,我们会结合路由进行分块打包,路由管理工具大部分都支持异步加载。

我们可以根据自己需要,来打包成多个文件,在路由进入的时候才获取和加载。Vue 的话可参考《Vue2使用笔记17--路由懒加载》,打包效果像这样:

image

Webpack 分块打包

使用 Webpack 的话,可以用:

  • CommonsChunkPlugin:提取代码中的公共模块,然后将公共模块打包到一个独立的文件中,以便在其他的入口和模块中使用
  • ExtractTextPlugin:可以将样式或其他从 js 中抽出,生成单独的.css样式文件
  • require.ensure()
    • webpack 在编译时,会静态地解析代码中的require.ensure(),同时将模块添加到一个分开的 chunk 当中
    • 这个新的 chunk 会被 webpack 通过 jsonp 来按需加载

Source map

这里需要讲一下,Source map 就是一个信息文件,里面储存着位置信息。也就是说,转换后的代码的每一个位置,所对应的转换前的位置。有了它,出错的时候,除错工具将直接显示原始代码,而不是转换后的代码。这无疑给开发者带来了很大方便。

关于 Source map,可参考阮大神的《JavaScript Source Map 详解》

在开发环境下,还能通过 Chrome 匹配源文件进行在线 debug 和修复源码。大家也可以自行搜索下,尤其我们需要在浏览器上直接调试 CSS 并生效的时候,体验真的很棒。

Tree-shaking

不知道大家熟悉 Tree-shaking 不,我们在引入一些开源代码或是公共库的时候,其实大部分时间我们都只是使用其中里面的一小部分代码。

Tree-shaking 通常指按需加载,即没有被引用的模块不会被打包进来,减少我们的包大小,缩小应用的加载时间,呈现给用户更佳的体验。

最初是 Rollup 提出并实现。Rollup 静态分析代码中的 import,并将排除任何未实际使用的代码。这允许我们架构于现有工具和模块之上,而不会增加额外的依赖或使项目的大小膨胀。

同时在 Webpack 2 里也加入了 Tree-shaking 新特性。至于目前的一些情况,也可以参考下《你的Tree-Shaking并没什么卵用》这篇文章。

编写可测试代码

测试的重要性不用多说,有了测试,我们每次功能调整和重构的时候,心会踏实很多吧。

但是目前大部分情况是,项目中功能的快速迭代、开发工作量饱满等原因,导致甚至单元测试这种都很少编写。Emmmmm。。。所以这里不多讲述,因为本人也没有太多经验。

结束语

项目的维护永远是程序员的大头,多是前人种树后人乘凉。但是很多时候,大家会为了一时的方便,对代码规范比较随意,就导致了我们经常看到有人讨论“继承来的代码”。
或许相比新技术的研究和造轮子,有个好的写码习惯、提高项目维护性并不能带来短期的利益,但是其实身为程序员,还是要对自己写的东西负责任的呢。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant