Skip to content

Instantly share code, notes, and snippets.

@koh110
Created November 26, 2017 02:56
Show Gist options
  • Save koh110/791a4820e11f17349449c95b8d104d56 to your computer and use it in GitHub Desktop.
Save koh110/791a4820e11f17349449c95b8d104d56 to your computer and use it in GitHub Desktop.

Source to Binary - journey of V8 javascript engine

https://speakerdeck.com/brn/source-to-binary-journey-of-v8-javascript-engine

青野健利 a.k.a brn

V8の話

コードを全部パースすると重い
functionの外観だけを先にパースする
実際にfunctionが呼ばれたタイミングで実際にパースする
Lazy Parsing

ASTの話
let, const, spread operator
astは重いのでbinaryにしちゃおう

bytecode interpreter
astをbytecodeに変換して実行する

Hidden Class
obectの構造体から型を推論する
別のオブジェクトであっても同じpropertyを持っていれば同じHiddenClassとして扱う
Mapと呼ぶ
厳密にpropertyの順番をみるので、少しでも違うと違うMapとして扱う
propertyの増減は多いので前のMapを引き継ぎながら新しいMapを作る
Mapによってプロパティアクセスや型のチェックがより高速になる

inline caching
プロパティアクセスの高速化のためにcachingする
hashmapやfixedarrayからプロパティを毎回ロードするのはすごく遅い
特定のmapを記憶しておく
2回目以降のアクセスは早くなる
違う構造をもつものをあまりに大量に配列にいれると、毎回ロードするので遅くなる

Node.js Production Checklist

Gergely Nemeth

99.9%動くサービスを作るには
26s/month しかdowntimeをもてない
SLA
SLOは Best Practice だと思っています。

error handling
you have to lean to throw again
migrate from callbacks to async-await
callbackじゃなくてtry catch使おうね
error handler middleware
error handlingのためのboomというmoduleいいよ
Middlewareを使うとエラーの失敗が少なくなっています。コードも短くなっています。

