2

前言

较早的Nodejs开发者为了实现程序的同步都会使用几个“工具”,回调promiseco,或者是generator。记得写过一个递归删除目录下文件和文件夹的需求,用以上方法都是各种不爽(关键我就是想简单的写个递归啊)。

就在前几天Nodejs发布了v7.6.0版本。Nodejs开发者终于不用使用第三方模块就可以使用asyncawait让自己的程序在不需要异步的地方保持同步的特性了。

就在Nodejs v7.6.0刚发布不久,koa的作者也正式的发布的koa2

一句话总结:使用asyncawait是极大的解放生产力,减少脑细胞的消耗。

因为之前使用koa做了一个小项目,想着就把它给升级一下,及做一下网络请求方面的优化。

1.升级koa2.x及相关koa依赖

因为koa1.x和koa2.x区别还是挺大的。大部分的中间件目前已经做了针对koa2.x的兼容。没有做兼容的中间件,koa2.x本身也提供了方法进行兼容(后面会提到用法)。

升级的方法也很简单就是针对每一个中间件执行:yarn add koa-xxxxx@next 就可以升级到最新版本;

以下就是项目所依赖所有的中间件,都已经升级了最新的支持koa2。

"koa-bodyparser": "^3.2.0",
"koa-compress": "^2.0.0",
"koa-convert": "^1.2.0",
"koa-router": "^7.0.1",
"koa-static": "^3.0.0",
"koa-static-cache": "^4.0.0",
"koa-views": "^5.2.1",

2.针对koa2.x的特点对项目进行重构

koa1.x的特点就是使用genetator来控制项目的同步,而koa2.x最大的特点就是使用asyncawait

generator的写法:

myRouter.get('/', function *(){
    let body ;
    let peopleList =configParams.onDutyPeople();

    body = yield render('index', {'peopleList':peopleList});
    this.body = body;
    this.type='text/html; charset=utf-8';
});

await的写法

router
    .get('/', async(ctx, next) => {
        let peopleList = configParams.onDutyPeople();

        await ctx.render('index.jade', { 'peopleList': peopleList });
        ctx.type = 'text/html; charset=utf-8';
    })

3.不兼容koa2.x的中间件怎么办

在做网络优化的时候用到一个中间件koa-static-cache。这个中间件目前是不兼容koa2.x的,那么怎么在Koa2.x中使用呢?

运行的时候报错信息如下:

通过网络查询得出原因如下:

解决方法如下,使用koa-convert中间件把generator转化一下,使用方法如下:

const convert = require('koa-convert');
const staticCache = require('koa-static-cache');

//静态文件服务
app.use(convert(staticCache(path.join(__dirname, 'public'), {
    maxAge: 365 * 24 * 60 * 60
})));

对于代码的重构就是这样子,在需要使用promise来控制异步的地方,可以换写成asyncawait降低了代码的复杂度。第二就是对不支持koa2.x的中间件使用koa-convert来做兼容。

4.网络请求的优化

通过下面的图片可以发现,页面在加载过程中请求了多个静态文件。这无疑会影响页面的加载速度。从打开页面到页面加载完成总共花费了2.59s

那么怎么优化呢?其实就是借用了请打的fis对静态文件进行了压缩和合并。使页面在加载过程需要多个静态文件,变成只请求两个静态文件。最后优化的结果是页面加载只需要1.76s比之前快了将近1s。效果还是很明显的。

当我在观察这些网络请求的时候发现一个问题。每次我刷新页面或者是关闭浏览器重新打开页面的时候,浏览器都没有使用本地的缓存文件,而是重新向服务器发送请求,下载需要的静态文件。看下面的截图:

5.使浏览器使用本地缓存文件

做法也很简单,就是使用koa中间件koa-static-cache控制服务端的静态文件在客户单进行缓存。


//静态文件服务
app.use(convert(staticCache(path.join(__dirname, 'public'), {
    maxAge: 365 * 24 * 60 * 60
})));

我们来看看这样做到底有没有什么效果?看下面的截图(我多刷了几次页面):

与前面的那张截图做对比可以明显的发现,静态文件的下载时间变短了。页面加载时间变为了1.44s。比之前还是有所缩短的。而且在size那一栏会看到from memorycachefrom disk cache这样的字段。而不再是显示具体的文件大小。关于这里的区别可以看文章最后的参考文章。

6.对“文件”资源进行压缩

大多数情况下,我们的网站不仅仅就是存文字的还要包含一些其他类型的文件,比如:图片,mp3等。我们知道浏览器是支持加载gzip压缩过的网页的,所以以nginx为代表的静态文件服务器默认都会开启gzip压缩。那么我们Nodejs服务能不能对资源文件进行压缩呢?

答案是肯定的。Koa的作者写了一个中间件compress,支持对请求的response进行压缩,具体的使用如下:

var compress = require('koa-compress')
var Koa = require('koa')

var app = new Koa()
app.use(compress({
  filter: function (content_type) {  //配置过滤的压缩文件的类型
    return /text/i.test(content_type)
  },
  threshold: 2048,   //要压缩的最小响应字节
  flush: require('zlib').Z_SYNC_FLUSH  //同步的刷新缓冲区数据;
}))

因为当前项目中并没有提价较大的文件,所以该中间件并没有在项目中使用。这里仅仅介绍koa有中间件提供这样的能力供开发者使用。

7.怎么维护一个稳定nodejs服务

像这样node app.js来维护线上的服务肯定是不行。因为端口可能会不知不觉让linux给kill掉。目前在业界普遍使用的都是pm2来维护nodejs服务。提供了日志,端口被Kill后自动重启,性能监控等强大的功能。

7.1收集系统日志

使用pm2启动Nodejs进程后,会默认吧代码运行异常的错误和标准输出日志(比如:console.log)打到以下的目录下面。

7.2进程信息

提供了进行运行时相关信息;

7.3性能监控

提供了内存监控和cpu监控的命令。

总结:

FE到现在在大多数的后端工程师眼中都是切切页面,用js写写“特效”的角色。所以被大家戏称为“页面仔”。这也是为什么说FE是一个很容易遇到职业瓶颈的行业。

自从基于Nodejs的前后端开发模式在业界得到越来越多的实践后,前端工程师在其中扮演着重要的角色。由以上内容可以看出,在使用Nodejs以后,虽然前端技术栈得到了机房,但对FE的个人素质要求也会有所提高,性能优化网络请求优化都是前端工程师需要去面临的问题。因为我们会成为用户发起的网络请求在服务端的第一层接收者,我们也会面临着web安全的问题。

参考资料:

Koa文档

Koa2入门

配置错误产生的差距:200 OK (FROM CACHE) 与 304 NOT MODIFIED

HTTP缓存技术,304(Not Modified)和200(from cache)有何区别?


zhiqiang21
1.4k 声望1.1k 粉丝

I'm a Vimer!