apeescape2.com
  • メイン
  • アジャイル
  • 製品の担当者とチーム
  • 仕事の未来
  • リモートの台頭
バックエンド

ノード8を使用する時が来ましたか?

ノード8が出ました!実際、ノード8は、実際の使用法を確認するのに十分な時間使用されています。高速な新しいV8エンジンと、async / await、HTTP / 2、asyncフックなどの新機能が付属しています。しかし、それはあなたのプロジェクトの準備ができていますか?確認してみましょう!

編集者注: あなたはおそらくノード10(コードネーム ドブニウム )も出ています。ノード8に焦点を当てることを選択しています( 炭素 )2つの理由:(1)ノード10はちょうどロングタームサポート(LTS)フェーズに入ったばかりであり、(2)ノード8はノード10よりも重要な反復をマークしました。

ノード8LTSのパフォーマンス

まず、この注目に値するリリースのパフォーマンスの向上と新機能を見ていきます。改善点の1つは、NodeのJavaScriptエンジンです。



正確には です とにかく、JavaScriptエンジン?

JavaScriptエンジンがコードを実行し、最適化します。これは、JavaScriptをバイトコードにコンパイルする標準のインタープリターまたはジャストインタイム(JIT)コンパイラーである可能性があります。 Node.jsで使用されるJSエンジンは、すべてJITコンパイラーであり、インタープリターではありません。

V8エンジン

Node.js Googleを使用しました Chrome V8JavaScriptエンジン 、または単に V8 、最初から。一部のノードリリースは、新しいバージョンのV8と同期するために使用されます。ただし、ここではV8バージョンを比較するため、V8とノード8を混同しないように注意してください。

ソフトウェアのコンテキストでは、スラングとして「v8」を使用したり、「バージョン8」の正式な短縮形を使用したりすることが多いため、これは簡単に失敗します。そのため、「NodeV8」または「Node.jsV8」を「NodeJS8」と混同する場合があります。 」ですが、この記事では、物事を明確にするためにこれを避けています。 V8は、ノードのバージョンではなく、常にエンジンを意味します。

契約vsフルタイム給与計算機

V8リリース5

ノード6は、JavaScriptエンジンとしてV8リリース5を使用します。 (ノード8の最初のいくつかのポイントリリースもV8リリース5を使用しますが、ノード6よりも新しいV8ポイントリリースを使用します。)

コンパイラ

V8リリース5以前には、2つのコンパイラがあります。

  • フルコードゲン はシンプルで高速なJITコンパイラですが、遅いマシンコードを生成します。
  • クランクシャフト は、最適化されたマシンコードを生成する複雑なJITコンパイラです。
スレッド

深く掘り下げてみると、V8は複数のタイプのスレッドを使用しています。

  • メインスレッドはコードをフェッチし、コンパイルしてから実行します。
  • メインスレッドがコードを最適化している間、セカンダリスレッドはコードを実行します。
  • プロファイラースレッドは、パフォーマンスの悪いメソッドについてランタイムに通知します。次に、クランクシャフトはこれらの方法を最適化します。
  • 他のスレッドはガベージコレクションを管理します。
コンパイルプロセス

まず、Full-codegenコンパイラがJavaScriptコードを実行します。コードの実行中に、プロファイラースレッドはデータを収集して、エンジンが最適化するメソッドを決定します。別のスレッドでは、クランクシャフトがこれらのメソッドを最適化します。

問題点

上記のアプローチには2つの主な問題があります。まず、それはアーキテクチャ的に複雑です。第二に、コンパイルされたマシンコードははるかに多くのメモリを消費します。消費されるメモリの量は、コードが実行される回数とは無関係です。一度だけ実行されるコードでさえ、かなりの量のメモリを消費します。

V8リリース6

V8リリース6エンジンを使用する最初のノードバージョンはノード8.3です。

リリース6では、V8チームはこれらの問題を軽減するためにIgnitionとTurboFanを構築しました。 IgnitionとTurboFanは、それぞれFull-codegenとCrankShaftに取って代わります。

新しいアーキテクチャはより単純で、より少ないメモリを消費します。

点火 JavaScriptコードをマシンコードではなくバイトコードにコンパイルし、多くのメモリを節約します。その後、 ターボファン 、最適化コンパイラは、このバイトコードから最適化されたマシンコードを生成します。

