Hiroppy
Node.js v10の変更点まとめ

Node.js v10の変更点まとめ

2018 / 04 / 20
Hiroppy

Hiroppy

JavaScript Engineer


目次

この記事は Hatena Blog からの移行記事です

リリース日は 4/24(UTC)の予定です。 この記事では、バックポート含め v9 から入ったものを上げていこうかなと思います。 なので、Node10 の CHANGELOG からの拡張だと考えてください。

10.0.0 Proposal by jasnell · Pull Request #19091 · nodejs/node

This is nearly ready: 1st RC Build will be cut afternoon (pacific time) of April 19th 2nd RC Build (if there are any updates landed) will be cut afternoon of April 23rd Release will be afternoon o...

github.com
10.0.0 Proposal by jasnell · Pull Request #19091 · nodejs/node

注目すべき変更


用語

LTS (Long Term Support)

GitHub - nodejs/Release: Node.js Release Working Group

Node.js Release Working Group. Contribute to nodejs/Release development by creating an account on GitHub.

github.com
GitHub - nodejs/Release: Node.js Release Working Group

4 月にリリースされる偶数バージョンが対象であり、毎年 10 月から開始されます。 LTS には active/maintenance の二種類があり、 active は 18 ヶ月間サポートされ、その後 12 ヶ月間はメンテナンスになります。 LTS とメンテナンスの違いは、修正度のプライオリティに依存します。 バグ修正、セキュリティアップデート、関連されたドキュメント修正、破壊的変更がないパフォーマンス修正、etc…

今後のスケジュールは以下のとおりです。

v10(N/A)は 2018/10 に LTS が開始される予定です。 v8(Carbon)は引き続き active の LTS 対象です。 v6(Boron)は 2018/4/30 から maintenance の LTS 対象です。 v4(Argon)は 2018/4/30 に LTS が終了されます。

なので、6 以上(できれば 8 か 10)を使うことをオススメします。

Stablilty

API の安定指標のことを指します。

  • 0: 非推奨
  • 1: 実験
  • 2: 安定

v10 時点での、Stability:1 は以下のとおりです。

  • vm.Module
  • readable[@@asyncIterator] (Readable Streams)
  • HTTP2
  • ECMAScript Modules
  • Inspector
  • fs Promises API
  • Serialization API(V8)
  • Async Hooks
  • perf_hooks
  • Errors の一部

変更点

各 deps バージョン

  • ICU: 61.1
  • nghttp2: 1.29.0
  • node-inspect: 1.11.3
  • npm: 5.6.0
  • libuv: 1.20.0
  • OpenSSL: 1.1.0h
  • v8: 6.6.346.24-node.5

Assert

strict の追加 (v9.9.0)

[https://github.com/nodejs/node/pull/17615:title]

assert以下にstrictが追加されました。 これは、オブジェクト等の比較に有効で、差分を表示することができます。

> assert.strict.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]);
AssertionError [ERR_ASSERTION]: Input A expected to strictly deep-equal input B:
+ expected - actual ... Lines skipped

  [
    [
...
        2,
-       3
+       '3'
      ]
...
    5
  ]

rejects と doesNotReject の追加 (N/A)

[https://github.com/nodejs/node/pull/18023/:title]

assert.throws()の promise 版がassert.rejects()となります。 assert.doesNotThrow()の promise 版がassert.doesNotReject()となります。

(async () => {
  await assert.rejects(async () => {
    throw new Error("Wrong value");
  }, Error);
})();

assert.throws の error パラメーターに object が追加 (v9.9.0)

[https://github.com/nodejs/node/pull/17584:title]

今までは、RegExp か Function でしたが、object が追加されました。

const assert = require("assert");

assert.throws(
  () => {
    const err = new TypeError("Wrong value");
    err.code = 404;
    throw err;
  },
  {
    name: "TypeError",
    message: "Wrong value",
  },
);

Buffer

node_modules 外に対しての new Buffer()の非推奨警告の出力 (N/A)

[https://github.com/nodejs/node/pull/19524:title]

Buffer(new Buffer)は非推奨ですので、Buffer.alloc()Buffer.allocUnsafe()Buffer.from()を使ってください。

> Buffer(10)
<Buffer 00 00 00 00 00 00 00 00 00 00>
> (node:23527) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use theBuffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.

Console

console.table のサポート (N/A)

[https://github.com/nodejs/node/pull/18137:title]

console.tableが追加されました。

> console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]);
┌─────────┬──────────────────┐
│ (index) │      Values
├─────────┼──────────────────┤
0{ a: 1, b: 'Y' }
1{ a: 'Z', b: 2 }
└─────────┴──────────────────┘

> console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']);
┌─────────┬─────┐
│ (index) │  a
├─────────┼─────┤
01
1'Z'
└─────────┴─────┘

色がサポートされました (N/A)

[https://github.com/nodejs/node/pull/19372/:title]

colorModeが追加されました。デフォルトは auto です。 また、内部ではutil.formatWithOptionsが追加され、それをラップします。

> console.log('%o with object format param', { foo: 'bar' });
{ foo: 'bar' } with object format param // barだけ緑色になる

CLI

NODE_OPTIONS に—stack-trace-limit のオプションが追加 (v9.1.0)

backport: 6, 8

[https://github.com/nodejs/node/pull/16495]

V8 のオプションである--stack-trace-limitが有効可されました。 スタックトレースの上限数を設定します。

NODE_OPTIONS=--stack-trace-limit=100 node index.js

—trace-event-file-pattern のオプションが追加 (v9.8.0)

[https://github.com/nodejs/node/pull/18480:title]

トレースのログファイルは標準的にはnode_trace.${rotation}.logとなり、rotation が加算されていくログローテーションがされています。

--trace-event-file-patternでは、pidrotationをサポートします。

node --trace-events-enabled --trace-event-file-pattern '${pid}-${rotation}.log' server.js

Cluster

cluster.settings に cwd が追加 (v9.5.0)

[https://github.com/nodejs/node/pull/18399:title]

ワーカープロセスの現在の作業ディレクトリを返します。

EventEmitter

removeListener のエイリアスとして off が追加 (N/A)

[https://github.com/nodejs/node/pull/17156:title]

EventEmitter.prototype.offEventEmitter.prototype.removeListenerとなります。

Errors

[https://github.com/nodejs/node/issues/11273:title]

エラーコードをすべて、internal/errors.jsへ移行しました。 文言の修正等が行われたため、エラーコードを利用しているライブラリ群には影響が出る可能性があります。

詳細なドキュメントはこちら。 [https://nodejs.org/api/errors.html:title]

FS

Promises の API が追加 (N/A)

他の semver-minor と違う扱いなので、v9 には入りません。

[https://github.com/nodejs/node/pull/18297:title]

Node には同期、コールバックはありましたが、今まで非同期はありませんでした。

const fs = require("fs/promises");

(async () => {
  const n = await fs.readFile("./node");

  console.log(n);
})();

HTTP

カスタムレスポンスとカスタムリクエストのオプションを追加 (v9.6.0)

[https://github.com/nodejs/node/pull/15752:title]

createServerの第一引数に options として追加されました。 IncomingMessageServerResponseが設定できます。

class MyIncomingMessage extends http.IncomingMessage {
  getUserAgent() {
    return this.headers["user-agent"] || "unknown";
  }
}

const server = http.createServer(
  {
    IncomingMessage: MyIncomingMessage,
  },
  (req, res) => {
    res.statusCode = 200;
    res.end();
  },
);

server.listen();

RFC に従い 100, 102 - 199 の処理が変更 (N/A)

[https://github.com/nodejs/node/pull/18033:title]

  • 100 (Continue)
    • RFC7231 Section 6.2.1
  • 102 (Processing)
    • RFC2518
  • 103 (Early Hints)
    • RFC8297
  • 104-199 (Unassigned)

URL のパスに 2 バイトの文字が禁止 (N/A)

[https://github.com/nodejs/node/pull/16237:title]

> http.request({path: '/thisisinvalid\uffe2'}).end();
TypeError [ERR_UNESCAPED_CHARACTERS]: Request path contains unescaped characters
    at new ClientRequest (_http_client.js:105:13)
    at Object.request (http.js:41:10)

Module

Stability: 1

ECMAScript Modules が Node.js にも実験的に入りました。 以下の記事を参考にしてください。 [http://blog.hiroppy.me/entry/nodejs-esm:embed:cite]

N-API

安定的になった (N/A)

[https://github.com/nodejs/node/pull/19262:title]

Stability が 1 から 2 となり、安定した API になりました。

process.versions に n-api のバージョンが追加 (v9.5.0)

backport: 6, 8

[https://github.com/nodejs/node/pull/18067:title]

> process.versions
{ http_parser: '2.8.0',
  node: '10.0.0-pre',
  v8: '6.6.346.24-node.3',
  uv: '1.20.0',
  zlib: '1.2.11',
  ares: '1.14.0',
  modules: '63',
  nghttp2: '1.29.0',
  napi: '3',
  openssl: '1.1.0h',
  icu: '61.1',
  unicode: '10.0',
  cldr: '33.0',
  tz: '2018c' }

Net

net.Socket.prototype.listen が削除 (v9.4.0)

[https://github.com/nodejs/node/pull/13735:title]

ドキュメント化されておらず、消しても問題ないため消されます。

ready のイベントが追加 (v9.11.0)

[https://github.com/nodejs/node/pull/19408:title]

fs と同様です。

const server = net
  .createServer((conn) => {
    conn.end();
    server.close();
  })
  .listen(0, () => {
    const client = new net.Socket();

    client.on("ready", () => {
      client.end();
    });

    client.connect(server.address());
  });

end 後に close が発行される (N/A)

[https://github.com/nodejs/node/pull/19241:title]

endが emit された後に、closeが発行されるように変わりました。

server.on("connection", (socket) => {
  let endEmitted = false;

  socket.once("readable", () => {
    setTimeout(() => {
      socket.read();
    }, 100);
  });
  socket.on("end", () => {
    endEmitted = true;
  });
  socket.on("close", () => {
    assert(endEmitted);
    server.close();
  });
  socket.end("foo");
});

Perf_Hooks

Stability: 1

パフォーマンス周りの API です。 もともと、processに追加していたのですが、perf_hooksというモジュールに切り出されました。 以下の記事を参考にしてください。

[http://blog.hiroppy.me/entry/performance-timing-api-with-node.js:embed:cite]

Process

process.ppid の追加(v9.6.0)

backport: 6, 8

[https://github.com/nodejs/node/pull/16839:title]

現在の親プロセスの PID を返します。

> process.ppid
73124

シグナル番号によりプロセスを殺すことが可能 (v9.6.0)

[https://github.com/nodejs/node/pull/16944:title]

> process.kill(0, 985)
Error: kill EINVAL
    at process.kill (internal/process.js:190:13)
> process.kill(0, 15, 0, 15);
[1]    39152 terminated  ./node

ready のイベントが追加 (v9.11.0)

[https://github.com/nodejs/node/pull/19408:title]

ファイルディスクリプタが使用可能になると、発火されます。

const readStream = fs.createReadStream("foo.txt");
readStream.on("ready", () => {});

const writeStream = fs.createWriteStream("foo.txt", { autoClose: true });
writeStream.on("ready", () => {});

Streams

writableLength と readableLength の追加 (v9.4.0)

[https://github.com/nodejs/node/pull/12857:title]

res._readableState.lengthからres.readableLengthへのアクセスに変わります。

nextTick で常に readable となる (N/A)

[https://github.com/nodejs/node/pull/17979:title]

一回だけ、readable._read()を呼び出します。

readable に for-await のサポート (N/A)

Stability:1

[https://github.com/nodejs/node/pull/17755:title]

async/await がサポートされました。

const fs = require("fs");

async function print(readable) {
  readable.setEncoding("utf8");
  let data = "";
  for await (const k of readable) {
    data += k;
  }
  console.log(data);
}

print(fs.createReadStream("file")).catch(console.log);

Timers

immediate.ref と immediate.unref の追加 (v9.7.0)

[https://github.com/nodejs/node/pull/18139:title]

setImmediateは普通、スケジューリングされるとイベントループがアクティブである限り続行されます。 この動作を操作するために追加されました。

> setImmediate(() => {}).ref()
....
> setImmediate(() => {}).unref()
Immediate {
  _idleNext: null,
  _idlePrev: null,
  _onImmediate: [Function],
  _argv: undefined,
  _destroyed: false,
  domain:
   Domain {
     domain: null,
     _events:
      { removeListener: [Function: updateExceptionCapture],
        newListener: [Function: updateExceptionCapture],
        error: [Function: debugDomainError] },
     _eventsCount: 3,
     _maxListeners: undefined,
     members: [] },
  [Symbol(refed)]: false,
  [Symbol(asyncId)]: 665,
  [Symbol(triggerId)]: 6 }

URL

WHATWG URL がグローバルへ (N/A)

[https://github.com/nodejs/node/pull/18281:title]

今までは、require(url).URLでしたが、ブラウザ同様にグローバルに置かれます。 後方互換のために、urlにも置かれていますが、今後はグローバルのを使うほうが良いでしょう。

> URL
[Function: URL]
> URLSearchParams
[Function: URLSearchParams]
> url.URL
[Function: URL]
> url.URLSearchParams
[Function: URLSearchParams]

Util

NODE_DEBUG にワイルドカードが使用可能 (v9.4.0)

[https://github.com/nodejs/node/pull/17609:title]

登録されたデバッグログ名の実行を出力させるのに、ワイルドカードが使えるようになりました。

const util = require("util");
const debuglog = util.debuglog("foo-bar");

debuglog("hi there, it's foo-bar [%d]", 2333);
$ NODE_DEBUG=foo* node index.js
FOO-BAR 42404: hi there, it's foo-bar [2333]
$ NODE_DEBUG=*oo* node index.js
FOO-BAR 42404: hi there, it's foo-bar [2333]

util.inspect に compact オプションが追加 (v9.9.0)

[https://github.com/nodejs/node/pull/17576:title]

falseにすることにより、標準のインデントが変更されます。 複数行に並べず、オブジェクトごとに改行するプロパティを一行にまとめます。

デフォルトはtrueとなります。

const o = {};

o.a = () => {};
o.b = new Number(3);
console.log(util.inspect(o, { compact: true, breakLength: 3 }));
/*
{ a: [Function],
  b: [Number: 3] }
*/

console.log(util.inspect(o, { compact: false, breakLength: 3 }));
/*
{
  a: [Function],
  b: [Number: 3]
}
*/

const a = "12 45 78 01 34 67 90 23 56 89 1234567890123 0";

console.log(util.inspect(a, { compact: true, breakLength: 3 }));
/*
'12 45 78 01 34 67 90 23 56 89 1234567890123 0'
*/

console.log(util.inspect(a, { compact: false, breakLength: 3 }));
/*
'12 45 78 01 34 ' +
  '67 90 23 56 89 ' +
  '1234567890123 0'
*/

util.inspect が bigint の対応 (N/A)

[https://github.com/nodejs/node/pull/18412:title]

V8 側で bigint が対応されたので、Node 側でも対応されました。 --harmony-bigintが必要です。

> util.inspect(1n)
'1n'

util.types の追加 (N/A)

[https://github.com/nodejs/node/pull/18415:title]

util.typesという型チェックをするメソッドが追加されました。 追加されたメソッドは以下の通りです。

isExternal, isDate, isArgumentsObject, isBooleanObject, isNumberObject, isStringObject, isSymbolObject, isNativeError, isRegExp, isAsyncFunction, isGeneratorFunction, isGeneratorObject, isPromise, isMap, isSet, isMapIterator, isSetIterator, isWeakMap, isWeakSet, isArrayBuffer, isDataView, isSharedArrayBuffer, isProxy, isWebAssemblyCompiledModule, isModuleNamespaceObject, isAnyArrayBuffer, isArrayBufferView, isTypedArray, isUint8Array, isUint8ClampedArray, isUint16Array, isUint32Array, isInt8Array, isInt16Array, isInt32Array, isFloat32Array, isFloat64Array, isBigInt64Array, isBigUint64Array

> util.types.isPromise(new Promise(() => {}))
true
> util.types.isRegExp(/\*/)
true

ZLib

ArrayBuffer がサポート (v9.4.0)

[https://github.com/nodejs/node/pull/16042:title]

今までのサポートは Buffer、TypedArray、DataView でしたが、そこに ArrayBuffer が入りました。


関連記事