checklistの2つめはsecurity
npmコマンド自体のセキュリティをまず見直す
X-Frame-Options: clickjacking attak
strict-transport-security: to keep your yours on https
x-xss-protection: to prevent reflected css attacks
x-dns-prefetch-control
セキュリティのベーシックチェックは [helmet] (https://www.npmjs.com/package/helmet) で対応できます
joiでvalidateing user input

logging best practice

timestamp
format
destination
support for log levels

ログインを作る最低限の要素
timestamps いつおきたか
format人にも機械にも読みやすいもの
destination: 最低限のものをアウトプットする
Loglevel: debug とか infoとか

error
general errors, always reported
whenever
app may try to recover or forcefully terminate

warn

info
indicate major state changes in the application like the startup of the http server
each component shoud log

debug
diagnostical level events

log the original url of the request for errors

CICD

継続的なデリバリーを作るのに、なにをチェックするか

protect the master branch
only approved pull request can be merge

run automated checks on your codebase

with good test coverage
youcan doploy to production on evenry commit
Test Coverageが高い場合はデプロイが早くなります。

monitoring your applications

error rate: as they directly affetct customor satisfaction
latency
throughput
saturation

Response Time は役に立っていません。 (Gergleyの経験です)
you want to have route-level metrics
ユーザが使っている Endpoint は大事です。
endpointごとに見ろ。averageじゃなく
Black Box Monitoring サービスはいくつかがあります。
例えば Pingdom, ping.apex.sh

アラートシステム構築

問題の場合は書いている人が担当者にした方がいいです。
そうすると客と近くなるからコードのクオリティーが増えています。
問題のために Status Page があるのが客も気持ちが安全になります。
24時間のサービスのために少なくとも3人が必要になります。
war room

サマリー

  • Async awaitでのエラーハンドリングについて
  • 継続的デリバリーについて
  • ログの仕方、モニタリングの仕方
  • そしてアラートシステム構築

Node.js x Chrome headless で、お手軽WebRTC MCU

がねこまさし

https://www.slideshare.net/mganeko/nodejs-x-headless-chrome-for-wertc-mcu-nodejs-x-chrome-headless-webrtc-mcu/

mcuをNode.js x ヘッドレスブラウザで実現していじり放題

iOSはコーデックが1部しか対応してない

p2p

ブラウザ同士

good

  • サーバ不要
  • シンプル

bad

  • cpu負荷
  • ネットワーク負荷

負荷が高い理由
圧縮不可が高い理由
通信相手に合わせて別々に圧縮している(状況に合わせて

sfu

サーバ側で映像/音声を配布
サーバでは圧縮しない
クライアントがサーバに1つ映像を送りつける
結局うけ取るのは個別

MCU

サーバ側で映像/音声を合成

回線に合わせた圧縮率
クライアントに合わせたコーデックが利用可能

OSS

  • kuranto
  • licode

mcuをブラウザで

ブラウザのrequest animation frameを使っているのでタブを切り替えたりタブが隠れたりすると止まる
自分の声をのぞいた声を合成してあげないといけない

シグナリングの方法が規定されていない
アプリケーション、サービスごとに異なる

メッセージとシグナリングにだけnode.jsを使ってるっぽい

puppeteerとかは使ってない

Node.jsからchildProcessで起動
proc.kill('SIGKILL')で殺す

接続を始めたタイミングでheadless chromeを立ち上げてる。
全員いなくなったらプロセスkill

サーバ側の負荷は非常に高い

No REST for the weary... Introducing GraphQL

https://speakerdeck.com/siakaramalegos/no-rest-for-the-weary-dot-dot-dot-introducing-graphql-nodefest-japan

Sia Karamalegos

GraphQL -> ぐらふきゅーえるかと思ってたらぐらふぃくるって発音してる

before REST theare was SOAP
restはclientとserverを分ける(decouple)ためのものだった

watus the problem

API のコントロールが問題です。この API の例は FrontEnd のかたが変えません。
ブログのトップページを表示するのに、9つのリクエストを必要とする。
フロントエンドが必要ないデータもサーバーが送っています

chatty == slow

too much data

GraphQLは Specのみです。
GraphQLは、データの形を宣言して、必要なプロパティをリクエストするとそのデータだけを返す、という仕様
今日の例で REST のAPI を GraphQLに書き換えます。
現在はRESTで実装されているStar WarsのAPIを使います

https://github.com/graphql/graphiql
https://swapi.co/
ドキュメンテションは Spec で自動にもらえます。
今は swapi を GraphQL を使って試しています。
スターウォーズに登場する惑星のデータをgraphqlで取得します
必要のないデータはサーバーからは返ってきません

使い方
sample code
https://github.com/siakaramalegos/star_wars_graphql

expressでgraphqlを実現するためのライブラリ
https://www.npmjs.com/package/express-graphql
schemeをもとに、express-graphqlを利用しGraphQLのapiの作成
Apolloとかのツールもありますがこれはgraphql標準のスキーマです
GraphQLListを使うことで、外部テーブルをそのまま使うように定義を持ってくることができる

今さら聞けないSPAのCORS対策の話

杉浦颯太

CORS

Origin -> Scheme, Host, Port
サブドメインとかもoriginは変わるよ

Same Origin Policy

ブラウザがsame origin policyにのっとって処理を抑制している

意図的に制御を解除する仕組み -> CORS

Access-Control-Allow-Origin
Access-Control-Allow-Method

この辺理解しておいてね

  • cors
  • preflight
  • ajax with credentials

cross origin

Access-Control-Allow-Origin

Access-Control-Allow-Method

Access-Control-Expose-Headers
-> 明示的に許可したいヘッダを追加

access tokenをlocalstorageとかにもたせる

not best

xss仕込まれる
expireの仕組みとか自分で作らないといけない
-> 現状cookieになるんじゃないかな

Set-Cookie: HttpOnly; Secure

jsからdocument.cookieにアクセスできなくなる

withCredentials

Access-Control-Allow-Credentials: true

Access-Control-Allow-Originは*を指定できない
ちゃんと指定しようね

Optimize performance

preflight request

cross originのときにブラウザが勝手に送るリクエスト
-> 単純に通信コストが2倍になる

preflight request -> 実際のreuqest
put, delete, patch, optionsはpreflight requestが送られる
headerにもいくつか送られるやつがある

何も送らないように制御するのが一番いい

  • get,postしか使わないとか
  • content-typeを絞るとか

CSRF

origin headerはブラウザでは書き換えられないのでそれでチェック

preflightを最適化する方法はある

ブラウザでcacheできる
Access-Control-Max-Age: 100 -> 100秒間はブラウザにcacheさせる
あまりいけてない設定
ブラウザによって上限値が決まっている
chrome -> 10m
firefox -> 24h

Turbo Boost Next Node.js

Yosuke Furukawa

とりあえず資料だけメモ https://speakerdeck.com/yosuke_furukawa/turbo-boost-next-node-dot-js

Native ES Module - something almost, but not quite entirely unlike CommonJS

Gil Tayar
https://twitter.com/giltayar

es modulesがついにnode.jsにきたぞ
3年もかかった

--experimental-modules

named exports

kettle.mjs

export const spout = 'the spout'
export const handle = 'the handle'
export const tea = 'hot tea'

main.mjs

import { handle, spout, tea} from './kettle'

console.log(handle)

全てのloadはasynchronousであり、syncで動くcommonjsとは違う
ファイル名には .mjs が必要

ES modulesのルール

  1. ESM には .mjs を付ける
  2. .js は CJS

mjs は michael jackson script とも呼ばれてる

export default foo is same module.exports = foo and import a from 'a' is same to const a = require('a')

file resolution - index

index ファイルの解決方法は異なる。
ES Modulesでは、 package.json には main: "foo.mjs" と書く必要がある。

// このへんはcommon moduleの仕組みと一緒ぽいな

file resolution - node_modules

  • node_modules/kettle.mjsimport { tea } from './kettle'でimportできる

// node_modules以下が./になる。。。?

file resolution - dynamic

async function main() {
  const { tea } = await import('./kettle.mjs')

  console.log(tea)
}

main()

動的なloadをする場合、CommonJS の require はただの関数なので任意のタイミングで実行できる。 ESMの場合は import() という新しいsyntaxを使う必要がある。
これを await させて使う。

// importがpromiseを返す

import path from 'path'
import fs from 'fs'
import url from 'url'

const __dirname = path.dirname(new url.URL(import.meta.url).pathname)

import.meta.urlは__dirnameとimport.meta.urlはfile://xn--hogehoge-z83gka8m8am4be8w9g2327f、URL parsingは必要です。

Interoperability

ESM と CJS の間には 巨大なバリアがある
Node.js はそのバリアのためにbridgeを用意している

mjs can import js

  • but only default import

js can import mjs

  • but only dynamic import

js で named export されていると MJS から import するときには named import できない。失敗する
js で default export すれば MJS から default import で呼べる

migrating from cjs

CJSからESMにmigrationするには2つのアプローチがある。

as application developpers

  • stop using babel !!
  • rename all js to mjs cahnge all require-s to imports if it's cjs, then defualt imports only
  • change dynamic require-s to await import() only if they are really dynamic !

全てのjsをmjsに変更しよう。
requireをimportに変更して、もしもCJSから使うならdefault importだけ使うようにしよう。
dynamic require は 全て dynamic import だけにして、実行しよう。

as library developpers

  • require('no-extension') ** only '.js'
  • import ... from 'no-extension' ** first '.mjs' (as ecma)

Migrationのためのルールとしては .mjs.js を書かないextension無しでの呼び出しはやめておこう。

dual-mode-libraly
簡単なはなし。mjsとjsの2つのファイルを吐き出せばいい

まずはmjs-styleのファイルを書いてpackage.jsonのmainにそのファイルを書く
babelでmjsをjsファイルにbuildにする
シンプルに2つだけpluginを使えばいい

transform-es2015-modules-commonjs
dynamic-import

その時は.gitignoreにbabel済みのものをignoreするのを忘れずに。

TLに流れてた

http://teppeis.hatenablog.com/entry/2017/08/es-modules-in-nodejs

memo

https://speakerdeck.com/quramy/introduction-to-visual-regression-testing-jp これスクリーンショットのときに使えそう
requestIdleCallbackでスクリーンショット -> レンダリングのあとにスクリーンショットをとる
CSS animation, transitionをnone importで強制的に潰す

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment