JavaScript 和前端前沿技术探索

本文最后更新于 2018年02月24日。

“一套单页面应用,任何 path 访问都是服务端渲染、然后客户端路由,既解决 seo 问题,又解决渲染问题和前后端分离问题,并且为未来的 progresive web app 做准备。套上 servie worker 就具有离线功能。所以,从前端开发者长期受益来看,放弃 node 是弊大于利的。”—— 语自 @携程-工业聚

“集市” 和“大教堂”之争,推动着前端这个大生态的繁荣和演进。我把这个过程,总结为 “工程实践 + 标准化 => JavaScript 生态”。

  1. 匠心之路
  2. 关于 React 系前端技术的思考
  3. 一套编写 redux 最佳实践的案例
  4. Create React App 应用中添加 Storybook 指南

Web 前端

至今,没有最佳实践,大家对同一个问题通常有不同解法。这是 library 相对于 framework 的劣势。 目前,主流的三大 FRP 框架 React系、Angular 2系、Vue系 在相互融合。

另外,Hyperapp + Parcel 也是个值得关注的组合。hyperapp-parcel-app 项目相关文章

推荐的React设计模式、技术、技巧和窍门:React Bits

更多: React.js 资料和教程microjs

技术 React系(Webpack+ React + Redux) Progressive Web App 微信小应用 支付宝小程序
JS 编译器 TypeScript、FlowCoffeeScript Babel + ES6
CSS 预处理 Scss/SassLessStylus sass-loader、style-loadercss-modulesstyled-componentscssnano
CSS 后处理 PostCSSuncssCriticalCSSO
CSS 样式库 CSSgram(滤镜特效)、You-Dont-Need-JavaScript(UI 组件)
web UI Semantic UIMasonryBootstrapFuel UXRatchetMaterializeMaterial-UIAngular MaterialBulma(基于Flexbox)、 Grd Ant-designFusion Design(Next)UXCoreMaterial-UISemantic-UI-ReactBlueprintReact-BootstrapReact-ToolboxGrommetFabricReact-mdhyperappReact Desktop
H5 UI SUI MobileFrozenUIReact-WeUIFramework7PhononFoundationMaterial Foundation Fusion Design(Mext)
UI 组件 spectrum(Colorpicker)、jquery-qrcodechosenCodeMirrorjPickerpaginationjslz-stringPapaParseparticles.jshandsontableORY EditorTrixpush.jszuck.js react-colorReact-Grid-Layoutfixed-data-tablefixed-data-table-2react-virtualized、react-transitive-number、 ckeditor、 echarts、 react-list、 sortablejs
后台管理模版 Gentelella Admin
Shim es6-shimes5-shim.js
Polyfill reflect-metadata babel-polyfill、 ima.js-babel6-polyfill、 regenerator-runtime/runtime(async wait 的 polyfill)
DOM库 zepto、jQuery、 react-dom
HTML 5兼容旧浏览器 html5shivobject-observe(Object.observe polyfill)、 Feature.js
多点触摸手势库 HammerjsjGestures react-hammerjs
工具库 ramdajs、lodash、underscore、collect.jsLZMA-JScrypto-jsTetherPinYin、Moment、NumeralhumanizeCleave.js(格式化)、Mousetrapflat、setRafTimeout react-cookiereact-qartclassnamesglamorousglamor、d3-format、prismjsreact-sizemeclipboard、 detector、 pubsub-js、 query-string、 react-dropzone、 react-motion、 react-scroll、react-flighthighlight.jsreact-json-inspectorsource-map
模版引擎 pug、Handlebars、Mustache、doT
异步Task跟踪,分析,错误记录、开发调试跟踪等 zone.js
模块化 ES6 Modules、Browserify(CommonJS)、RequireJS(AMD)、SeaJS(CMD)、KMD.js(KMD)、systemjs
UI 层轻量级解决方案 Vue、Inferno、Preact React、React VRHyperapp
高阶组件(HOC) Recompose
MV* 框架(路由、数据获取、状态管理) Angular、Aurelia、Avalon、Ember
Pure Render pure-render-decorator
动画 AOSAnimate.css react-transition-group、rc-queue-animreact-flightPopmotionAnt MotionReact-Motion
表单 redux-formFormik
表单验证 React 内置的 propTypes、Yup
路由控制,可选 react-router、react-router-redux、junctions
连接React 组件与 Redux store,可选 React-Redux
中间件与异步操作 Async、Q redux-thunk
不可变数据结构 Immutable.js、immutability-helper、seamless-immutable、 moricortex
应用状态管理 ngrx/store Redux(redux-promise/redux-sequence-actionredux-immutablejs)、Mobx、Dob、React Easy State
静态网页生成器(SSG) Gitlab pages、 Netlify、 Surge、 Now static、 Hexo、Docsify Gatsby

模块化/组件化

Web MV*/Virtual DOM

基于组件(component-based)的构建方式。

MVVM 双向绑定、Virtual DOM,都是为解决直接操作 DOM 的“性能墙”。也有人提出了质疑,比如前端框架 Turbine 的开发者直言 《Why Turbine doesn't use virtual DOM

传统的 DOM 操作是直接在 DOM 上操作的,当需要修改一系列元素中的值时,就会直接对 DOM 进行操作。而采用 Virtual DOM 则会对需要修改的 DOM 进行比较(DIFF),从而只选择需要修改的部分。也因此对于不需要大量修改 DOM 的应用来说,采用 Virtual DOM 并不会有优势。开发者就可以创建出可交互的 UI。

说明 个人实例 相关 探讨
React Github 中最流行的 JavaScript 项目(popular-javascript) 模板生成器 create-react-app、React boilerplate、express-react-viewsReact Express 组件和分形,参考《关于 React 系前端技术的思考》的“组合、分形与 Redux”
Vue Hacker news(vue-test)
Moon 类 Vue
Angular 我的书柜(my-books)
Angular 2 其创建理念是声明式编程应该用于构建用户界面以及编写软件构建,而命令式编程非常适合来表示业务逻辑
Aurelia
React-Native 仅适用业务型场景

Web Components/Shadow DOM

模板HTML引入Shadow DOM简介基础样式样式续),所有这些技术的终极目标就是自定义元素(custom elements)

使用 shadow DOM 的时候应该确保内容和表现的分离。

  1. webcomponentsjs
  2. Polymer

可视化

专题 data-visualization

  1. JavaScript应用领域(d3-test)
  2. heatmap.js:Web 的动态 JavaScript 热图
  3. recharts

工程化/工作流

专题 匠心之路—工具

  1. Parcel:号称“零配置、构建快”的打包工具,应用场景和 Webpack 类似
  2. Webpack:业务项目常用的打包工具
  3. rollup-test:库项目常用的打包工具
  4. broccoli-babel-test
  5. grunt-babel-test
  6. phantomjs-test
  7. nightmare-test

状态管理

不要把应用的逻辑和数据结构耦合在一起——取自《Clean Architecture》

数据状态可分为:

  • domain-state 领域模型,比如user,order
  • ui-state 纯 UI 状态,比如一个弹窗的开闭,tab 是否 active
  • aspect-state 指一些切面,比如 redux-simple-router 需要在根 reducer上有个“routing”结点,redux-form 也需要自己的结点

MDV(Model Driven View)

公式: V = f(M)

Redux 可表述为 state := actions.reduce(reducer, initState)

说明 探讨
Redux 优点:单一store;通过Action 触发、Reducer 中操作数据; 单向数据流(Component -> Action -> Middleware -> Reducer -> State)。特点可预测、可扩展。缺点:数据关联查询时,还是感觉不方便 分组与管理?
MobX 通过透明的函数响应式编程(transparently applying functional reactive programming - TFRP) 使状态管理简单、可扩展

MVI(Model View Intent)

MVI 基于 Reactive 理念。相关:数据管道。解读:

  • Intent,负责从外部的输入中,提取出所需信息;
  • Model,负责从Intent生成视图展示所需的数据;
  • View,负责根据视图数据渲染视图。

提取为公式:App := View(Model(Intent({ DOM, Http, WebSocket })))

说明
RxJS 为处理异步操作而设计
CycleJS
xstream

React 和 Redux 之上的前端Web应用开发架构

关于 View 和状态机的最佳实践,是大多前端团队当下的主旋律。当然,选型是不会限于 React 和 Redux 的。

说明
Kea 构建 React 和 Redux 之上的前端Web应用开发架构

数据结构可变&不可变

可变和不可变是数据结构的属性,而不是语言的。

关于此话题,可以参考《前端精读周刊》的 Immutable 结构共享是如何实现的?

可变(Mutable)

可变(Mutable)数据耦合了 Time 和 Value 的概念。

单线程场景: 例如 JavaScript 对象本身可变。通常用 shallowCopy(浅拷贝)或 deepCopy(深拷贝)来规避被修改。缺点是造成了 CPU 和内存的浪费。

并发场景:如 Java 采用并发锁、Immutable Object 模式等方式来实现结构不可变。

说明
lodash deepCopy, mergeWith
Object.freeze、const 等

不可变(Imutable)

React 系实践中,Pure Render + Immutable.js 搭配。非常适合数据状态为多层嵌套的场景。

另外,也有些语言如 Clojure 则是原子上不可变的。其原理是 Persistent Data Structure(持久化数据结构),并通过 Structural Sharing(结构共享)来优化性能。

  • 其内部使用 Trie 数据结构存储,只要两个对象的 hashCode 相等,值就是一样的。这样的算法避免了深度遍历比较,性能非常好。
  • 通常,结构共享与不可变数据结构相关联,但它也适用于结构上不可变的对象。
说明
Immutable.js
immutability-helper
redux-immutablejs
seamless-immutable 只支持 Array 和 Object 两种数据类型
mori ClojureScript里持久化数据结构的API支持带到了JavaScript
cortex

数据范式/扁平化

说明
normalizr

数据加载器

GraphQL 与 REST

说明 相关
Relay 采用 GraphQL,用于构建数据驱动的 React 应用程序的 JavaScript 框架
tectonic React 和 Redux 的声明性 REST 数据加载器

PWA

本地存储

离线访问是一套优秀 Web App 的必经之路。

浏览器提供

本地存储

类别 技术 相关
键值对 (KVP) Local Storage、Session Sorage
数据库组织型 IndexedDB、Web SQL

应用缓存

HTML5 使用 ApplicationCache 接口解决了由离线带来的部分难题。

组成 说明 示例
<html>manifest属性 缓存文件清单。必须以text/cache-manifest MIME类型提供。注意:需在服务器上配置自定义文件类型。 页面中<html manifest="https://tingge.github.io/cache.mf">;服务(以Apache为例)中AddType text/cache-manifest .appcache
window.applicationCache 更新缓存
AppCache 事件

JS框架的实践

框架 说明 特点
localForage Mozilla 出品,将本地存储操作 API 封装成了键值对 (KVP)风格 简单,拿来即用
lovefield 谷歌出品的,为 Web App 提供 SQL-like APIs 服务的本地关系型数据库 关联查询等能力较强

通用 JavaScript(Universal JS)

Nodejs 目前主流的应用场景在于中间层:通过node进行模版渲染,处理部分业务逻辑。而真正的后端, 由专业的后端处理。

个人建议: UniversalJS 目前只是一种边际场景。推荐“Koa2 + Sequelize”的组合。另 Next.js 也值得一试。

框架 说明 相关
Next.js 通用 JavaScript 应用程序,基于 React,Webpack 和 Babel 快速创建支持服务端渲染的 React 应用的命令行辅助工具 create-next-app
Electrode
React Server
Universal Angular 2 Angular 2
Fastboot Ember
Hypernova Airbnb 推出的一种 Universal JS 方案

快速构建应用的工具包(Toolkit)

工具包 组合内容
VulcanJS React, GraphQL & Meteor

Node.js 模块

模块 说明
os Node.js 工具模块,提供一些基本的系统操作函数
co 用同步写法编写异步代码
json-logic-js 构建复杂的规则,将它们序列化为 JSON,并在 JavaScript 中执行它们
mathjs 一个数学库
ejs 嵌入式的 JavaScript 引擎
enums 兼容 java 的枚举
node-schedule 类 Cron 和非类 Cron 的定时任务
nodemailer 邮件发送模块
request 简化的HTTP请求的客户端
svg2png 转换 svg 为 png
vm2 虚拟模块
Hello.js 基于 OAuth 的浏览器端用户认证 SDK
Sharp 图像调整模块
AdonisJS 服务端渲染 的 MVC 框架, Laravel 的 NodeJS 版
csvtojson csv 数据转 json
prompt 命令行提醒
commander 提供了用户命令行输入和参数解析强大功能
semver 语义化版本规则

Web 服务 && RESTful API

Node.js 一类的反应堆模式,不太适合做复杂的事务型业务。

服务端框架 说明 个人小示例 相关
Egg 基于 Node.js 和 Koa 的企业级框架
Koa2 借 babel 通过 async/await 来支持 ES6+ koa2-spider
Koa 通过 co 生成器支持 ES6 koa-app
Hapi 「配置大于约定」,业务逻辑必须和传输层进行分离 hapi-app
Feathers
Now “微服务”
Nodal 用来创建基于 PostgreSQL 的无状态的、分布式的服务
expressjs5-app 社区生态完善。Express.js 黑历史后,IBM 过度干预,使 Douglas Wilson 在16年3月退出 5,个人建议转其它
Express 一个路由和中间件 Web 框架,其自身只具有最低程度的功能
Nodal
Keystone 以 Express 和 MongoDB 为基础搭建的 Node.js CMS 和 web 应用程序平台
Loopback 集“Express + ORM + RESTFul API”于一体的后端解决方案。 关联查询有些坑,个人建议转其它
DataLoader 一个通用工具。可用作应用程序数据提取层的一部分,为各种后端提供一致 API,并通过批处理和缓存减少对后端的请求。
Restify 仅是 API 服务,可观测 Http 应用的延迟、特征等

实时服务

  1. horizon-app
  2. meteor-test

数据库 Node 框架

与业务场景对应,数据库分为事务型分析型

一般 “ORM + SQL” 或 “SQL 客户端 + SQL” 组合,来满足常规规模应用。当流量大到数据库扛不住时,加入 MQ 服务。

事务是恢复和并发控制的基本单位,保证 ACID:原子性、一致性、隔离性、持久性。

ORM

Sequelize 提供对 MySQL,MariaDB,SQLite ,PostgreSQL 和 MSSQL 数据库的简单访问

SQL

客户端/驱动 说明
mysql 一个纯 javascript 实现的 nodejs 的 MySQL 客户端程序。MySQL 引擎比较好
node-postgres 一个支持纯 JavaScript 和本地 libpq 库绑定的 nodejs 的 PostgreSQL 客户端程序。个人感觉这个更好用点
pg-promise PostgreSQL 的 Promises/A+ 接口
sqlite3 SQLite 小、应用于移动端
hbase-client Node.js的异步HBase客户端

NoSQL

客户端/驱动 说明
cassandra-driver Cassandra 便于扩张
redis Redis 一般缓存、读写快
Mongoose MongoDB ODM(对象模型工具),即将 MongoDB 中数据转换为 JavaScript 对象以供在应用中使用
mongodb Mongo DB 原生的 NodeJS 驱动
nano 最简约的 CouchDB 客户端
level、levelup 和 leveldown LevelDB
apoc Neo4j

分布式

分布式的 CAP 理论,任何一个分布式系统无法同时满足 Consistency (一致性)、Availability (可用性) 和 Partition tolerance (分区容错性)。

其中, Consistency 是任何一个系统都不能放弃的,分布式事务亦是为了保证数据一致性,有时为了妥协另外两个特性,会放弃强一致性,来保证最终一致性

Node.js /浏览器 客户端库 对应的查询引擎
presto-client-node 分布式查询引擎 Presto
elasticsearch RESTful 搜索引擎 ElasticSearch
druid-query 分布式实时处理系统 Druid

数据库

类别 数据库 特点 应用场景
SQL MySQL 分析
PostgreSQL
SQLite
NoSQL Cassandra 列存储(Wide Column Store/Column-Family)数据库 日志;博客平台
HBase 分布式的、面向列的开源数据库
Redis 键值(Key-Value)数据库 储存用户信息
MongoDB 面向文档(Document-Oriented)数据库 日志;分析
Azure DocumentDB 一个完全托管的 NoSQL 数据库服务
CouchDB 同 MongoDB 同 MongoDB
LevelDB
Neo4j 图(Graph-Oriented)数据库 关系性强的数据; 推荐引擎
分布式查询引擎 Presto
实时的分布式搜索和分析引擎 ElasticSearch 面向文档的数据库 大数据;实时监控
分布式实时处理系统 Druid 列存储,分布式

研发基础平台

  1. 部署私有 Docker Registry 服务
  2. Docker 中搭建 GitLab服务器
  3. Nginx
  4. LDAP

附录

趋势

计算机视觉库

NodeJS

浏览器

HTML & 性能 & CSS

React & Angular & Vue 等

原理剖析