Slide 1

Slide 1 text

Frontend Boot Camp 2022-08-23 #hatenaintern

Slide 2

Slide 2 text

׆סه٭ع؞ٔ٤وסإ٭ٜ "نٞ٤عؙ٤غ" JavaScript/TypeScript/React Web React TypeScript #hatenaintern

Slide 3

Slide 3 text

( min) #hatenaintern

Slide 4

Slide 4 text

杯♏סنٞ٤عؙ٤غמ חַי React ٝؕؓؗع؅磝׳׆כע׵ה؀؆յؓوٛ آ٭ب٘٤ֿ辐炐׈׿׾ױךס孱׿؅縒ֻ יײ׾כ䑒釐כ׈׿׾湳閁׵㛡ׂםזי׀ ױ׌ն Frontend Developer Roadmap: Learn to become a modern frontend developer React JavaScript #hatenaintern

Slide 5

Slide 5 text

喋չםⳂ⛼梪㗞ס┉❆ א׿ב׿ס梪㗞מעյ׆׿׼ס䤗软מ׻זי⤓ֻ׾׆כֿך׀ױ׌ն IE Web (accessibility, a y) א׿ב׿յלס׻ֹמ㵚瓀׌׾ס־釤יַ׀ױ׌ն #hatenaintern

Slide 6

Slide 6 text

: React 1. TypeScript JavaScript 2. Web 3. Web html 4. (accessibility, a y) TypeScript - TypeScript Deep Dive #hatenaintern

Slide 7

Slide 7 text

: React ˝ Web ˝ ˝ (accessibility, a y) ⪮⛮氳מעלֹס׻ֹמ㵚瓀׊יַׂס ־յꝧ氦ס孱׿כ⪦מ釤יַ׀ױ׌ն #hatenaintern

Slide 8

Slide 8 text

: React React JavaScript html > ls index.html main.js #hatenaintern

Slide 9

Slide 9 text

: React React/TypeScript
// main.tsx const App = () => { const user: User | null = useUser() return (
Α͏ͦ͜ɺ{user?.name ?? 'ήετ'}͞Μɻ
) } const container = document.getElementById('root') const root = createRoot(container!) root.render() #hatenaintern

Slide 10

Slide 10 text

: React TypeScript JavaScript const user = useUser() TypeScript const user: User | null = useUser() jsx jsx const label = () => (
...
) HTML ES ?. ?? => JSX TypeScript JavaScript Null (??) - JavaScript | MDN (?.) - JavaScript | MDN JSX React #hatenaintern

Slide 11

Slide 11 text

عٚ٤تقٜؕ 僃二ס乃嫎ך傴ַגؤ٭غ؅㛡ׂס⹿ַ梪㗞⹿ַهٚؗاםלך׵ Ⳃׂ׻ֹמ⹿ַ鋗嫎׫㚺䬵׌׾׆כ Null (??) const hello = (name) => `hello, ${name ?? "ήετ"}!` hello("hatena") // > hello, hatena! hello() // > hello, ήετ! #hatenaintern

Slide 12

Slide 12 text

عٚ٤تقٜؕ ES (ES ) Null (??) ES var hello = function hello(name) { return "hello, " + (name !== null && name !== void 0 ? name : "ήετ") + "!" } hello("hatena") // > hello, hatena! hello() // > hello, ήετ! #hatenaintern

Slide 13

Slide 13 text

ص٭ٜزؘؕ٤ 3 (Rome , Deno ) عٚ٤تقؕٚ Babel (JavaScript) SWC (Rust) esbuild (Golang) ف٤غٚ Webpack Rollup Parcel (SWC) Snowpack, Vite (esbuild) https://deno.land/ https://rome.tools #hatenaintern

Slide 14

Slide 14 text

Web Chrome, IE, Safari, Firefox Web API JavaScript(ECMAScript) HTML DOM API CSS API poly ll JavaScript transpile 2021 | gihyo.jp Web standards ( ) - MDN Web Docs : | MDN #hatenaintern

Slide 15

Slide 15 text

Web هٚؗاׇכסئَ٭ع敯媲ע♓┖סئؕعך澬鏀׌׾׆כֿך׀ױ׌ն MDN https://developer.mozilla.org/ja/docs/Web MDN Can I use https://caniuse.com mozilla Google Open Web Docs https://opencollective.com/open-web-docs/updates/ introducing-open-web-docs #hatenaintern

Slide 16

Slide 16 text

(accessibility, a y) | MDN ؘؗهꝧ氦מֽׄ׾ؓؠجبلٛطؔכעյ⛰׼־ס杼榺מ׻׽耆ⱱמ⯆硜ֵֿ׾㕙⺬ך׵յ⺎耆ם꡾׽㛡ׂ ס☔չֿؘؗهئؕع؅✳榫ך׀׾׻ֹמ׌׾׆כ؅䙫⽏׊ױ׌նؓؠجبلٛطؔכעյ⠕☔ס骰⛮氳٬鏀 湳氳耆ⱱ׷ؘؗه׫סؓؠجت亠嫎מ꞊؂׼׍յ⺎耆ם꡾׽ؓؠجت⺎耆םؤ٤ط٤ص؅ꝧ氦׌׾׆כך׌ն W C - Accessibility / #hatenaintern

Slide 17

Slide 17 text

(accessibility, a y) ( HTML) alt (Tab ) HTML - | MDN Semantics ( ) - MDN Web Docs : | MDN #hatenaintern

Slide 18

Slide 18 text

قنؚ٭ُ٤ت㵚瓀 ⮵榫⯆꡾ֿ־־זיַ׾鷐ַ٬┘㱦㲊םؕ٤ذ٭ؾشع؅✳זיַ׾ٗ٭ا٭ֿ ╚מ㵚霄כם׾ն js css 1 => 僃⮣סً٭ةמ䑒釐ם׵סדׄرؗ٤ٞ٭غ׊י碛企ׂ辐炐׌׾׬׀ Cumulative Layout Shift (CLS) https://web.dev/i n/ja/cls/ #hatenaintern

Slide 19

Slide 19 text

قنؚ٭ُ٤ت㵚瓀 ⮵榫⯆꡾ֿ־־זיַ׾鷐ַ٬┘㱦㲊םؕ٤ذ٭ؾشع؅✳זיַ׾ٗ٭ا٭ֿ╚מ㵚霄כם ׾ն (CDN, Edge) CDN 1 (Code Splitting) (preload, defer, lazy) #hatenaintern

Slide 20

Slide 20 text

: React 1. TypeScript JavaScript 2. Transpile, Polyfill Bundle, Code Splitting 3. Web html 4. #hatenaintern

Slide 21

Slide 21 text

JavaScript ( min) #hatenaintern

Slide 22

Slide 22 text

JavaScript ( min) ES (ES ) JavaScript JavaScript JavaScript · JavaScript Primer #jsprimer #hatenaintern

Slide 23

Slide 23 text

1/2 // ม਺ͱએݴ var a = "a" // ม਺ʢάϩʔόϧʣ let b = "b" // ม਺ʢϩʔΧϧʣ const c = "c" // ఆ਺ /* ஫ҙ * var Λ༻͍ͨม਺એݴ͸ɺ window ΦϒδΣΫτΛ্ॻ͖ͯ͠͠·͏ */ var console = null console.log("xxx") // Error: window.console is null const id = "1234" // string const name = null // null const age = 2022 // number const isAdmin = false // boolean // object const user = { id, username: name age, isAdmin, memo, } user.age // 2022 // ະఆٛϓϩύςΟͩͱ undefined ͕ฦΔ user.abc #hatenaintern

Slide 24

Slide 24 text

2/2 // ؔ਺ function getUser(id) { return db.users.find(id) } const getBlog = (id) => { return db.blogs.find(id) } // ഑ྻ const array1 = [1, 2] const array2 = new Array(1, 2) // ഑ྻॲཧ for (elm in array1) { console.log(elm) } array2.forEach((elm) => { console.log(elm) }) array1.map((elm) => elm * 2) // [2, 4] array2.at(0) // 1 #hatenaintern

Slide 25

Slide 25 text

Arrow Function ˝ function׷return؅✳؂׍מ꞊丗؅榟䡗ך׀׾ ˝ 㓹儖氳מע׆ס亠嫎ך꞊丗؅榟䡗׊יֽׄףـُ׼םַ const hello = (name) => `Hello, ${name}` hello("world") // hello, world 1 () Tips: () const getProps = () => ({ a: "foo", b: "bar" }) this Arrow Function #hatenaintern

Slide 26

Slide 26 text

Arrow Function ˝ 䌕丗ֿ邾丗ֵ׾㕙⺬ע()ך㍱ֹ ˝ ꞊丗⫂ס鋗鳭ֿ邾丗车מ峚׾כ׀ע{}כreturn؅榫ַ׾ const hello = (name, lang) => { if (lang === "ja") return `͜Μʹͪ͸ɺ${name}` if (lang === "es") return `Hola, ${name}` return `Hello, ${name}` } #hatenaintern

Slide 27

Slide 27 text

Promiseמחַי Pending( ) (resolve) Fulfilled (reject) Rejected Fulfilled Rejected ( ) Settled then catch const sleep = (ms) => new Promise((resolve) => { setTimeout(() => resolve(ms), ms) }) sleep(1000) .then((ms /* resolveͨ͠஋Λड͚औΕΔ */) => console.log(`sleep: ${ms}ms`)) .catch((e) => { console.error(e) }) #hatenaintern

Slide 28

Slide 28 text

fetch؅✳זג❆ fetch HTTP API Promise Promise console / /* Ϣʔβʔ৘ใΛऔಘ͢ΔAPIͷྫɻҎԼͷΑ͏ͳJSON͕ฦͬͯ͘Δͱ͍͏૝ఆɻ { user: {id: 1, name: 'hatena'} } */ const promise = fetch("https://api.example.com/user/1") .then((res) => res.json()) .then((json) => json.user) .then((user) => { console.log(`${user.name}ͷid͸${user.id}`) }) .catch(console.error) console.log(promise) // Promise {} ɾɾɾ ᶃ #hatenaintern

Slide 29

Slide 29 text

Promise Promiseס鿥⮛؅⛼䡗׊յא׿؅䣽ֹ׆כך䴧⛍氳ם┾⮛⭚杼؅车ֹ׆כֿ⭳全׾ն const promises = urls.map((url) => fetch(url)) // ෳ਺ͷAPIͳͲΛฒྻʹୟ͘ Promise.all() Resolve( ) 1 Reject Promise.allSettled() Resolve Reject Promise Promise: {status: 'fulfilled', value: resolveͨ͠஋}, Promise: {status: 'rejected', reason: reject͞ΕͨΤϥʔ} #hatenaintern

Slide 30

Slide 30 text

