ノード8が出ました!実際、ノード8は、実際の使用法を確認するのに十分な時間使用されています。高速な新しいV8エンジンと、async / await、HTTP / 2、asyncフックなどの新機能が付属しています。しかし、それはあなたのプロジェクトの準備ができていますか?確認してみましょう!
編集者注: あなたはおそらくノード10(コードネーム ドブニウム )も出ています。ノード8に焦点を当てることを選択しています( 炭素 )2つの理由:(1)ノード10はちょうどロングタームサポート(LTS)フェーズに入ったばかりであり、(2)ノード8はノード10よりも重要な反復をマークしました。
まず、この注目に値するリリースのパフォーマンスの向上と新機能を見ていきます。改善点の1つは、NodeのJavaScriptエンジンです。
正確には です とにかく、JavaScriptエンジン?
JavaScriptエンジンがコードを実行し、最適化します。これは、JavaScriptをバイトコードにコンパイルする標準のインタープリターまたはジャストインタイム(JIT)コンパイラーである可能性があります。 Node.jsで使用されるJSエンジンは、すべてJITコンパイラーであり、インタープリターではありません。
Node.js Googleを使用しました Chrome V8JavaScriptエンジン 、または単に V8 、最初から。一部のノードリリースは、新しいバージョンのV8と同期するために使用されます。ただし、ここではV8バージョンを比較するため、V8とノード8を混同しないように注意してください。
ソフトウェアのコンテキストでは、スラングとして「v8」を使用したり、「バージョン8」の正式な短縮形を使用したりすることが多いため、これは簡単に失敗します。そのため、「NodeV8」または「Node.jsV8」を「NodeJS8」と混同する場合があります。 」ですが、この記事では、物事を明確にするためにこれを避けています。 V8は、ノードのバージョンではなく、常にエンジンを意味します。
契約vsフルタイム給与計算機
ノード6は、JavaScriptエンジンとしてV8リリース5を使用します。 (ノード8の最初のいくつかのポイントリリースもV8リリース5を使用しますが、ノード6よりも新しいV8ポイントリリースを使用します。)
V8リリース5以前には、2つのコンパイラがあります。
深く掘り下げてみると、V8は複数のタイプのスレッドを使用しています。
まず、Full-codegenコンパイラがJavaScriptコードを実行します。コードの実行中に、プロファイラースレッドはデータを収集して、エンジンが最適化するメソッドを決定します。別のスレッドでは、クランクシャフトがこれらのメソッドを最適化します。
上記のアプローチには2つの主な問題があります。まず、それはアーキテクチャ的に複雑です。第二に、コンパイルされたマシンコードははるかに多くのメモリを消費します。消費されるメモリの量は、コードが実行される回数とは無関係です。一度だけ実行されるコードでさえ、かなりの量のメモリを消費します。
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で顕著なパフォーマンスの向上を示しました。
Node 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'); } });
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' } */
実験的な機能は安定しておらず、非推奨になる可能性があり、時間とともに更新される可能性があります。でこれらの機能を使用しないでください 製造 それらが安定するまで。
非同期フックは、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モジュールをサポートするようになり、次の構文を使用できるようになりました。
import { UtilityService } from './utility_service';
ノード8でES6モジュールを使用するには、以下を実行する必要があります。
--experimental-modules
を追加しますコマンドラインへのフラグ.js
から変更します〜.mjs
HTTP / 2は、頻繁に更新されないHTTPプロトコルの最新の更新であり、ノード8.4以降 ネイティブにサポート 実験モードで。その前身であるHTTP / 1.1よりも高速で、安全で、効率的です。そして Googleはそれを使用することをお勧めします 。しかし、それは他に何をしますか?
HTTP / 1.1では、サーバーは接続ごとに一度に1つの応答しか送信できませんでした。 HTTP / 2では、サーバーは複数の応答を並行して送信できます。
サーバーは、単一のクライアント要求に対して複数の応答をプッシュできます。なぜこれが有益なのですか?例としてWebアプリケーションを取り上げます。従来、
サーバープッシュ機能は、サーバーがこれらすべてのリソースをすでに認識しているという事実を利用します。サーバーはそれらのリソースをクライアントにプッシュします。したがって、Webアプリケーションの例では、クライアントが最初のドキュメントを要求した後、サーバーはすべてのリソースをプッシュします。これにより、待ち時間が短縮されます。
クライアントは、優先順位付けスキームを設定して、必要な各応答の重要性を判断できます。サーバーは、このスキームを使用して、メモリ、CPU、帯域幅、およびその他のリソースの割り当てに優先順位を付けることができます。
HTTP / 1.1では多重化が許可されていなかったため、低速とファイルの読み込みをカバーするために、いくつかの最適化と回避策が使用されています。残念ながら、これらの手法はRAM消費量の増加とレンダリングの遅延を引き起こします。
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ガイド 。
ノード8には、パフォーマンスが向上し、async / await、HTTP / 2などの新機能が追加されました。エンドツーエンドの実験では、ノード8はノード6よりも約25%高速であることが示されています。 大幅なコスト削減 。したがって、グリーンフィールドプロジェクトの場合は、絶対に!しかし、既存のプロジェクトの場合、 ノードの更新 ?
これは、既存のコードの多くを変更する必要があるかどうかによって異なります。 このドキュメント ノード6から来ている場合は、ノード8の重大な変更をすべて一覧表示します。プロジェクトのすべてのnpm
を再インストールして、一般的な問題を回避することを忘れないでください。最新のNode8バージョンを使用するパッケージ。また、開発マシンでは、本番サーバーと同じNode.jsバージョンを常に使用してください。頑張ってください!
Node.jsは、Windows、Linux、Mac OS Xなどのさまざまなプラットフォームで実行されるオープンソースのJavaScriptランタイムです。Node.jsは、ChromeのV8JavaScriptエンジン上に構築されています。
Node.jsは、サーバー上でJavaScriptを実行するために使用されます。他のランタイムや言語と同様に、Node.jsはサーバー上のファイルの処理、データベースとの通信、動的ページコンテンツの生成、RESTfulAPIサービスの構築などを行うことができます。
Node.jsは、リアルタイムの双方向通信の処理に優れており、すぐに使用できる非同期コードを実行します。これは、拡張性が高く、パフォーマンスの高いアプリケーションの作成に役立ちます。また、JavaScriptをすでに知っているフロントエンド開発者は、別の言語を学ぶ必要はありません。
LTSは「長期サポート」の略です。この場合、Node.js 8はLTSフェーズにあり、最も安定したバージョンの選択肢の1つであることを意味します。