参考
jason strimpel & Maxime Najim
同构 javascript (isomorphic javascript) 是 Spike Brehm 提出的
Niko kobler 的
with nashorn and react.js
zZTpb.png同构源于希腊语,iso 是等于意思而 morph 是形状的意思。同构是一个数学上术语,对于两个数学对象来说,如果我们简单地忽略他们的 差异,则当他们具有相似的属性和操作时,就是同构。
同构 javascript 我们 (客户端和服务端)的 context 不同的代码看做一个整体,让客户端和服务端共享一套代码。
任何一个应用都可能用 javascript 进行开发,最终也将会用 javascript。
在 Ilya Grigorik 在 《Web 性能权威指南》 中提到解释了 TCP 协议是经过“ 客户端与服务端之间 4 次 往返...以及几百毫秒的延迟,才能 到达 64KB 的吞吐量”。
1. 为什么需要同构 javascript
现在单页应用框架泛滥,也占据主导地位。 本来想用业余时间也 写一个类似 vue 的框架(竟说大话)。
- 支持 SEO
- 快速加载
- 特别对移动用户友好
最近几年 web 应用开发从重服务端、轻客户端方式转变为重客户端、轻服务端。在中国,是讲究中庸,无论是重服务端、轻客户端还是重客户端、轻服务端,如果做的太过都会有问题。
重客户端\轻服务端的问题
- SEO
- 首次加载的问题
想想一下客户端和服务器端共享一套代码的好处是
- DRY 原则代码重用
- 共享相同逻辑
- 维护一套代码
- 可能是同一种语言
- 同一种技术,我们服务端和客户端可以用同一套技术进行实现,何乐而不为
定义同构 Javascript
评价其他 Web 应用架构方案
同构 Javascript 图谱
屏幕快照 2019-02-23 下午1.50.40.png 屏幕快照 2019-02-23 下午1.50.48.png共享模板
为了加载速度和 SEO 希望服务端也能够像客户端那样进行渲染。视图渲染从客户端向服务端渲染,客户端接受从服务端渲染成字符串格式模板,也就是浏览器加载后客户端还需进行适当的转换。dehydrate 和 rehydrate。
服务端渲染
- 可以解决SPA 加载速度慢的问题
- UX
<div>[[server_side_rendered_markup]]</div>
<script>
window.__state__ = [
[serialized_state]
]
</script>
共享路由
路由是控制跳转事件、改变状态和页面视图的主要机制。所以服务端和客户端只需要一套路由,并且方便共享,难点在于经常需要访问环境相关的 API,例如 URL 信息、HTTP 头部信息以及 cookie。
- 服务端:通过请求 对象获取
- 客户端:通过浏览器 API 获取
同构 javascript 的分类
超越服务器端的渲染
实时 Web 应用
- 同构 API
- 双向数据同步
-
在服务器端进行客户端仿真
在极端情况下,同构 javascript 应用版本问题
起步
我们 需要的 javascript 库
- Node.js 服务端使用的语言
- Hapi.js 服务端使用的框架
- Gulp.js
- Babel.js
服务端我们用 nodejs 的 hapi 框架来写
- 安装 nodejs
- 使用 npm 管理项目
npm install hapi
import Hapi from "hapi";
import nunjucks from "nunjucks";
const server = new Hapi.server({
host:'localhost',
port:'4200'
});
nunjucks.configure('./dist')
server.route({
method:'GET',
path:'/hello',
handler:function(request,reply){
return 'hello world';
}
});
server.start();
这是搭建好服务端,开始时候我们用 const Hapi = require('hapi'),运行代码没有问题。随后我们用
import Hapi from "hapi"; 会提示我们错误,因为 nodejs 是支持 commonjs来管理模块的,而我们这里用的是 es6 的模块管理,需要进行处理一下。
npm install -g gulp
npm install babel --save-dev
npm install --save-dev babel-cli babel-preset-es2015
npm install gulp gulp-babel --save-dev
然后我们创建一个 gulpfile.js
var gulp = require('gulp');
var babel = require('gulp-babel')
var nodemon = require('gulp-nodemon')
gulp.task('compile',function(){
return gulp.src("src/**/*.js")
.pipe(babel({
presets:['es2015']
}))
.pipe(gulp.dest('dist'))
});
网友评论