Node.js セキュリティアップデートが出てた
2.23 に、Node.js の新しいバージョンがでたのでチェックしよう。
https://nodejs.org/en/blog/vulnerability/february-2021-security-releases/
10.x, 12.x, 14.x 15.x 用のセキュリティアップデート
重大(1), 高い深刻度(1), 低い深刻度(1)
- HTTP/2 の unknownProtocol があまりにも多くなった時、DoS 攻撃を受ける可能性がある問題
- ファイルシステムが漏洩する可能性
- メモリリークを引き起こす可能性
- localhost6 がホワイトリストに含まれている場合、DoS 攻撃を受ける可能性がある問題
- /etc/hosts に localhost6 を含んでいる場合、この攻撃を受ける可能性がある https://jvndb.jvn.jp/ja/contents/2018/JVNDB-2018-005401.html
- OpenSSL の脆弱性が Node.js を介して悪用される可能性がある問題
適宜追従しましょう(フロントエンドだけなら別にって感じだけど)。
※Nodejs 10.x は 2021.4.30 にサポート終了予定、12.x 系は 2022.4.30 で終了予定
※奇数バージョンは機能開発用バージョンで、偶数バージョンは長期サポートバージョン。最新 15.x 以外の奇数はない
Node.js のバグ報告について
nodejs-sec グループ
https://groups.google.com/g/nodejs-sec?pli=1
バグ報告の方法
https://github.com/nodejs/node/blob/master/SECURITY.md
Nodejs にバグを報告するとお金もらえるプログラム:バグバウンティプログラム
https://hackerone.com/nodejs
Node.js v15 について
Node.js v15 あまりキャッチアップしてなかったので、おさらいしてみました。
v15 のリリースは 2020.10.21。v16 は 2021.4 とかですかね。
公式 Medium
https://nodejs.medium.com/node-js-v15-0-0-is-here-deb00750f278
codedamn さんのまとめ YouTube
https://www.youtube.com/watch?v=OIzGI5wFiXg
めっちゃまとまってる
https://shisama.hatenablog.com/entry/2020/10/21/004612
1. npm 7 が同梱
npm 7 が入った。
https://www.npmjs.com/package/npm
-
workspace
という概念が入った- monorepo で作りたい時とかは便利そう
-
acceptDependencies
という概念も入った -
peerDependencies
の挙動変更 -
npx
が実行前に確認されるようになった -
npm audit
の表示方法が変更 -
package.exports
が npm の内部モジュールを参照できないようになった -
npm test
の表示内容が変更 -
npm build
とnpm unbuild
が廃止
https://blog.watilde.com/2020/10/14/npm-v7の主な変更点まとめ/
2. unhandledRejection の挙動変更
ブレイキングチェンジ!
-
unhandledRejection
の挙動が変わった。defaultwarn
だったのがthrow
になった。
ただそもそもこれが起きてる時は以下のタイミングで
-
Promise
を使った非同期処理において想定外のエラーが起きた - エラーハンドリングが漏れている
- 単純なコードのエラー
マズイプログラムになっているはずなので、挙動が変更になることでより安全なコードが書けるようになった。
https://zenn.dev/kimamula/articles/b32d11d52c2b7a733119
unhandledRejection について
https://medium.com/@hagevvashi/unhandledrejectionについて-70739d2b6a60
Web サービスを運営していると、Sentry を使ってエラーハンドリングしたりすると思う
window.onerror
は、Promise.reject()
によって投げられたエラーは拾わない
(ただし console.error()
形式で表示はされる)
Promise
を使うエラー(Node.js でファイル操作だとかをするときの I/O 処理や、ブラウザで API 通信の失敗)を検知する時に使う。
try {
await axios.post("/some-resources");
} catch(e) {
// error handling
throw e; // this causes unhandled rejection
}
window.addEventListener("unhandledrejection", (e: PromiseRejectionEvent): void => {
// an error loginng
logError(e.reason);
});
process.on("unhandledRejection", (error: {} | null | undefined, promise: Promise<any>) => {
// an error loging
logError(error);
})
https://medium.com/@hagevvashi/unhandledrejectionについて-70739d2b6a60
3. ES2021 に対応
JavaScript エンジンの V8 が v8.6 にアップデート。まぁでもブラウザでは既に使えるので珍しくはない
Promise.any
Promise.all
は、全部が resolved
になった時 / どれかが rejected
になった時エラー
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'foo');
});
Promise.all([promise1, promise2, promise3])
.then((values) => {
console.log(values);
})
.catch(() => {
console.log("error");
});
// expected output: Array [3, 42, "foo"]
Promise.race
は、どれかが resolved
になった時 / どれかが rejected
になった時エラー
Promise.allSettled
は、全部が resolved
か rejected
になった時 / エラーにはならない
Promise.any
は、どれかが resolved
になった時 / 全部が rejected
になった時エラー
10 個の Promise
を走らせて、9 個失敗しても、最後の 1 つが成功なら成功としたい時(race
だとどれかが reject
になるとエラーになっちゃう)に使う
WeakRefs
Garbage Collection 時に破棄できるオブジェクトを作れる。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef
var ref = new WeakRef(element)
ref.deref() // 参照元を取り出す
簡単にサンプルを作ってみた。↓
https://playcode.io/740665/
タイマーが動き続けている。別のタイマーで DOM 要素を 5 秒後に remove
する。元のタイマー関数では参照はできている。Garbage Collection されると参照がきえて止まる。
メモリリークを防ぐコードが書ける。
AggregateError
複数のエラーをまとめたい時に使う。
try {
throw new AggregateError([
new Error("some error"),
], 'Hello');
} catch (e) {
console.log(e instanceof AggregateError); // true
console.log(e.message); // "Hello"
console.log(e.name); // "AggregateError"
console.log(e.errors); // [ Error: "some error" ]
}
エラーを配列で与えられる。
Logical Assignment Operators 論理代入演算子
読みにくくなるからやめてほしいw
let a = true
a &&= false // x && (x = y): x と y が true な値の場合、y の値が代入される
// false
a
// false
a ||= true // x || (x = y): x が false な値の場合、y の値が代入される
// true
a
// true
a = null
a ??= 1 // x ?? (x = y): x が null or undefined な値の場合、y の値が代入される
// 1
a
// 1
a ??= 2
// 1
a
// 1
Numeric separators
桁が読みやすくなるから積極的に使おう。
123 === 1_2_3
// true
1_000_000_000.000_001
// 1000000000.000001
ただこんなでかいマジックナンバー扱いたくないし扱う機会もない気がする。
String.prototype.replaceAll
ブラウザで使えるようになってたやつ。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll
https://caniuse.com/mdn-javascript_builtins_string_replaceall
IE 11 は Babel を通せば replaceAll
が書かれたコードはトランスパイルしてくれる。preset-env (core-js)
を使うことで IE11 でも動く。
https://v8.dev/features/string-replaceall
ちなみに Next.js は @babel/preset-env
入ってないので IE11 対応させるなら config
で指定する。
4. Web Crypto API
JavaScript で暗号化・復号・署名・検証ができる Web 標準 API。
https://caniuse.com/cryptography
ブラウザでは昔っから使えたやつ。
Node は最近ブラウザで使えたやつが使えるようになってきているといういい話。
5. AbortController
Web リクエストを中止することができるグローバルユーティリティオブジェクトの AbortController
が Node.js 15 でも使えるようになった。
const ac = new AbortController();
ac.signal.addEventListener('abort', () => console.log('Aborted!'),
{ once: true });
ac.abort();
console.log(ac.signal.aborted); // Prints True
動画のダウンロードを中止する例
https://developer.mozilla.org/en-US/docs/Web/API/AbortController
var controller = new AbortController();
var signal = controller.signal;
var downloadBtn = document.querySelector('.download');
var abortBtn = document.querySelector('.abort');
downloadBtn.addEventListener('click', fetchVideo);
abortBtn.addEventListener('click', function() {
controller.abort();
console.log('Download aborted');
});
function fetchVideo() {
...
fetch(url, {signal}).then(function(response) {
...
}).catch(function(e) {
reports.textContent = 'Download error: ' + e.message;
})
}
fetch
はまだ Node.js に実装されてないけどね。
フロントエンドの UI 開発で、ボタンに対しての mousedown/mouseup イベントを addEventListen していて、クリック後画面遷移してしまうので removeEventListen しておきたい時、abortController を使えば一発で解除できるテクがどっかで紹介された。
6. Event Target
ブラウザで使えた EventTarget
が Node.js でも使えるようになった。Event
の発行・伝播はブラウザでは EventTarget
、Node.js では EventEmitter
を使っていた。
https://nodejs.org/api/events.html#events_eventtarget_and_event_api
const target = new EventTarget();
target.addEventListener("foo", (event) => {
console.log("foo is called");
});
const ev = new Event("foo");
target.dispatchEvent(ev);
イベントが DOM ツリーを伝って伝播が行われないなど差はあるが、ユニバーサルなプログラムが書けるようになってきている。
7. N-API updated
Node.js のネイティブ拡張をするための Node API (通称 N-API) がアップデート。C 言語のインターフェース。まぁ使うことはあまりないのかなぁ。
https://nodejs.org/api/n-api.html#n_api_node_api
8. QUIC (実験的機能)
UDP ベースの通信プロトコル「QUIC」が使用できるようになった。
TLS 1.3 ベースでのセキュリティ、フロー制御、エラー訂正、接続、多重化とかとか。
TLS 1.3 とは: https://kinsta.com/jp/blog/tls-1-3/
HTTP/3 サーバーを作ることができる。
https://blog.leko.jp/post/http-over-quic-on-nodejs15/
むずすぎてよくわからんですね
かんそう
- せめて Node.js 14.x にはしとこう