特定のパフォーマンスの改善

以前のノードバージョンと比較して、ノード8.3以降のパフォーマンスが変化した領域を見ていきましょう。

オブジェクトの作成

オブジェクトの作成は、ノード8.3以降ではノード6よりも約5倍高速です。

関数サイズ

V8エンジンは、いくつかの要因に基づいて関数を最適化する必要があるかどうかを決定します。 1つの要因は関数のサイズです。小さな関数は最適化されますが、長い関数は最適化されません。

関数サイズはどのように計算されますか?

古いV8エンジンのクランクシャフトは、「文字数」を使用して機能サイズを決定します。関数内の空白とコメントは、関数が最適化される可能性を減らします。これはあなたを驚かせるかもしれませんが、当時、コメントは速度を約10%低下させる可能性がありました。

ノード8.3以降では、空白やコメントなどの無関係な文字が関数のパフォーマンスに悪影響を与えることはありません。何故なの?

最近発生した可能性のある攻撃の原因を特定することに関心があります

新しいターボファンは、関数のサイズを決定するために文字をカウントしないためです。代わりに、抽象構文木(AST)ノードをカウントするため、効果的には 実際の機能説明 。 Node 8.3+を使用すると、コメントと空白を好きなだけ追加できます。

Array-引数の定義

の通常の機能 JavaScript 暗黙のArrayのようなargumentを運ぶオブジェクト。

Arrayのような意味は何ですか?

argumentsオブジェクトの行為 幾分 配列のように。 lengthがありますプロパティですが、ArrayのようなforEachの組み込みメソッドがありませんおよびmap。

argumentsの方法は次のとおりですオブジェクトは機能します:

