別のnode.jsライブラリ...

次のJSライブラリの出現のために、カウンタをリセットできると思います。







それはすべて、6年前にnode.jsに出会ったときに始まりました。 約3年前、私は素晴らしいexpress.jsライブラリとともにプロジェクトでnode.jsを使い始めました(wikiではフレームワークまたはパッケージと呼ばれることもありますが、アプリケーションフレームワークと呼ばれます)。 Expressは、node.js httpサーバーと、RubyのSinatraフレームワークのイメージで作成されたミドルウェアシステムを組み合わせます。







私たちは皆、新しいライブラリの作成速度とJSの開発速度について知っています。 IO.jsとの分離と統合の後、node.jsはJS-ES6の世界から、そして4月-ES7の世界から最高のものを取りました。







これらの変更の1つについてお話したいと思います。 特にasync / awaitPromiseについて 。 ExpressプロジェクトでPromiseを使用して、 node.js 7のフラグを使用してasync / awaitを使用しようとすると、調和のとれた興味深い新世代のフレームワークである koa.js、特に2番目のバージョンに出会いました。







最初のバージョンは、 ジェネレーターCOライブラリーを使用して作成されました。 2番目のバージョンは、Promise / async / awaitを使用する際の利便性を約束し、フラグなしでこれらの機能をサポートするnode.jsの4月リリースを待っています。







koaのコアを調べ、Promiseとの作業がどのように実装されているかを知ること 、私にとって興味深いことでした。 でも驚いた コアは以前のバージョンとほぼ同じままです。 エクスプレスライブラリとコアライブラリの両方の作成者は同じです。アプローチが同じままであることは驚くことではありません。 ミドルウェアの構造を意味します。 node.jsになる段階でRubyのアプローチを使用することは有用でしたが、JSのような現代のnode.jsには利点、美しさ、優雅さがあります...







ちょっとした理論。







Node.js httphttps )サーバーは、 EventEmitterを実装するnet.Serverを継承します。 そして、すべてのライブラリ(express、koa ...)は、本質的にserver.on( 'request')イベントのハンドラです。

例:







const http = require('http'); const server = http.createServer((request, response) => { //   });
      
      





または







 const server = http.createServer(); server.on('request', (request, response) => { //     });
      
      





そして、真の「新世代フレームワーク」がどのように見えるべきか想像しました。







 const server = http.createServer( (req, res) => { Promise.resolve({ req, res }).then(ctx => { ctx.res.writeHead(200, {'Content-Type': 'text/plain'}); ctx.res.end('OK'); return ctx; }); });
      
      





これにより、たとえばexpressで実装されているように、すべてのレベルでコールバックの地獄と一定のエラー処理を取り除く絶好の機会が与えられます。 また、これにより、 Promise.all()を使用して、ミドルウェアを順次ではなく並列に「実行」できます。







そして、別のライブラリーが生まれました: YEPS -Yet Another Event Promiseed Server。







YEPS構文は、ミドルウェアの並列処理など、約束ベースの設計アーキテクチャのすべての単純さと優雅さを伝えます。







 const App = require('yeps'); const app = new App(); const error = require('yeps-error'); const logger = require('yeps-logger'); app.all([ logger(), error() ]); app.then(async ctx => { ctx.res.writeHead(200, {'Content-Type': 'text/plain'}); ctx.res.end('Ok'); }); app.catch(async (err, ctx) => { ctx.res.writeHead(500); ctx.res.end(err.message); });
      
      





または







 app.all([ logger(), error() ]).then(async ctx => { ctx.res.writeHead(200, {'Content-Type': 'text/plain'}); ctx.res.end('Ok'); }).catch(async (err, ctx) => { ctx.res.writeHead(500); ctx.res.end(err.message); });
      
      





たとえば、 errorloggerredis packagesがあります







しかし、最も驚くべきことは仕事のスピードでした。 YEPSのパフォーマンスをexpresskoa2 、さらにはnode.js httpと比較するパフォーマンス比較テスト-yeps-benchmarkを実行できます。







ご覧のように、並列実行は興味深い結果を示しています。 これはどのプロジェクトでも達成できますが、このアプローチは、パフォーマンステストなしで単一のステップを踏むのではなく、アイデア自体でアーキテクチャ内に定義する必要があります。 たとえば、ライブラリのコアであるyeps-promisifyは 、array.slice(0)を使用します。これは、配列をコピーするため最速の方法です







ミドルウェアの並列実行の可能性により、Promise.all()で完全に作成されたルーター(ルーター、ルーター)を作成するというアイデアが生まれました。 正しいルート(ルート)、正しいルールをキャッチし、それに応じて目的のハンドラーを返すというアイデアは、Promise.all()の中心にあります。







 const Router = require('yeps-router'); const router = new Router(); router.catch({ method: 'GET', url: '/' }).then(async ctx => { ctx.res.writeHead(200); ctx.res.end('homepage'); }); router.get('/test').then(async ctx => { ctx.res.writeHead(200); ctx.res.end('test'); }).post('/test/:id').then(async ctx => { ctx.res.writeHead(200); ctx.res.end(ctx.request.params.id); }); app.then(router.resolve());
      
      





すべてのルールを順番に列挙する代わりに、すべてのチェックを同時に実行できます。 この点は、パフォーマンステストなしで残されたものではなく、 結果はすぐに現れます。







最初のルールを見つけるのは約10%高速でした。 最後のルールはまったく同じ速度で機能し、他のライブラリよりも約4倍高速です(ここでは10のルートについて話しています)。 統計を収集して分析する必要がなくなり、どのルールを立てるべきかを考えます。







しかし、完全な生産準備作業のために、「 鶏と卵 」の問題を解決する必要がありました-追加のパッケージなしでライブラリを使用したり、未使用のライブラリにパッケージを書き込んだりする人はいません。 ここでは、 ラッパーが役立ち、 body-parserserve-faviconなどの高速ミドルウェアを使用できるようになりました...







 const error = require('yeps-error'); const wrapper = require('yeps-express-wrapper'); const bodyParser = require('body-parser'); const favicon = require('serve-favicon'); const path = require('path'); app.then( wrapper(favicon(path.join(__dirname, 'public', 'favicon.ico'))) ).all([ error(), wrapper(bodyParser.json()), ]);
      
      





また、アプリケーションテンプレートがあります-yeps-boilerplate 、これにより、新しいアプリケーションを起動し、コード、サンプルを表示できます...







この研究と結果が役に立つことを願っています。それは、美しく、速く、多分エレガントなソリューションを作成するようにあなたを刺激するかもしれません。 そしてもちろん、各ステップのパフォーマンスをテストするという考え方は、新規および既存のプロジェクトの基盤を形成するはずです。







PS:コメントにヒント、アイデア、建設的な批判を期待しています。








All Articles