技術探し

JavaScriptを中心に記事を書いていきます :;(∩´﹏`∩);:

Node.js v10の変更点まとめ

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

github.com

注目すべき変更



目次

用語

LTS (Long Term Support)

github.com

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)

assert: add error diffs by BridgeAR · Pull Request #17615 · nodejs/node · GitHub

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)

assert: adds rejects() and doesNotReject() by feugy · Pull Request #18023 · nodejs/node · GitHub

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)

assert: .throws accept objects by BridgeAR · Pull Request #17584 · nodejs/node · GitHub

今までは、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)

buffer: do deprecation warning outside `node_modules` by addaleax · Pull Request #19524 · nodejs/node · GitHub

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)

console: add table method by devsnek · Pull Request #18137 · nodejs/node · GitHub

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  │
├─────────┼─────┤
│    0    │  1  │
│    1    │ 'Z' │
└─────────┴─────┘

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

console: add color support by addaleax · Pull Request #19372 · nodejs/node · GitHub

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)

trace_events: add file pattern cli option by AndreasMadsen · Pull Request #18480 · nodejs/node · GitHub

トレースのログファイルは標準的には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)

cluster: add cwd to cluster.settings by cjihrig · Pull Request #18399 · nodejs/node · GitHub

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

EventEmitter

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

events: add off alias to removeListener by Ulmanb · Pull Request #17156 · nodejs/node · GitHub

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

Errors

Tracking Issue: Migrate errors to internal/errors.js · Issue #11273 · nodejs/node · GitHub

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

詳細なドキュメントはこちら。
Errors | Node.js v10.0.0 Documentation

FS

PromisesのAPIが追加 (N/A)

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

fs: add promises API by jasnell · Pull Request #18297 · nodejs/node · GitHub

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

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

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

  console.log(n)
})();

HTTP

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

HTTP/1 createServer() options to pass custom Request and Response classes by hekike · Pull Request #15752 · nodejs/node · GitHub

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)

Process 100, 102-199 status codes according to specs. by miles-po · Pull Request #18033 · nodejs/node · GitHub

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

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

http: disallow two-byte characters in URL path by bennofs · Pull Request #16237 · nodejs/node · GitHub

> 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にも実験的に入りました。
以下の記事を参考にしてください。 blog.hiroppy.me

N-API

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

n-api: take n-api out of experimental by mhdawson · Pull Request #19262 · nodejs/node · GitHub

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

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

backport: 6, 8

n-api: expose n-api version in process.versions by mhdawson · Pull Request #18067 · nodejs/node · GitHub

> 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)

net: remove net.Socket.prototype.listen by BridgeAR · Pull Request #13735 · nodejs/node · GitHub

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

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

fs,net: emitting ready event for fs streams and network sockets in addition… by sameer-coder · Pull Request #19408 · nodejs/node · GitHub

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)

net: emit 'close' after 'end' by lpinca · Pull Request #19241 · nodejs/node · GitHub

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というモジュールに切り出されました。
以下の記事を参考にしてください。

blog.hiroppy.me

Process

process.ppidの追加(v9.6.0)

backport: 6, 8

src: add process.ppid by cjihrig · Pull Request #16839 · nodejs/node · GitHub

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

> process.ppid
73124

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

lib: allow process kill by signal number by sam-github · Pull Request #16944 · nodejs/node · GitHub

> 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)

fs,net: emitting ready event for fs streams and network sockets in addition… by sameer-coder · Pull Request #19408 · nodejs/node · GitHub

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

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)

stream: remove {writeableState/readableState}.length by calvinmetcalf · Pull Request #12857 · nodejs/node · GitHub

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

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

stream: always defer 'readable' with nextTick by mcollina · Pull Request #17979 · nodejs/node · GitHub

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

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

Stability:1

stream: added experimental support for for-await by mcollina · Pull Request #17755 · nodejs/node · GitHub

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)

timers: allow Immediates to be unrefed by apapirovski · Pull Request #18139 · nodejs/node · GitHub

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)

url: expose the WHATWG URL API globally by targos · Pull Request #18281 · nodejs/node · GitHub

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

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

Util

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

util: allow wildcards in debuglog() by TylerYang · Pull Request #17609 · nodejs/node · GitHub

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

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)

util: add util.inspect compact option by BridgeAR · Pull Request #17576 · nodejs/node · GitHub

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)

util: add bigint formatting to util.inspect by devsnek · Pull Request #18412 · nodejs/node · GitHub

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

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

util.typesの追加 (N/A)

util: introduce `util.types.is[…]` type checks by addaleax · Pull Request #18415 · nodejs/node · GitHub

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)

zlib: add ArrayBuffer support by JemBijoux · Pull Request #16042 · nodejs/node · GitHub

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