Promise const promises = [ getFromCache(), // cache͕ۭͷͱ͖͸ࣦഊ͢Δ getFromApi(), ] Promise.race() 1 Promise Resolve Reject Promise.any() Resolve Promise Reject #hatenaintern

Slide 31

Slide 31 text

async/await async function await Promise try {} catch (e) {} async function throw const getUser = async (id) => { try { const res = await fetch(`https://api.example.com/user/${id}`) const json = await res.json() const user = json.user console.log(`${user.name}ͷid͸${user.id}`) return user } catch (e) { console.error(e) throw new Error("error reason: *********") } } ECMAScript Top-level await async function await #hatenaintern

Slide 32

Slide 32 text

async/await async function Promise Promise then Promise await getUser(1) .then(console.log) // {id: 1, name: 'hatena'} .catch(console.error) ˝ 扛⺲꞊丗כ׊י㲔车׌׾׆כ׵׵ה؀؆⭳全׾ ;(async () => { const user = await getUser(1) console.log(user.name) // 'hatena' })() #hatenaintern

Slide 33

Slide 33 text

class ES class class Rect { constructor(width, height) { this.width = width this.height = height } // getter΍setterΛఆٛͰ͖Δ get area() { return this.getArea() } getArea() { return this.width * this.height } } const rect = new Rect(5, 10) console.log(rect.area) // 50 function class https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritanceandtheprototypechain #hatenaintern

Slide 34

Slide 34 text

ECMAScript Modules ٓةٖ٭ٜ 1 == 1 import/export CommonJS Node.js ECMAScript Node.js Babel 1 webpack JavaScript ECMAScript JavaScript ECMAScript JavaScript ( ) module.exports require https://nodejs.org/docs/latest/api/modules.html #hatenaintern

Slide 35

Slide 35 text

default export // module.js export default function doSomething() {} ˝ export defaultךؙؠتَ٭ع׌׾כյimport侇מע♳䙫ס⺲ ⯥؅錃㲊ך׀׾ import awesome from "./module" #hatenaintern

Slide 36

Slide 36 text

(named export) ˝ constך㚺丗㲚銧׌׾כ׀מexport؅♀ⱶ׌׾׆כך⺲⯥♀׀ؙؠتَ٭عֿ⭳ 全׾ // namedModule.js export const logType = { error: 'error', log: 'log' }; export const log = (message, type) => { if (type === 'error') return console.error(message); return console.log(message); } export const hello => log('hello'); #hatenaintern

Slide 37

Slide 37 text

ؕ٤َ٭عס亠嫎מחַי export import { log, hello } from "./namedModule" ˝ asךٛؾ٭ّ⭳全׾ import { logType as LOGTYPE } from "./namedModule" * as export import * as Logger from "./namedModule" Logger.hello() // 'hello' (webpack TreeShaking ) * as #hatenaintern

Slide 38

Slide 38 text

Tips #hatenaintern

Slide 39

Slide 39 text

for...of (iterable) NodeList Map Set const iterable = [10, 20, 30] for (const value of iterable) { console.log(value) } #hatenaintern

Slide 40

Slide 40 text

Nullish coalescing operator ?? JavaScript || const rect = (width: number, height?: number) => ({ width: width, height: height || 100, // ߴ͞Λলུͨ͠ͱ͖͸σϑΥϧτ஋Λ༩͑Δ }) rect(50, 0) // {width: 50, height: 100} 0 ''( ) Falsy height 0 ?? null undefined ?? ?? !!0 !!'' boolean false JavaScript false null undefined NaN Falsy boolean true Truthy https://developer.mozilla.org/en-US/docs/Glossary/Falsy JavaScript || Truthy Falsy && Falsy Truthy #hatenaintern

Slide 41

Slide 41 text

Optional chaining ?. ˝ ؛هةؘؠعֿnull׷undefinedם⺎耆䓪ֵֿ׾כ׀յאס؛هةؘؠعסوٞقطؔ؅⽛שג״מifמ׻׾⮆㹎׷&&מ׻׾湾 礘鍐❫؅傴ׂ䑒釐ֵֿזגն const val = nullOrObject && nullOrObject.method() const result = val && val.methodOfReturnValue() ˝ .?؅榫ַ׾כյ⽛צ⭳׊⩕ֿnullױגעundefinedסכ׀עא׿♓꡸סوٞقطؔؓؠجت؅׊םַնױגյאס㕙⺬ע undefinedכ׊י鍐❫׈׿׾ն const result = nullOrObject?.method()?.methodOfReturnValue() nullOrObject׵nullOrObject.method()ס鲭׽⡁ֿ⪦מnullך׵undefinedך׵םַכ׀מյ nullOrObject.method().methodOfReturnValue()ס磵冽؅䐂׼׿׾ն && Falsy null undefined && || Falsy Optional chaining #hatenaintern

Slide 42

Slide 42 text

Spread Syntax ˝ ...؅✳ֹכ鿥⮛׷؛هةؘؠع؅㷣ꝧ⭳全׾ const sum = (a, b, c, d) => a + b + c + d const nums = [1, 2] const copied = [...nums] // த਎Λෳ੡ͨ͠഑ྻΛ࡞ΕΔ const moreNums = [...copied, 5] // [1, 2, 5] sum(...nums, 10) // 18 const obj = { a: 10, b: "foo" } const obj2 = { b: "bar", c: true } // 2ͭҎ্ͷobjectΛmerge͢ΔɻΩʔ͕ॏෳ͍ͯ͠Δ৔߹͸ޙʹॻ͍ͨํͰ্ॻ͖͞ΕΔ const merged = { ...obj, ...obj2 } // {a: 10, b: 'bar', c: true} const getUserConfig = (received) => ({ force: false, allowJs: false, ...received, // σϑΥϧτ஋Λ౉͞Εͨ஋͕͋Ε͹্ॻ͖͢Δ }) #hatenaintern

Slide 43

Slide 43 text

Rest Parameters ... Spread Syntax 1 // const sum = (num1, num2, ...nums) => num1 + num2 + nums.reduce((a, b) => a + b, 0) const numbers = [1, 2, 3] sum(3, ...numbers, 6) // 15 #hatenaintern

Slide 44

Slide 44 text

TypeScript ( min) #hatenaintern

Slide 45

Slide 45 text

TypeScript is JavaScript JavaScript JavaScript node React JavaScript JavaScript API Uncaught TypeError: Cannot read property 'foo' of undefined JavaScript Alternative JavaScript TypeScript #hatenaintern

Slide 46

Slide 46 text

tsc: TypeScript compiler TypeScript TypeScript https://github.com/microsoft/TypeScript TypeScript JavaScript ( ) --noEmit TypeScript JavaScript JavaScript ( ) JavaScript Babel, esbuild babel @babel/preset-typescript babel enum enum typeof JavaScript ( ) #hatenaintern

Slide 47

Slide 47 text

㑔㲚銧鼧⮆؅鐆״׾׻ֹמם؀ֹ TypeScript Playground #hatenaintern

Slide 48

Slide 48 text

㚺丗㲚銧侇ס㑔ؓؿط٭ب٘٤ // JavaScriptͷ৔߹ const a = 'hello'; // TypeScriptͷ৔߹͸ม਺໊ͱ=ͷؒʹ:Λஔ͍ͯܕΞϊςʔγϣϯΛॻ͘ const a: ʲ͜͜ʹܕΞϊςʔγϣϯʳ = 'hello'; // ྫ͑͹ const a: string = 'hello'; ׆׿ׂ׼ַדזג׼䫟鑜׊יׂ׿׾סךյ㲔꤀מע傴־םַ׆כ ׵㛡ַ #hatenaintern

Slide 49

Slide 49 text

: string, number, boolean, null, undefined 'hello', 12, true, false ( ) const a: number = 10 const b: boolean = false const c: string = 11 // Type Error const d: "hello" = "hello" const n: null = null ˝ 鿥⮛ const arr: string[] = ["hello", "world"] const arr2: Array = [1, 2, 3, 5, 8] const arr3: [string, number] = ["year", 2021] // λϓϧ(Tuple)ܕͱ΋ #hatenaintern

Slide 50

Slide 50 text

JavaScript ? const person: { name: string age: number address?: string } = { name: "john", age: 21, } string | undefined JavaScript (Object.keys() ) TypeScript . exactOptionalPropertyTypes tsc #hatenaintern

Slide 51

Slide 51 text

type type؅✳ֹכ㑔辐杯מؙؕٛؓت؅♀ׄ׼׿׾ type Person = { name: string age: number } type Team = Person[] #hatenaintern

Slide 52

Slide 52 text

Union Type ( ) 邾丗ס㑔סַ׍׿־؅嵹ג׌ type Primitive = string | number | boolean | undefined | null type Color = "red" | "green" | "blue" | "yellow" | "purple" #hatenaintern

Slide 53

Slide 53 text

(Type Guard) JavaScript JavaScript TypeScript typeof in JavaScript #hatenaintern

Slide 54

Slide 54 text

typeof ( " " JavaScript ) 'string', 'number', 'boolean', 'object', 'function', 'undefined' console.log(typeof "hello world") // 'string' const n = 10 console.log(typeof n) // 'number' const p: Person = { name: "jonh", age: 20 } console.log(typeof p) // 'object' console.log(typeof undefined) // 'undefined' console.log(typeof null) // 'object' console.log(typeof ["a"]) // 'object' #hatenaintern

Slide 55

Slide 55 text

typeof ˝ 攐מnumber׷stringךֵ׾׆כמ⯆꡾׊גַכ׀מ값⭳ // paddingʹ͸ۭനͷ਺·ͨ͸λϒจࣈͳͲ͕΍ͬͯ͘Δ͜ͱΛ૝ఆͨؔ͠਺ const padLeft = (val: string, padding: string | number) => { if (typeof padding === "number") { return " ".repeat(padding) + val } // padding͕numberͰͳ͍ͷͰɺstringͰ͋Δͱਪ࿦͞ΕΔ return padding + val } #hatenaintern

Slide 56

Slide 56 text

in API type Fish = { name: string swim: () => void } type Bird = { name: string fly: () => void } const move = (x: Fish | Bird) => { if ("swim" in x) { // swim͕༗Δͷ͸FishܕͷΈ return x.swim() } // ͳͷͰɺ͜͜ʹ౸ୡ͢Δͱ͸BirdܕͰ͋Δͱ෼͔Δ return x.fly() } #hatenaintern

Slide 57

Slide 57 text

Object.hasOwn() 2022/08/18 TypeScript ES Object.hasOwn() const move = (x: Fish | Bird) => { if (Object.hasOwn(x, "swim")) { // swim͕༗Δͷ͸FishܕͷΈ͚ͩͲɺ Fish͔ Bird͔ͷͲͪΒ͔Λ൑ఆͰ͖ͳ͍ return x.swim() // error: Property 'swim' does not exist on type 'Fish | Bird'. } ... } Support for Object.hasOwn (lib.d.ts and narrowing) · Issue # · microsoft/TypeScript #hatenaintern

Slide 58

Slide 58 text

Tagged Union Types ˝ type׷kindס׻ֹםوٞقطؔמٛطٜٚ㑔؅錃㲊׊יַֽיյאס╈骰؅===׷switch؅✳זי奂鬳׌׾׆כךյ㑔ס礓׽鱮ײ؅车ֹ ˝ ⠕☔氳ם䚉釶דכյinךס礓׽鱮ײ׻׽׵׆ה׼סقذ٭٤ס亠ֿ׻ׂ⮵榫׌׾妳ֿ׊ױ׌ ˝ ٛطٜٚ㑔ס奂鬳ס亠ֿ傴ׂסֿ癨ⶡךյ־ח׆ה׼ס׮ֹֿ׻׽㱦⪒ך׌ն type Fish = { kind: "fish" name: string swim: () => void } type Bird = { kind: "bird" name: string fly: () => void } const move = (x: Fish | Bird) => { if (x.kind === "fish") { return x.swim() } return x.fly() } #hatenaintern

Slide 59

Slide 59 text

as (Type Assertion) TypeScript ( ) #hatenaintern

Slide 60

Slide 60 text

as JavaScript // ܕFooΛ௥Ճ͢Δ type Foo = { bar: number piyo: string } const something = (x: Foo) => { // ܕͱͯ͠͸߹͍ͬͯΔ͕ɺϥϯλΠϜ্Ͱͷ࣮ߦ࣌ʹ͸piyo͕undefinedʹͳΔͷͰΤϥʔ͕ى͖Δ return x.piyo.split(",") } var foo = {} as Foo // Fooͱͯ͠ѻ͑ΔΑ͏ʹ͓ͯ͘͠ // ࣮ࡍʹ͸barͳͲ͸ແ͍͕Fooͱͯ͠Ξαʔγϣϯ͍ͯ͠ΔͷͰ౉ͤΔ something(foo) #hatenaintern

Slide 61

Slide 61 text

const as as const ( readonly ) const a = [1, 2, 3] // aͷܕ͸number[]ͱͳΔ const b = [1, 2, 3] as const // bͷܕ͸readonly [1, 2, 3]ͱͳΔ type Pallet = { colors: readonly Color[] } const setPallet = (p: Pallet) => { /* do something */ } const pallet = { colors: ["red"], } // ͜͜ʹ as const Λ෇͚ͳ͍ͱ{ color: string[] }ͱਪ࿦͞ΕͯΤϥʔʹͳΔ setPallet(pallet) #hatenaintern

Slide 62

Slide 62 text

any unknown TypeScript #hatenaintern

Slide 63

Slide 63 text

any ˝ ⛰׼־ס⡁ֿ⪌זיַ׾׆כ؅炐׌նundefined־׼؛هةؘؠ ع־׼꞊丗ױך⛰ֿ⪌זיַי׵荁ַնtscֿ㑔ס吾錞؅׊םַ סךյas⺱喋מ鹴ׄ׼׿׾㕙⺬ע鹴ׄ׾ն let anything: any = {} // anyʹ͸ԿͰ΋୅ೖͰ͖Δ anything = () => {} anything = null anything.split(",") // anyͷ৔߹͸ϝιου΋ͳΜͰ΋ࢀরͰ͖Δ #hatenaintern

Slide 64

Slide 64 text

unknown any any unknown unknown {} | null | undefined const getObjectValues = (obj: {}) => Object.values(obj) // ݺͼग़͠ଆ͸unknownͳͷͰ޷͖ͳ஋Λ౉ͤΔ const stringifyForLog = (val: unknown) => { if (val === null || val === undefined) return "(anonymous)" return JSON.stringify(getObjectValues(val)) } #hatenaintern

Slide 65

Slide 65 text

typeכinterface ˝ typeעؙؕٛؓت ˝ interfaceע؛هةؘؠعמ㑔؅♀ׄ׾⮯ס亠嫎ն ˝ 仴㰆ס׵סמ䏲־׼وٞقطؔ؅鴑ⱶך׀׾סעinterface ˝ ٚؕهֿٚٛ䬠❠׊גinterface؅⮵榫縖ֿ舅榺מ䦡䍖ך׀׾ ˝ typeע⮯ס⺲⯥؅♀ׄ׾䑒釐ֵֿ׾ ˝ typeכinterfaceס✳ַ⮆ׄעؤ٭غ釨硜םלך荇չם孱孬׷╚䍖ֵֿ׾ סךյ齁מ⪌׿ף齁מ䏼זיׂד׈ַ #hatenaintern

Slide 66

Slide 66 text

typeכinterface Type Type type Blog = { title: string content: string } // NG: Duplicate identifier 'Blog'. type Blog = { tags: string[] } // OK type NewBlog = Blog & { tags: string[] } Interface Interface ES Array at() TypeScript . Array // lib.es5.d.ts interface Array { length: number toString(): string ... } // lib.es2022.array.d.ts interface Array { at(index: number): T | undefined } #hatenaintern

Slide 67

Slide 67 text

꞊丗 仴מئ٤وٜךע⛰䈱׵⭳י׀יַ׾ׄלյ䌕丗׷鲭׽⡁ס㑔ס傴׀亠סقذ٭٤גה磆☭׊יֽ׀ױ׌ն const f = (x: string): number => { return x.length } // ಛʹreturnΛ͠ͳ͍৔߹͸ฦΓ஋ʹvoidΛࢦఆ͢Δ const a: () => void = () => { console.log("a") } // ΦϓγϣφϧͳҾ਺͸keyʹ?Λ෇͚Δ // ਪ࿦͞ΕΔ΋ͷͰྑ͍ͳΒฦΓ஋ͷܕ͸লུՄ const b = (n?: number) => `${n}` // Rest ParametersΛड͚औΔ৔߹͸͜͏͍͏ײ͡ const c = (...texts: string[]) => { return texts.join("|") } #hatenaintern

Slide 68

Slide 68 text

(Generics) TypeScript querySelector - Hatena Developer Blog const getJSON = (url: string): Promise => { // res.json͸anyͱͳΒͣʹܕҾ਺Ͱ౉͞Εͨ΋ͷͱղऍ͞ΕΔ return fetch(url).then((res) => res.json()) } // ͜͜Ͱusers͸User[]ʹͳΔ const users = await getJSON("/api/users") // ͜͜Ͱblogs͸Blog[]ʹͳΔ const blogs = await getJSON("/api/blogs") #hatenaintern

Slide 69

Slide 69 text

: extends / const echo = (text: T): T => { return text } const a = echo("foo") // a ͷܕ͸ 'foo' const str: string = "foo" const b = echo(str) // b ͷܕ͸ 'string' #hatenaintern

Slide 70

Slide 70 text

never never void never never ( ) const infiniteLoop = (): never => { while (true) {} } strictNullChecking JavaScript undefined #hatenaintern

Slide 71

Slide 71 text

never؅榫ַג禿糵䓪زؘشؠ ˝ never؅榫ַ׾׆כך㑔؝٭غםלךס禿糵䓪؅زؘشؠך׀׾ type Color = "red" | "yellow" | "purple" const magical = (color: Color) => { switch (color) { case "red": return "tomato" case "yellow": return "banana" default: // શͯͷcase͕໢ཏ͞Ε͍ͯΕ͹͜͜ʹ౸ୡ͢Δ͜ͱ͸ͳ͍ // ͜ͷ৔߹͸'purple'͕୅ೖ͞ΕΔՄೳੑ͕͋ΔͷͰɺ੩తղੳ࣌ʹΤϥʔʹͳͬͯݕग़Ͱ͖Δ const val: never = color throw new Error(`"${color}" is not implemented`) } } #hatenaintern

Slide 72

Slide 72 text

׉זכדׄ浊״׾ؤ٭ػ٭ ˝ ׆׆ױך؅杼鉮׊גכ׀מ鐆׳כ➘⮵םؤ٭ػ٭ך׌ ˝ ה׺זכ׊גطؠؼشؠכ⺬؂׎י傴ַיֽ׀ױ׌ #hatenaintern

Slide 73

Slide 73 text

Readonly / ReturnType ˝ Readonlyע؛هةؘؠع׷鿥⮛ס釐碛؅鐆ײ鱮ײ㵠榫מך׀׾ ˝ ⫋䅯氳מע鸵榫׈׿םַ׆כמ嫰䙫 type PersonRo = Readonly ˝ ReturnTypeע꞊丗ס鲭׽⡁㑔כ׊י䐂׾ type Func = () => string type ReturnVal = ReturnType // ReturnVal͸stringͱղऍ͞ΕΔ #hatenaintern

Slide 74

Slide 74 text

typeof TypeScript JavaScript const hello = () => "hello" type Func = typeof hello type P = ReturnType // P͸stringͱղऍ͞ΕΔ #hatenaintern

Slide 75

Slide 75 text

keyof key union type const config = { checkJs: false, force: true, } // typeofͰconfigͷܕΛಘͯɺkeyofͰͦͷΦϒδΣΫτͷܕͷΩʔΛྻڍ͢Δ type ConfigKey = keyof typeof config // "checkJs" | "force" const getConfigVal = (key: ConfigKey) => config[key] getConfigVal("ignore") // Τϥʔͱͯ͠ݕग़Ͱ͖Δ #hatenaintern

Slide 76

Slide 76 text

Indexed Access Types JavaScript [] typeof keyof JavaScript type Person = { name: string age: number } type Age = Person["age"] // number const signalColors = ["red", "blue", "yellow"] as const // as const͠ͳ͍ͱstring[]ʹͳΔ // Arrayʹ[number]ͰΞΫηε͢Δͱ഑ྻͷ஋Λྻڍͨ͠ܕΛಘΒΕΔ type Signal = typeof signalColors[number] // 'red' | 'blue' | 'yellow' #hatenaintern

Slide 77

Slide 77 text

(Intersection Types) 邾丗ס㑔؅磝ײ⺬؂׎י㑔؅榟䡗׌׾ն❆ֻףٗ٭ا٭ס嘤꡾מ 䑴׋יٝتَ٤تס㑔؅㚺ֻ׾㕙⺬ע׆ַֹֹ䚉׋ն type Blog = { title: string; domain: string } type Editor = { editable: true; authority: ["edit"] } type Owner = { editable: true; authority: ["edit", "publish"] } type ResponseForEditor = Blog & Editor type ResponseForOwner = Blog & Owner #hatenaintern

Slide 78

Slide 78 text

Conditional Types JavaScript condition ? trueExpression : falseExpression // JavaScriptͷࡾ߲ԋࢉࢠ // SomeType͕OtherTypeΛຬͨͤ͹TrueTypeΛಘΔ SomeType extends OtherType ? TrueType : FalseType; Overloads declare function getID( fancy: T ): T extends true ? string : number const stringReturnValue = getID(true) const numberReturnValue = getID(false) const stringOrNumber = getID(Math.random() < 0.5) #hatenaintern

Slide 79

Slide 79 text

Overloads Overloads function request(url: string): Promise function request(url: string, onlyIsOk: true): Promise function request(url: string, onlyIsOk = false) { const promise = fetch(url) if (onlyIsOk) return promise.then((res) => res.ok) return promise } #hatenaintern

Slide 80

Slide 80 text

Overloads ˝ 㓹儖ע湾ׂ傴ׂס؅✳זיֽׄף荁ַך׌ type f = (x: number) => number ˝ ⺱喋ס׆כ؅׆ס׻ֹמ׵傴ׄ׾ type f = { (x: number): number } Overloads type func = { (x: number): number (x: string): string } #hatenaintern

Slide 81

Slide 81 text

React ( min) #hatenaintern

Slide 82

Slide 82 text

React React View React https://ja.reactjs.org/ #hatenaintern

Slide 83

Slide 83 text

ْؕ٭ة׊יײ׾ TODO #hatenaintern

Slide 84

Slide 84 text

JavaScript #hatenaintern

Slide 85

Slide 85 text

JavaScript Ⳃ氳榟䡗סゖ갭憠 UI #hatenaintern

Slide 86

Slide 86 text

React #hatenaintern

Slide 87

Slide 87 text

React UI UI GUI GUI #hatenaintern

Slide 88

Slide 88 text

(Virtual) DOM React DOM DOM DOM React DOM DOM UI key https://ja.reactjs.org/docs/reconciliation.html Document Object Model HTML XML https://zenn.dev/mizchi/books/ c c f cc c b #hatenaintern

Slide 89

Slide 89 text

React #hatenaintern

Slide 90

Slide 90 text

JSX JSX JavaScript

My name is Clementine!

React DOM HTML class className class JavaScript #hatenaintern

Slide 91

Slide 91 text

ؠٚتؤ٤َ٭ؾ٤عכ꞊丗ؤ٤َ٭ؾ٤ع React 2 ؠٚتؤ٤َ٭ؾ٤ع class HelloMessage extends React.Component { render() { return
Hello {this.props.name}
} } ꞊丗ؤ٤َ٭ؾ٤ع const HelloMessage = ({ name }) => { return
Hello {name}
} #hatenaintern

Slide 92

Slide 92 text

ؠٚتؤ٤َ٭ؾ٤عכ꞊丗ؤ٤َ٭ؾ٤ع ؠٚتؤ٤َ٭ؾ٤عע㵧全氳ם䉬塛ֿ◀㲊׈׿יַ׾ג״յ꞊丗ؤ٤َ٭ؾ٤ع؅✳榫׌׾׆כ؅䍚ׂ䫟㝢׊ױ׌ն ؠٚتؤ٤َ٭ؾ٤ع React Error Boundary (Function Component) React Component React Component React Component null Presenter/View React Component Unit Test #hatenaintern

Slide 93

Slide 93 text

Function Component TypeScript TypeScript JSX .tsx () => JSX.Element React.FC type Props = { name: string } const Welcome: React.FC = ({ name }) => { return

Welcome {name}

} React Component undefined #hatenaintern

Slide 94

Slide 94 text

Props State React Component 2 Props State #hatenaintern

Slide 95

Slide 95 text

Props / 1 type Props = { name: string } const Welcome: React.FC = ({ name }) => { return

Welcome {name}

} ( ) JSX //

Welcome John

#hatenaintern

Slide 96

Slide 96 text

React Fragmentמחַי <> > React Fragment React Component 1 Element
2 React Component const Component = () => { return ( <> hello
͜Μʹͪ͸ > ) } key #hatenaintern

Slide 97

Slide 97 text

Function Component Hooks Hooks React . 2019 SFC ( Stateless Functional Component ) #hatenaintern

Slide 98

Slide 98 text

(State) useState use React (Hooks) const Counter = () => { const [count, setCount] = useState(0) const increaseCount = () => setCount((prevCount) => prevCount + 1) return (
Χ΢ϯτ: {count} Χ΢ϯτ
) } #hatenaintern

Slide 99

Slide 99 text

Hooks Rules of Hooks React use if early return ׆׿׼עeslint-plugin-react-hooksך吾⭳׊יׂ׿׾׻ֹמ⭳全׾ #hatenaintern

Slide 100

Slide 100 text

Hooks #hatenaintern

Slide 101

Slide 101 text

useState useState() 1 2 setter ( ) setter Component DOM const [color, setColor] = useState("red") #hatenaintern

Slide 102

Slide 102 text

useState setter ˝ 二׊ַ⡁؅峚׌ const [color, setColor] = useState("red") const change2Blue = () => setColor("blue") ˝ 泡⯥ס⡁؅⮵榫׊י二׊ַ⡁؅婊㲊׌׾ const [count, setCount] = useState(0) const increaseCount = () => setCount((prevCount) => prevCount + 1) #hatenaintern

Slide 103

Slide 103 text

useEffect React Component Hooks DOM DOM props state #hatenaintern

Slide 104

Slide 104 text

Component alert const Counter = () => { const [count, setCount] = useState(0) const increaseCount = () => setCount((prevCount) => prevCount + 1) alert(count) return
{/* ུ */}
} alert OK #hatenaintern

Slide 105

Slide 105 text

useEffectס╈ךalert؅⽛ש const Counter = () => { const [count, setCount] = useState(0) const increaseCount = () => setCount((prevCount) => prevCount + 1) useEffect(() => { alert(count) }) return
{/* ུ */}
} Component Component alert alert alert UI UI Component #hatenaintern

Slide 106

Slide 106 text

useEffectכ❣㰆鿥⮛ 2 ❣㰆؅辐׌鿥⮛؅峚׌ Component useEffect(೚ҙͷॲཧؔ਺, []) state useEffect(೚ҙͷॲཧؔ਺, [state]) state Component 2 alert const [countA, setCountA] = useState(0) const [countB, setCountB] = useState(0) useEffect(() => { alert(`conutAͷ஋͕${countA}ʹߋ৽͞Ε·ͨ͠`) }) useEffect(() => { alert(`conutAͷ஋͕${countB}ʹߋ৽͞Ε·ͨ͠`) }) countA countB #hatenaintern

Slide 107

Slide 107 text

useEffectכ❣㰆鿥⮛ ˝ ❣㰆鿥⮛؅錃㲊׌׾׆כךյא׿ב׿ס❣㰆鿥⮛⫂סַ׍׿־ס⡁ֿ㚺催׈׿גכ׀סײⰜ⛼榫ֿ⽛צ⭳׈׿׾׻ֹמ⭳全׾ const [countA, setCountA] = useState(0) const [countB, setCountB] = useState(0) useEffect(() => { alert(`conutAͷ஋͕${countA}ʹߋ৽͞Ε·ͨ͠`) }, [countA]) useEffect(() => { alert(`conutAͷ஋͕${countB}ʹߋ৽͞Ε·ͨ͠`) }, [countB]) [] Component Component DOM ( ) (mount) DOM (unmount) Hooks #hatenaintern

Slide 108

Slide 108 text

useEffectכؠٛ٭٤ػشو ˝ useEffectע꞊丗؅鲭׌׆כךאס꞊丗ֿ域סⰜ⛼榫ֿ⽛צ⭳׈׿׾⯥מ㲔车׈׿׾ ˝ ׆׿؅⮵榫׌׾כⰜ⛼榫סؠٛ٭٤ػشوֿ⭳全׾ roomIdֿ㚺催׈׿׾כյزٔشعס⹿ַ頇鐆؅⹦׽寕׊յ二׊ַ頇鐆؅ꝧ㡎׌׾❆ useEffect(() => { const handler = () => { /* ৽͍͠ϝοηʔδΛड͚औͬͨͱ͖ͷॲཧ */ } chat.subscribe(roomId, handler) return () => { chat.unsubscribe(roomId) } }, [roomId]) #hatenaintern

Slide 109

Slide 109 text

(Custom Hook) use Hook Hooks Component 1 const useGetStatus = ({ userId }) => { const [status, setStatus] = useState(null) useEffect(() => { const handler = (user) => { setStatus(user.status) } Api.subscribe(userId, handler) return () => Api.unsubscribe(userId, handler) }) return status } #hatenaintern

Slide 110

Slide 110 text

Tips Component useState useMemo useEffect useCallback ( ) useEffect useCallback - uhyo/blog #hatenaintern

Slide 111

Slide 111 text

ֽ檄׿׈ױך׊ג TypeScript React TypeScript React JavaScript #hatenaintern

Slide 112

Slide 112 text

♀ꎰ 儖稴מ⪌׽⮉׼ם־זג馐ײ鱮؆ד遨餉׷鉮鐄מחַי傴 ַיַױ׌ն艄⽏ֵֿ׿ף鐆؆ךׂד׈ַ氳םؤ٭ػ٭ך ׌ն 泘域 Arrow Function useState state Hooks useMemo useCallback React Component DOM JavaScript JavaScript JavaScript ( ) #hatenaintern

Slide 113

Slide 113 text

Arrow Function function (new ) arguments this #hatenaintern

Slide 114

Slide 114 text

Arrow Function this Arrow Function function this #hatenaintern

Slide 115

Slide 115 text

thisסتؤ٭وס鷿ַמחַי ˝ function؅榫ַג꞊丗ס㕙⺬ const person = { name: "chris", say: function () { setTimeout(function () { console.log(`I'm ${this.name}`) }, 100) }, } person.say() // I'm this window.setTimeout(window ) window https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/ setTimeout#thethisproblem #hatenaintern

Slide 116

Slide 116 text

thisסتؤ٭وס鷿ַמחַי Arrow Function const person = { name: "chris", say: function () { setTimeout(() => { console.log(`I'm ${this.name}`) }, 100) }, } person.say() // I'm chris #hatenaintern

Slide 117

Slide 117 text

useState state 二׊ַ⡁؅峚׌כ׀ס蛽כ׊狌 const [count, setCount] = useState(0) const increaseCount = () => setCount(count + 1) כ׊י׊ױֹכյ const increaseDouble = () => { increment() increment() } ס׻ֹם׵ס؅⛼זגכ׀מյincreaseDouble؅⽛؆ך׵1׊־㘃ֻםַכַֹ杯霄מ鸿鷔׌׾ך׊׺ֹն #hatenaintern

Slide 118

Slide 118 text

꞊丗⫂ס㚺丗تؤ٭وכuseState ❆ֻףյcountֿ5ךֵ׾כ׌׾כ const Component = () => { const [count, setCount] = useState(0) // ͜͜Ͱม਺count͸είʔϓ಺Ͱݻఆ͞ΕΔ(5) const increaseCount = () => setCount(count + 1) // ↑Ͱݻఆ͞Εͨcount + 1(=6)ΛsetCountʹ౉͢ const increaseDouble = () => { increment() // ↑Ͱ࡞ͬͨؔ਺ΛݺͿͱɺ6͕setCountʹ౉͞ΕΔ increment() // ͜ͷؔ਺ΛݺͿͱ͖΋ɺ6͕setCountʹ౉͞ΕΔͷͰɺ஋͸6ͷ·· } } #hatenaintern

Slide 119

Slide 119 text

ؤ٭ٜفشؠ꞊丗؅峚׌亠嫎ך傴׀泡׌ ❆ֻףյcountֿ5ךֵ׾כ׌׾כ const Component = () => { const [count, setCount] = useState(0) // ͜͜Ͱม਺count͸είʔϓ಺Ͱݻఆ͞ΕΔ(5) const increaseCount = () => setCount((prevCount) => prevCount + 1) // prevCount͸ݺͼग़࣌͠ͷ௚લͷ஋ const increaseDouble = () => { increment() // ͜͜ͰݺͿͱɺprevCountʹ͸5͕ೖ͍ͬͯΔͷͰɺprevCount+1=6͕setCount͞ΕΔ increment() // ͜͜ͰݺͿͱɺprevCountʹ͸6͕ೖ͍ͬͯΔͷͰɺprevCount+1=7͕setCount͞ΕΔ } } state #hatenaintern

Slide 120

Slide 120 text

Hooks === Object.is const a = "foo" const b = "foo" console.log(a === b) // true const objA = { a: "foo", b: 10 } const objB = { a: "foo", b: 10 } console.log(objA === objB) // true console.log(Object.is(objA, objB)) // false #hatenaintern

Slide 121

Slide 121 text

❣㰆鿥⮛מ؛هةؘؠع؅⪌׿׾آ٭تמחַי const config = { theme: "sports" } useEffect(() => { loadConfig(config).then(() => {}) }, [config]) config [config.theme] #hatenaintern

Slide 122

Slide 122 text

ب٤وٜם㍑鹴瓀 Component const config = { theme: "sports" } function Component() { useEffect(() => { loadConfig(config).then(() => {}) }, [config]) } Props #hatenaintern

Slide 123

Slide 123 text

useMemo useMemo React Hooks 1 Component function WordCount({ children }) { // text͸stringͳͷͰɺͦͷ··ґଘ഑ྻʹग़དྷΔ const words = useMemo(() => children.split(" "), [text]) useEffect(() => { alert(`୯ޠ਺͸${words.length}Ͱ͢`) }, [words]) } Component children Lorem ipsum dolor sit amet #hatenaintern

Slide 124

Slide 124 text

useCallbackך꞊丗؅ْٓ⴫׌׾ ˝ ⡁⺱喋מ꞊丗؅ْٓ⴫׊גַ㕙⺬עuseCallback؅⮵榫׌׾ ˝ ْٓ⴫׊םַכ夵ٝ٤رٛ٤ء侇מ꞊丗؛هةؘؠعֿ榟䡗 ׈׿י׊ױֹ const handler = useCallback((val) => alert(val), []) useEffect(() => { Api.notification.subscribe(handler) }, [handler]) #hatenaintern

Slide 125

Slide 125 text

useMemo׷useCallback؅榫ַגقنؚ٭ُ٤ ت䷉ャ ˝ useMemo׷useCallbackע⡁׷꞊丗סْٓ⴫מ׻זיuseEffectםלס┘釐ם⽛צ⭳׊؅䤰⯆׌׾׆כמ׻זיقنؚ٭ُ٤ت ס䷉ャ؅僿䏨ך׀׾ ˝ 攐מuseMemoךע❣㰆מ✳؂םַ㕙⺬ך׵յ⭚杼סꄆַ銶畀磵冽؅ْٓ⴫׌׾׆כךٝ٤رٛ٤ء侇סهٞشؠ؅䤰ֻ׾׆כ ׵⭳全׾ function Component ({a, b}) => { const resultA = useMemo(() => superDuperHighCostCalculation(a), [a]); const resultB = useMemo(() => superDuperHighCostCalculation(b), [b]); return <> {a}͔ΒʮΊͪΌͪ͘Όॏ͍ܭࢉʯΛͨ݁͠Ռ: {resultA} {b}͔ΒʮΊͪΌͪ͘Όॏ͍ܭࢉʯΛͨ݁͠Ռ: {resultB} > } #hatenaintern

Slide 126

Slide 126 text

React Component DOM React ref useRef ref current const textInput = useRef(null) const submit = (e) => { e.preventDefault() if (textInput.current.value.length < 100) return alert("101จࣈҎ্͕ඞཁͰ͢") createPost({ body: textInput.current.value }) } return ( ) #hatenaintern

Slide 127

Slide 127 text

DOM DOM React const [text, setText] = useState("") const submit = (e) => { e.preventDefault() if (text < 100) return alert("101จࣈҎ্͕ඞཁͰ͢") createPost({ body: text }) } return ( setText(e.target.value)} /> ) #hatenaintern

Slide 128

Slide 128 text

JavaScript TypeScript/JavaScript #hatenaintern

Slide 129

Slide 129 text

TypeScript TypeScript JavaScript tsc babel JavaScript JavaScript API babel poly ll TS JS babel JavaScript JavaScript webpack JavaScript (bundle) ES Modules 1 JavaScript JavaScript(+sourcemap) minify TS/JS sourcemap 1 webpack Terser TreeShaking #hatenaintern

Slide 130

Slide 130 text

webpack TypeScript JavaScript babel(babel-loader ) webpack Terser(webpack-terser-plugin ) #hatenaintern

Slide 131

Slide 131 text

create-react-app React OK webpack, babel, eslint npm start npm test react-scripts create-react-app React create-react-app React #hatenaintern

Slide 132

Slide 132 text

JavaScript ( ) JavaScript DOM HTML CSS API ECMAScript WHATWG HTML Living Standard WHATWG DOM Living Standard W C CSS Speci cations #hatenaintern

Slide 133

Slide 133 text

ם׏☼喋؅湳׾ס־ API JavaScript CSS - #hatenaintern

Slide 134

Slide 134 text

ECMAScript JavaScript ECMAScript Ecma International Technical Committee TC https://github.com/tc /ecma Living Standard 6 ECMAScript babel tsc poly ll Ecma International C# #hatenaintern

Slide 135

Slide 135 text

ECMAScript Stage ECMAScript (proposal) Github proposal issue PR TC Stage ⾒ Issue Stage ECMAScript #hatenaintern

Slide 136

Slide 136 text

Stage 2 ECMAScript · JavaScript Primer #jsprimer Stage pre x API 2 JavaScript Google Chrome Node.js V Safari JavaScriptCore Firefox SpiderMonkey Facebook Hermes #hatenaintern

Slide 137

Slide 137 text

ECMAScript Stage ECMAScript core-js poly ll babel ECMAScript Open Open JavaScript ECMAScript #hatenaintern

Slide 138

Slide 138 text

JavaScript ECMAScript JavaScript ECMAScript location.assign WHATWG HTML Living Standard document.querySelector WHATWG DOM Living Standard WHATWG HTML/DOM Living Standard ECMAScript HTML DOM (Node.js ) W C HTML HTML . 399 5 WHATWG 2021 1 29 WHATWG Living Standard W C / : [https://future-architect.github.io/articles/ a/ HTML | ] 2004 Apple Mozilla Opera 3 W C HTML Living Standard #hatenaintern

Slide 139

Slide 139 text

WHATWG Google Chrome HTML DOM API Google Chrome Apple Moziila Chrome : Chrome Platform Status Mozilla : Mozilla Speci cation Positions W C Web Incubator Community Group https://scrapbox.io/pastak-pub/ WebAPI #hatenaintern

Slide 140

Slide 140 text

W C CSS Speci cations CSS CSS WHATWG W C All CSS speci cations #hatenaintern