Node.js v10の変更点まとめ

2018 / 04 / 20

Edit
🚨 This article hasn't been updated in over a year
💁‍♀️ This post was copied from 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 ...

注目すべき変更


用語

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 Gi...

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 が入りました。