Vue服务端渲染Bigpipe,IO密集Koa 2等问题回复

Posted Node全栈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue服务端渲染Bigpipe,IO密集Koa 2等问题回复相关的知识,希望对你有一定的参考价值。

狼叔说:最近因为工作,以及家里生娃,没太多更新,请大家谅解,只要我时间ok就会尽量更新的~



整理了一下最近大家问的比较多的问题,具体如下,希望对大家有用


为啥说Node.js适合io密集操作

理解http,基本的请求响应模型

var http = require("http");

http.createServer((req, res) => {    res.writeHead(200, {        "Content-Type": "text/plain"    });    res.write("Hello World");    res.end();
}).listen(8888);


理解事件驱动,凡是简单on("data",function(chunk){}的,是listener监听器,都是继承自EventEmit才有的功能,那么事件emit发射在哪里?自己试着想想

var http = require('http');

http.createServer(function(request, response) {  var body = [];  request.on('data', function(chunk) {    body.push(chunk);  }).on('end', function() {    body = Buffer.concat(body).toString();    response.end(body);  });
}).listen(8080);


理解Stream,各种语言、框架里pipe管道(比如shell里,比如gulp里的pipe),本身http就是io操作比较多,使用Stream流式处理可以减少切换成本,无中间文件等,

Stream学习资料 https://cnodejs.org/topic/570b1fa494b38dcb3c09a7f8


var http = require('http');

http.createServer(function(request, response) {  if (request.method === 'GET' && request.url === '/echo') {    request.pipe(response);  } else {    response.statusCode = 404;    response.end();  }
}).listen(8080);


如果一个请求要多次处理呢?


request.pipe(xx).pipe(yy).pipe(response);


总结,说Node.js适合io密集操作,确实是,就是为了Node.js异步io而生的。这部分是有优化的,所以它比较强,如果在cpu密集方面也有类似的库,是不是它也适合cup密集工作呢?凡事皆有二面性,非不能解,看想不想解。

koa好是好,不过第三方生态圈不如express,express好多比较有特色的模块,并不直接支持koa

koa好是好,不过第三方生态圈不如express,express好多比较有特色的模块,并不直接支持koa。虽然也可以转,但是用起来还是不如原生用的方便。

如果说要比生态,用java和php等老牌语言会更加成熟。其实选型取舍是需求和追求,express已经很长时间了,是非常稳定的web框架。从代码提交、issues、测试就可以看出来。明显比Koa要完善很多。本质上,它最多是Node.js http模块的强力补充。

我们又要回到那个很久远的问题,都喜欢温水,都不喜欢冷水,换一个环境多少会有不适应的感觉。最好是一只不变下去。但实际呢?技术的驱动和演进往往是那些打破你舒适区的东西。我也是个express老司机,我也很喜欢拿express去理解koa,被苏大fengmk2喷过好几次,如果要完全一样,革新干什么呢?

举个例子:webpack-dev-middleware算比较火热的模块了,它只支持express

如果想改写成Koa版本,你需要掌握2点

  • Koa中间件写法(基础)

  • webpack-dev-middleware模块的用法

代码如下

'use strict'

const devMiddleware = require('webpack-dev-middleware')

module.exports = (compiler, opts) => {  const expressMiddleware = devMiddleware(compiler, opts)  return (ctx, next) => {    return expressMiddleware(ctx.req, {      end: (content) => {        ctx.body = content
     },      setHeader: (name, value) => {        ctx.headers[name] = value      
     }    }, next);  }
}
  • 用法,传参都一样

  • return (ctx, next) => {} 是Koa 2.x经典的中间件写法

  • 配置项end和setHeader等都是webpack-dev-middleware里需要的

就这点代码,难度很大么?折腾了一番,相信大家对webpack-dev-middleware这个模块会有更深入的理解。

爷爷都是从孙子走过来的,哪个大牛没写过hello world!

Koa-bigpipe

bigpipe当年给facebook立了很大功劳。给出百科简介

BigPipe是一个重新设计的基础动态网页服务体系。大体思路是,分解网页成叫做Pagelets的小块,然后通过Web服务器和浏览器建立管道并管理他们在不同阶段的运行。这是类似于大多数现代微处理器的流水线执行过程:多重指令管线通过不同的处理器执行单元,以达到性能的最佳。虽然BigPipe是对现有的服务网络基础过程的重新设计,但它却不需要改变现有的网络浏览器或服务器,它完全使用PHPjavascript来实现。

它只是优化技术而已,很明显这段简介里是有问题的。早起fb是php,微博也是php,所以才有这个无解。但技术问题是通用的,所有语言都可以实现,只是看哪个简单哪个高效而已。用Node.js实现bigpipe是非常好的选择。

这里简单说一下大家对bigpipe技术的感觉,在express使用res.write,多次写html片段到浏览器,而已。

原理上确实是这样的,所以说也对也不对,原因是你真的在项目里使用它了么?

Koa里没有提供对bigpipe的支持,ctx.body赋值做了很多约定。可以说是不太容易控制。

  • http模块是基于stream的,所以方案1是通过require(‘stream’).Readable来处理,这种是非常容易理解,但要求大家对stream有一个比较好的理解。

  • 方案2,反正Koa和express都是基于http模块的,那么为什么不用http模块的方法呢?

在Koa里有2个概念非常容易混,req和request,res和response,我们经常在express里用req和res,但在Koa里它们指的是http启动server时传入的req和res参数

var http = require("http");http.createServer((req, res) => {    res.writeHead(200, {        "Content-Type": "text/plain"    });    res.write("Hello World");    res.end();
}).listen(8888);

那么是不是可以不用Koa的东西,改用http的接口呢?res.write和express里的res.write是一样的。

所以代码如下

'use strict'

/** * Module exports. * @public */

module.exports = (ctx, next) => {  ctx.type = 'html'  ctx.status= 200  ctx.chunks = []  let req = ctx.req  let res = ctx.res  // write chunk to browser  ctx.write = (chunk) => {    if (!chunk) {      return ctx.end()    }    ctx.chunks.push(chunk)    res.write(chunk)  }  // end response  ctx.end = (chunk) => {    if (chunk) {      ctx.write(chunk)    }    res.end(null)  }  return next()
}

总结一下,ctx.write和ctx.end方法是为了保持跟koa风格一致,ctx本身是上下文的意思,通过提供这2个方法来完成bigpipe,其实如果从简,你直接ctx.res.write也是可以的。

vue ssr

抓出一段代码

// example usage with express

app.get('/', (req, res) => {  const vm = new App({ url: req.url })  const stream = renderer.renderToStream(vm)  res.write(`<!DOCTYPE html><html><head><title>...</title></head><body>`)  stream.on('data', chunk => {    res.write(chunk)  })  stream.on('end', () => {    res.end('</body></html>')  })
})

这很明显就是express里bigpipe的写法。如果你想把它改成Koa版本的,那么你首先要搞定Koa版本的bigpipe如何实现。然后再考虑vue的ssr。

如果盲点太多,又怕坑,那么还是早早的转行吧,这个时刻需要学习的行业不适合你~

退一步讲,如果连express这段代码都不是特别懂,那还是乖乖的用express好了。

给出Koa vue ssr的代码

app.use((ctx, next) => {  let res = ctx.res  let req = ctx.req  if (!renderer) {    return res.end('waiting for compilation... refresh in a moment.')  }  var s = Date.now()  const context = { url: req.url }  const renderStream = renderer.renderToStream(context)  let firstChunk = true  ctx.write(html.head)  renderStream.on('data', chunk => {    if (firstChunk) {      // embed initial store state      if (context.initialState) {        ctx.write(          `<script>window.__INITIAL_STATE__=${            serialize(context.initialState, { isJSON: true })          }</script>`        )      }      firstChunk = false    }    ctx.write(chunk)  })  renderStream.on('end', () => {    ctx.end(html.tail)    console.log(`whole request: ${Date.now() - s}ms`)  })  renderStream.on('error', err => {    throw err  
 })
})

使用了ES6和module,如何做测试和覆盖率

测试和覆盖问题

这个问题有点蒙,测试框架是独立的,通用的,对Koa还是express没有啥区别。

引入es6对测试的影响,我觉得只是多了一步实例化的过程,整体并无太多。另外其他特性,新版的测试框架都已经集成的差不多了。

如果激进点,选择ava,非常爽,非常快,尤其是新特性,如果想保守点,可以用mocha,另外jest和jasmine也不错。

测试覆盖率还是要在根上看,如果严格遵守tdd或bdd,做这个比较容易。如果是为了做而做就失去意义的。

Google出来的文章分不清Koa 1和Koa 2

不能一概而论,下面的方法可以快速辨别

方法1

直接用的是Koa1

var koa = require('koa')var app = koa()

实例化的是Koa2

const Koa = require('koa')const app = new Koa()

方法2

中间件,完全是generator的,一定是koa1

function* hello() {  yield 'hello';  yield function () {    return 'generator';  };  return 'done';
}

如果出现convert和co.wrap的就是Koa2

另外async/await和function(ctx, next)也是koa2

方法3

在处理过程中,大量使用this的,是koa1

而使用ctx显示声明的,是koa2

我使用了koa static管理public资源,当资源不存在时,依然走了后面的N个中间件,怎么才能在资源没有时,直接404

这其实是中间件的原理问题。

static放到最前面,如果找不到资源,自然会将请求转交给后面的路由或中间件的的。

可以使用 https://github.com/koa-modules/serve-static 这个,效率高,逻辑等同express。

至于中间件原理,限于篇幅,参见 https://github.com/i5ting/stuq-koa


大前端和 Node.js那些事儿


文中很多内容讲的不够深入,如果想交流,请在1月24日知乎live上详聊,我要讲的主题是《大前端和Node.js哪些事儿》有兴趣的可以来聊聊

本次 Live 是受斯达克学院「 StuQ 公开课」的邀请,并与「 StuQ 公开课」共同策划,我将围绕大前端和 Node.js 进行深度解读。随着大前端的演进与火爆, h5 、 hybrid 、组简化、小程序,越来越多的公司和程序员不得不去重视前端,那么多框架 react 、 vue 、 ng2 到底该怎么选?没有很多经验的程序员该如何高效的解决问题?对于不得不用的 Node.js 欲拒还迎,到底该如何抉择?作为资深全栈工程师、架构师、实践者,狼叔带你回顾 2016 ,展望 2017 ,以 Node.js 视角来帮助大家更好处理前端问题。

本次 Live 主要包括以下内容:

  • * Node.js 2016 回顾

  • * Node.js 的应用场景(前端工具、 proxy2 种、后端、微服务)

  • * Node.js 如何高效配合服务器端渲染(以 react 、 vue 为例)

  • * 如何结合 Node.js 完成更多(以最近写的 bigview 模块为例)

  • * 如何在真实项目里使用、推广 Node.js ?

  • * Node.js 2017 展望


如果想参与Live一起来聊聊,请点击阅读原文链接,进入知乎Live链接


全文完

你身边如果有朋友对Node.js或全栈感兴趣,可以转发给他们看看哦,O(∩_∩)O先谢过


以上是关于Vue服务端渲染Bigpipe,IO密集Koa 2等问题回复的主要内容,如果未能解决你的问题,请参考以下文章

Vue+koa2开发一款全栈小程序(5.服务端环境搭建和项目初始化)

Vue.js+Koa2移动电商实战-1

vue项目改造SSR(服务端渲染)

前后端分离全栈开发项目师徒开启,VUE+koa+MongoDB!

使用 Vue 2.0 实现服务端渲染的 HackerNews

Vue 2.0 服务端渲染入门