function foo() { console.log(arguments[0]); // Expected output: a console.log(arguments[1]); // Expected output: b console.log(arguments[2]); // Expected output: c } foo('a', 'b', 'c');

では、どうすればargumentsを変換できますか配列へのオブジェクト?簡潔なArray.prototype.slice.call(arguments)を使用する。

function test() { const r = Array.prototype.slice.call(arguments); console.log(r.map(num => num * 2)); } test(1, 2, 3); // Expected output: [2, 4, 6]

Array.prototype.slice.call(arguments)すべてのノードバージョンでパフォーマンスが低下します。したがって、forを介してキーをコピーしますループのパフォーマンスが向上します。

function test() { const r = []; for (index in arguments) { r.push(arguments[index]); } console.log(r.map(num => num * 2)); } test(1, 2, 3); // Expected output [2, 4, 6]

forループは少し面倒ですよね?スプレッド演算子を使用することもできますが、ノード8.2以下では低速です。

function test() { const r = [...arguments]; console.log(r.map(num => num * 2)); } test(1, 2, 3); // Expected output [2, 4, 6]

ノード8.3以降では状況が変わりました。これで、スプレッドはforループよりもはるかに高速に実行されます。

部分適用(カリー化)と製本

カリー化とは、複数の引数をとる関数を一連の関数に分解することであり、新しい関数はそれぞれ1つの引数のみを取ります。

単純なaddがあるとしましょう関数。この関数のカレーバージョンは、1つの引数num1を取ります。別の引数を取る関数を返しますnum2そしてnum1の合計を返しますおよびnum2:

function add(num1, num2) { return num1 + num2; } add(4, 6); // returns 10 function curriedAdd(num1) { return function(num2) { return num1 + num2; }; } const add5 = curriedAdd(5); add5(3); // returns 8

bindメソッドは、簡潔な構文でカリー化された関数を返します。

function add(num1, num2) { return num1 + num2; } const add5 = add.bind(null, 5); add5(3); // returns 8

だからbind信じられないほどですが、古いバージョンのノードでは遅くなります。ノード8.3以降では、bindははるかに高速で、パフォーマンスへの影響を心配することなく使用できます。

実験

いくつかの実験 実施されました ノード6とノード8のパフォーマンスを高レベルで比較します。これらはノード8.0で実施されたため、V8リリース6のアップグレードによるノード8.3以降に固有の上記の改善は含まれていません。

ノード8のサーバーレンダリング時間はノード6より25%短縮されました。大規模なプロジェクトでは、サーバーインスタンスの数を100から75に減らすことができました。これは驚くべきことです。ノード8で一連の500テストをテストすると、10%高速になりました。 Webpackのビルドは7%高速でした。一般に、結果はノード8で顕著なパフォーマンスの向上を示しました。

ノード8の機能

Node 8の改善点は速度だけではありませんでした。また、いくつかの便利な新機能ももたらされました。おそらく 最も重要なこと 、 非同期/待機 。

ノード8での非同期/待機

コールバックとPromiseは通常、JavaScriptで非同期コードを処理するために使用されます。コールバックは、保守不可能なコードを生成することで有名です。彼らは騒乱を引き起こしました(特に コールバック地獄 )JavaScriptコミュニティで。 Promisesは長い間コールバック地獄から私たちを救いましたが、それでも同期コードのクリーンさには欠けていました。 Async / awaitは、次のことを可能にする最新のアプローチです。 同期コードのように見える非同期コードを書く 。

また、以前のNodeバージョンではasync / awaitを使用できましたが、外部ライブラリとツールが必要でした。たとえば、Babelによる追加の前処理が必要でした。今では、箱から出してネイティブに利用できます。

async / awaitが従来のpromiseよりも優れているいくつかのケースについて説明します。

条件付き

データをフェッチしていて、新しいAPI呼び出しが必要かどうかを判断するとします。 ペイロードに基づく 。以下のコードを見て、これが「従来の約束」アプローチを介してどのように行われるかを確認してください。

const request = () => { return getData().then(data => { if (!data.car) { return fetchForCar(data.id).then(carData => { console.log(carData); return carData; }); } else { console.log(data); return data; } }); };

ご覧のとおり、上記のコードは、条件が1つ追加されているだけで、すでに乱雑に見えます。非同期/待機には、ネストが少なくなります。

const request = async () => { const data = await getData(); if (!data.car) { const carData = await fetchForCar(data); console.log(carData); return carData; } else { console.log(data); return data; } };

エラー処理

Async / awaitは、try / catchで同期エラーと非同期エラーの両方を処理するためのアクセスを許可します。非同期API呼び出しからのJSONを解析するとします。 1回のtry / catchで、解析エラーとAPIエラーの両方を処理できます。

const request = async () => { try { console.log(await getData()); } catch (err) { console.log(err); } };

中間値

約束が別の約束から解決されるべき議論を必要とする場合はどうなりますか?これは、非同期呼び出しを連続して実行する必要があることを意味します。

従来のpromiseを使用すると、次のようなコードになる可能性があります。

const request = () => { return fetchUserData() .then(userData => { return fetchCompanyData(userData); }) .then(companyData => { return fetchRetiringPlan(userData, companyData); }) .then(retiringPlan => { const retiringPlan = retiringPlan; }); };

連鎖非同期呼び出しが必要なこの場合、Async / awaitが光ります。

const request = async () => { const userData = await fetchUserData(); const companyData = await fetchCompanyData(userData); const retiringPlan = await fetchRetiringPlan(userData, companyData); };

並列同期

複数の非同期関数を並行して呼び出したい場合はどうなりますか?以下のコードでは、fetchHouseDataを待ちます解決するには、fetchCarDataを呼び出します。これらはそれぞれ独立していますが、順番に処理されます。両方のAPIが解決するまで2秒待ちます。これは良くない。

function fetchHouseData() { return new Promise(resolve => setTimeout(() => resolve('Mansion'), 1000)); } function fetchCarData() { return new Promise(resolve => setTimeout(() => resolve('Ferrari'), 1000)); } async function action() { const house = await fetchHouseData(); // Wait one second const car = await fetchCarData(); // ...then wait another second. console.log(house, car, ' in series'); } action();

より良いアプローチは、非同期呼び出しを並行して処理することです。以下のコードをチェックして、これがasync / awaitでどのように達成されるかを理解してください。

async function parallel() { houseDataPromise = fetchHouseData(); carDataPromise = fetchCarData(); const house = await houseDataPromise; // Wait one second for both const car = await carDataPromise; console.log(house, car, ' in parallel'); } parallel();

これらの呼び出しを並行して処理すると、両方の呼び出しを1秒だけ待つ必要があります。

完了は機能ではありません

新しいコアライブラリ関数

ノード8は、いくつかの新しいコア機能ももたらします。

ファイルのコピー

ノード8の前は、ファイルをコピーするために、2つのストリームを作成し、一方から他方にデータをパイプしていました。以下のコードは、読み取りストリームがデータを書き込みストリームにパイプする方法を示しています。ご覧のとおり、ファイルのコピーなどの単純なアクションではコードが乱雑になっています。

const fs = require('fs'); const rd = fs.createReadStream('sourceFile.txt'); rd.on('error', err => { console.log(err); }); const wr = fs.createWriteStream('target.txt'); wr.on('error', err => { console.log(err); }); wr.on('close', function(ex) { console.log('File Copied'); }); rd.pipe(wr);

ノード8ではfs.copyFileおよびfs.copyFileSyncはるかに少ない手間でファイルをコピーするための新しいアプローチです。

const fs = require('fs'); fs.copyFile('firstFile.txt', 'secondFile.txt', err => { if (err) { console.log(err); } else { console.log('File copied'); } });

PromisifyとCallbackify

util.promisify通常の関数を非同期関数に変換します。入力された関数は、一般的なNode.jsコールバックスタイルに従う必要があることに注意してください。最後の引数としてコールバックを取る必要があります。つまり、(error, payload) => { ... }です。

const { promisify } = require('util'); const fs = require('fs'); const readFilePromisified = promisify(fs.readFile); const file_path = process.argv[2]; readFilePromisified(file_path) .then((text) => console.log(text)) .catch((err) => console.log(err));

ご覧のとおり、util.promisify変換しましたfs.readFile非同期関数に。

一方、Node.jsにはutil.callbackifyが付属しています。 util.callbackify util.promisifyの反対です:非同期関数をNode.jsコールバックスタイル関数に変換します。

destroy読み取り可能および書き込み可能の関数

destroyノード8の関数は、読み取り可能または書き込み可能なストリームを破棄/クローズ/中止するための文書化された方法です。

const fs = require('fs'); const file = fs.createWriteStream('./big.txt'); file.on('error', errors => { console.log(errors); }); file.write(`New text. `); file.destroy(['First Error', 'Second Error']);

上記のコードにより、big.txtという名前の新しいファイルが作成されます。 (まだ存在しない場合)テキストNew text.。

Readable.destroyおよびWriteable.destroyノード8の関数はcloseを発行しますイベントと オプション errorイベント— destroy必ずしも何かがうまくいかなかったという意味ではありません。

スプレッド演算子

スプレッド演算子(別名...)はノード6で機能しましたが、配列やその他の反復可能オブジェクトでのみ機能しました。

const arr1 = [1,2,3,4,5,6] const arr2 = [...arr1, 9] console.log(arr2) // expected output: [1,2,3,4,5,6,9]

ノード8では、オブジェクトはスプレッド演算子を使用することもできます。

SpringBootグローバル例外ハンドラ
const userCarData = { type: 'ferrari', color: 'red' }; const userSettingsData = { lastLoggedIn: '12/03/2019', featuresPlan: 'premium' }; const userData = { ...userCarData, name: 'Youssef', ...userSettingsData }; console.log(userData); /* Expected output: { type: 'ferrari', color: 'red', name: 'Youssef', lastLoggedIn: '12/03/2019', featuresPlan: 'premium' } */

ノード8LTSの実験的機能

実験的な機能は安定しておらず、非推奨になる可能性があり、時間とともに更新される可能性があります。でこれらの機能を使用しないでください 製造 それらが安定するまで。

非同期フック

非同期フックは、APIを介してノード内で作成された非同期リソースの存続期間を追跡します。

非同期フックを使用する前に、イベントループを理解していることを確認してください。 この動画 役立つかもしれません。非同期フックは、非同期関数のデバッグに役立ちます。それらにはいくつかのアプリケーションがあります。それらの1つは、非同期関数のエラースタックトレースです。

以下のコードをご覧ください。 console.logに注意してください非同期関数です。したがって、非同期フック内では使用できません。 fs.writeSync代わりに使用されます。

const asyncHooks = require('async_hooks'); const fs = require('fs'); const init = (asyncId, type, triggerId) => fs.writeSync(1, `${type} `); const asyncHook = asyncHooks.createHook({ init }); asyncHook.enable();

見る この動画 非同期フックについてもっと知るために。特にNode.jsガイドに関しては、 この記事 例示的なアプリケーションを介して非同期フックをわかりやすく説明するのに役立ちます。

ノード8のES6モジュール

ノード8はES6モジュールをサポートするようになり、次の構文を使用できるようになりました。

import { UtilityService } from './utility_service';

ノード8でES6モジュールを使用するには、以下を実行する必要があります。

  1. --experimental-modulesを追加しますコマンドラインへのフラグ
  2. ファイル拡張子の名前を.jsから変更します〜.mjs

HTTP / 2

HTTP / 2は、頻繁に更新されないHTTPプロトコルの最新の更新であり、ノード8.4以降 ネイティブにサポート 実験モードで。その前身であるHTTP / 1.1よりも高速で、安全で、効率的です。そして Googleはそれを使用することをお勧めします 。しかし、それは他に何をしますか?

多重化

HTTP / 1.1では、サーバーは接続ごとに一度に1つの応答しか送信できませんでした。 HTTP / 2では、サーバーは複数の応答を並行して送信できます。

サーバープッシュ

サーバーは、単一のクライアント要求に対して複数の応答をプッシュできます。なぜこれが有益なのですか?例としてWebアプリケーションを取り上げます。従来、

  1. クライアントはHTMLドキュメントを要求します。
  2. クライアントは、HTMLドキュメントから必要なリソースを検出します。
  3. クライアントは、必要なリソースごとにHTTP要求を送信します。たとえば、クライアントは、ドキュメントに記載されているJSおよびCSSリソースごとにHTTPリクエストを送信します。

サーバープッシュ機能は、サーバーがこれらすべてのリソースをすでに認識しているという事実を利用します。サーバーはそれらのリソースをクライアントにプッシュします。したがって、Webアプリケーションの例では、クライアントが最初のドキュメントを要求した後、サーバーはすべてのリソースをプッシュします。これにより、待ち時間が短縮されます。

優先順位付け

クライアントは、優先順位付けスキームを設定して、必要な各応答の重要性を判断できます。サーバーは、このスキームを使用して、メモリ、CPU、帯域幅、およびその他のリソースの割り当てに優先順位を付けることができます。

古い悪い習慣を取り除く

HTTP / 1.1では多重化が許可されていなかったため、低速とファイルの読み込みをカバーするために、いくつかの最適化と回避策が使用されています。残念ながら、これらの手法はRAM消費量の増加とレンダリングの遅延を引き起こします。

  • ドメインシャーディング:接続が分散され、並行して処理されるように、複数のサブドメインが使用されました。
  • CSSファイルとJavaScriptファイルを組み合わせてリクエスト数を減らします。
  • スプライトマップ: 画像ファイルを組み合わせる HTTPリクエストを減らすため。
  • インライン化:CSSとJavaScriptは、接続の数を減らすためにHTMLに直接配置されます。

HTTP / 2を使用すると、これらの手法を忘れて、コードに集中できます。

しかし、HTTP / 2をどのように使用しますか?

ほとんどのブラウザは、セキュリティで保護されたSSL接続を介してのみHTTP / 2をサポートします。 この記事 自己署名証明書の構成に役立ちます。生成された.crtを追加しますファイルと.key sslというディレクトリにあるファイル。次に、以下のコードをserver.jsという名前のファイルに追加します。

nodejsは何をしますか

--expose-http2を使用することを忘れないでくださいこの機能を有効にするには、コマンドラインでフラグを立てます。つまりこの例の実行コマンドはnode server.js --expose-http2です。

const http2 = require('http2'); const path = require('path'); const fs = require('fs'); const PORT = 3000; const secureServerOptions = { cert: fs.readFileSync(path.join(__dirname, './ssl/server.crt')), key: fs.readFileSync(path.join(__dirname, './ssl/server.key')) }; const server = http2.createSecureServer(secureServerOptions, (req, res) => { res.statusCode = 200; res.end('Hello from ApeeScape'); }); server.listen( PORT, err => err ? console.error(err) : console.log(`Server listening to port ${PORT}`) );

もちろん、ノード8、ノード9、ノード10などは、古いHTTP1.1を引き続きサポートします。Node.jsの公式ドキュメントは 標準のHTTPトランザクション 長い間古くなることはありません。しかし、HTTP / 2を使用したい場合は、 このNode.jsガイド 。

だから、私は最後にNode.js 8を使うべきですか?

ノード8には、パフォーマンスが向上し、async / await、HTTP / 2などの新機能が追加されました。エンドツーエンドの実験では、ノード8はノード6よりも約25%高速であることが示されています。 大幅なコスト削減 。したがって、グリーンフィールドプロジェクトの場合は、絶対に!しかし、既存のプロジェクトの場合、 ノードの更新 ?

これは、既存のコードの多くを変更する必要があるかどうかによって異なります。 このドキュメント ノード6から来ている場合は、ノード8の重大な変更をすべて一覧表示します。プロジェクトのすべてのnpmを再インストールして、一般的な問題を回避することを忘れないでください。最新のNode8バージョンを使用するパッケージ。また、開発マシンでは、本番サーバーと同じNode.jsバージョンを常に使用してください。頑張ってください!

関連:
  • なぜ地獄はNode.jsを使用するのでしょうか?ケースバイケースのチュートリアル
  • Node.jsアプリケーションでのメモリリークのデバッグ
  • Node.jsでの安全なRESTAPIの作成
  • キャビンフィーバーコーディング:Node.jsバックエンドチュートリアル

基本を理解する

Node.jsとは何ですか?

Node.jsは、Windows、Linux、Mac OS Xなどのさまざまなプラットフォームで実行されるオープンソースのJavaScriptランタイムです。Node.jsは、ChromeのV8JavaScriptエンジン上に構築されています。

Node.jsは何に使用されますか?

Node.jsは、サーバー上でJavaScriptを実行するために使用されます。他のランタイムや言語と同様に、Node.jsはサーバー上のファイルの処理、データベースとの通信、動的ページコンテンツの生成、RESTfulAPIサービスの構築などを行うことができます。

Node.jsを使用する理由

Node.jsは、リアルタイムの双方向通信の処理に優れており、すぐに使用できる非同期コードを実行します。これは、拡張性が高く、パフォーマンスの高いアプリケーションの作成に役立ちます。また、JavaScriptをすでに知っているフロントエンド開発者は、別の言語を学ぶ必要はありません。

LTSは何の略ですか?

LTSは「長期サポート」の略です。この場合、Node.js 8はLTSフェーズにあり、最も安定したバージョンの選択肢の1つであることを意味します。

Power Pivot for Excelチュートリアル:主な使用例と例

財務プロセス

Power Pivot for Excelチュートリアル:主な使用例と例
フリーランスのデザイナーとしてのリモートワーク

フリーランスのデザイナーとしてのリモートワーク

デザイナーライフ

人気の投稿
同じマシンでのMySQLマスタースレーブレプリケーション
同じマシンでのMySQLマスタースレーブレプリケーション
TypeScript、依存性注入、Discordボットの操作
TypeScript、依存性注入、Discordボットの操作
3つの医療技術革新:より良い結果とより低いコストの推進
3つの医療技術革新:より良い結果とより低いコストの推進
Calabashを使用したAndroidおよびiOSUIテスト
Calabashを使用したAndroidおよびiOSUIテスト
Node.js / TypeScript REST APIの構築、パート2:モデル、ミドルウェア、およびサービス
Node.js / TypeScript REST APIの構築、パート2:モデル、ミドルウェア、およびサービス
 
最高のデータ視覚化ツールの完全な概要
最高のデータ視覚化ツールの完全な概要
機械学習理論とその応用の紹介:例を含むビジュアルチュートリアル
機械学習理論とその応用の紹介:例を含むビジュアルチュートリアル
AngularJS開発者が犯す最も一般的な18の間違い
AngularJS開発者が犯す最も一般的な18の間違い
GoogleスプレッドシートとAppsScriptの操作
GoogleスプレッドシートとAppsScriptの操作
自然言語処理アプリを構築する方法
自然言語処理アプリを構築する方法
人気の投稿
  • 例のある初心者向けangularjsチュートリアル
  • すべてのデバイスのメディアクエリ
  • プロトタイプの作成方法
  • 最高のC ++プログラム
  • ipoを評価する方法
カテゴリー
アジャイルタレント 製品ライフサイクル エンジニアリング管理 データサイエンスとデータベース 財務プロセス 人とチーム Uxデザイン モバイル プロセスとツール 革新

© 2021 | 全著作権所有

apeescape2.com