JavaScript 和前端前沿技术探索
本文最后更新于 2018年02月24日。
“一套单页面应用,任何 path 访问都是服务端渲染、然后客户端路由,既解决 seo 问题,又解决渲染问题和前后端分离问题,并且为未来的 progresive web app 做准备。套上 servie worker 就具有离线功能。所以,从前端开发者长期受益来看,放弃 node 是弊大于利的。”—— 语自 @携程-工业聚
“集市” 和“大教堂”之争,推动着前端这个大生态的繁荣和演进。我把这个过程,总结为 “工程实践 + 标准化 => JavaScript 生态”。
Web 前端
至今,没有最佳实践,大家对同一个问题通常有不同解法。这是 library 相对于 framework 的劣势。 目前,主流的三大 FRP 框架 React系、Angular 2系、Vue系 在相互融合。
另外,Hyperapp + Parcel 也是个值得关注的组合。hyperapp-parcel-app 项目和相关文章。
推荐的React设计模式、技术、技巧和窍门:React Bits
技术 | React系(Webpack+ React + Redux) | Progressive Web App | 微信小应用 | 支付宝小程序 | |
---|---|---|---|---|---|
JS 编译器 | TypeScript、Flow、CoffeeScript | Babel + ES6 | |||
CSS 预处理 | Scss/Sass、Less、Stylus | sass-loader、style-loader、css-modules、styled-components、cssnano | |||
CSS 后处理 | PostCSS、uncss、Critical、CSSO | ||||
CSS 样式库 | CSSgram(滤镜特效)、You-Dont-Need-JavaScript(UI 组件) | ||||
web UI | Semantic UI、Masonry、Bootstrap、Fuel UX、Ratchet、Materialize、Material-UI、Angular Material、Bulma(基于Flexbox)、 Grd | Ant-design、Fusion Design(Next)、UXCore、Material-UI、Semantic-UI-React、Blueprint、React-Bootstrap、React-Toolbox、Grommet、Fabric、React-md、hyperapp、React Desktop、 | |||
H5 UI | SUI Mobile、 FrozenUI、 React-WeUI、 Framework7、Phonon、Foundation、Material Foundation | Fusion Design(Mext) | |||
UI 组件 | spectrum(Colorpicker)、jquery-qrcode、chosen、CodeMirror、 jPicker、paginationjs、lz-string、PapaParse、particles.js、handsontable、ORY Editor、Trix、push.js、zuck.js | react-color、React-Grid-Layout、fixed-data-table、fixed-data-table-2、react-virtualized、react-transitive-number、 ckeditor、 echarts、 react-list、 sortablejs | |||
后台管理模版 | Gentelella Admin | ||||
Shim | es6-shim、es5-shim.js | ||||
Polyfill | reflect-metadata | babel-polyfill、 ima.js-babel6-polyfill、 regenerator-runtime/runtime(async wait 的 polyfill) | |||
DOM库 | zepto、jQuery、 | react-dom | |||
HTML 5兼容旧浏览器 | html5shiv、object-observe(Object.observe polyfill)、 Feature.js | ||||
多点触摸手势库 | Hammerjs、jGestures、 | react-hammerjs | |||
工具库 | ramdajs、lodash、underscore、collect.js、LZMA-JS、crypto-js、Tether、PinYin、Moment、Numeral、humanize、Cleave.js(格式化)、Mousetrap、flat、setRafTimeout | react-cookie、react-qart、classnames、glamorous、glamor、d3-format、prismjs、react-sizeme、clipboard、 detector、 pubsub-js、 query-string、 react-dropzone、 react-motion、 react-scroll、react-flight、highlight.js、react-json-inspector、source-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 VR、Hyperapp | |||
高阶组件(HOC) | Recompose | ||||
MV* 框架(路由、数据获取、状态管理) | Angular、Aurelia、Avalon、Ember | ||||
Pure Render | pure-render-decorator | ||||
动画 | AOS、Animate.css | react-transition-group、rc-queue-anim、react-flight、Popmotion、Ant Motion、 React-Motion | |||
表单 | redux-form、 Formik | ||||
表单验证 | React 内置的 propTypes、Yup | ||||
路由控制,可选 | react-router、react-router-redux、junctions | ||||
连接React 组件与 Redux store,可选 | React-Redux | ||||
中间件与异步操作 | Async、Q | redux-thunk | |||
不可变数据结构 | Immutable.js、immutability-helper、seamless-immutable、 mori、cortex | ||||
应用状态管理 | ngrx/store | Redux(redux-promise/redux-sequence-action、redux-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-views、 React 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 的时候应该确保内容和表现的分离。
可视化
- JavaScript应用领域(d3-test)
- heatmap.js:Web 的动态 JavaScript 热图
- recharts
工程化/工作流
专题 匠心之路—工具
- Parcel:号称“零配置、构建快”的打包工具,应用场景和 Webpack 类似
- Webpack:业务项目常用的打包工具
- rollup-test:库项目常用的打包工具
- broccoli-babel-test
- grunt-babel-test
- phantomjs-test
- 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 应用的延迟、特征等 |
实时服务
数据库 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 | 列存储,分布式 |
研发基础平台
- 部署私有 Docker Registry 服务
- Docker 中搭建 GitLab服务器
- Nginx
- LDAP
附录
趋势
计算机视觉库
NodeJS
浏览器
HTML & 性能 & CSS
- Web 性能
- JavaScript 启动性能瓶颈分析与解决方案
- 下一代 Web 应用模型 —— Progressive Web App
- HTML 5
- 移动端适配方案。大致思路是:flexible.js 或 metahandler.js
- Houdini:CSS 领域最令人振奋的革新
- 前端开发中的一些黑魔法Pt2
- Sass绘制多边形
- CSS布局之-水平垂直居中
- H5项目常见问题汇总及解决方案
- 应用缓存初级使用指南
- 检查和管理存储、数据库与缓存
React & Angular & Vue 等
- An imperative guide to forms in React:React 表单组件 Formik
- Design Patterns with React Easy State:React 状态管理 React Easy State
Hyperapp for Redux refugees:React 替代品 Hyperapp,包含 view 和类 Redux 的状态管理
- Create React App:一个 Facebook 的React Boilerplate项目
- 让React组件变得可响应
- 复杂单页应用的数据层设计
- christianalfoni - Why we are doing MVC and FLUX wrong
- Webpack — The Confusing Parts
- webpack build可视化统计分析
- Next.js提供了基于React的简单通用JavaScript框架
- Angular 2 Keynote(September 27,2016)Slider