Upgrade to PRO for Only $50/YearâLimited-Time Offer! ð¥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Unlocking new capabilities for PWA
Search
Takepepe
February 01, 2020
Technology
2
2.8k
Unlocking new capabilities for PWA
PWA Night CONFERENCE 2020
https://conf2020.pwanight.jp/speaker/takepepe/
Takepepe
February 01, 2020
Tweet
Share
More Decks by Takepepe
See All by Takepepe
ã©ã®æ§ã«AIãšãŒãžã§ã³ããš åæ¥ãã¹ãã ã£ãã®ãïŒ
takefumiyoshii
2
820
ServerAction ã§ Progressive Enhancement ã¯ã©ããŸã§é 匵ãããïŒ / progressive-enhancement-with-server-action
takefumiyoshii
7
1.2k
App Router ãžã®ç§»è¡ã¯ãæ¹åããšãªãåŸãã®ãïŒ/ Can migration to App Router be an improvement
takefumiyoshii
8
3.7k
ããã³ããšã³ããã®æžããžããããã£ããã¹ããæžããªããŠããã£ããã¹ã
takefumiyoshii
40
17k
Webããã³ããšã³ãã®ããã®å®è·µããã¹ããææ³ CodeZine Night #1
takefumiyoshii
24
9.2k
Next.js ã§ãªã¢ãŒããã¯ããã話 / story-of-re-architect-with-nextjs
takefumiyoshii
12
9k
ããéã WEB ãç®æã Next.js / nextjs-make-the-web-faster
takefumiyoshii
54
20k
ããã³ããšã³ããã®è€éãã«èããããå®è·µããããš / readyfor-nextjs-first
takefumiyoshii
25
11k
Redux ã®å©ç¹ãæ¯ãè¿ã
takefumiyoshii
26
8.9k
Other Decks in Technology
See All in Technology
useEffectã£ãŠãªãã§éæšå¥šã¿ãããªããšèšãããŠãã®ïŒ
maguroalternative
9
6.1k
äžåç·æ¥åæ¹åãæ¯ãã瀟å AIãšãŒãžã§ã³ãåºç€ã®èŠè«Š
yukukotani
9
2.7k
ããŒãžã®å¯èŠé åãç®åºããæ¹æ³ã«ã€ããŠæŽçãã
yamatai1212
0
160
ãªãŒãã³ããŒã¿ã®å 補åããåãã£ãGISããŒã¿ãå·¡ãè¡æ¿ã®èª²é¡
naokim84
2
1.3k
MySQL AIãšMySQL Studioã䜿ã£ãŠã¿ãã
ikomachi226
0
130
ãã©ãŠã¶æ¡åŒµã®ã»ãã¥ãªãã£ã®è©± / Browser Extension Security
flatt_security
0
250
NoãäŒããæè¡2025: çéåæåœ¢æã®ããã®NICOãã¬ãŒã ã¯ãŒã¯éç¿ #pmconf2025
aki_iinuma
1
110
iRAFTæ³-ä»ç€ŸäºäŸã"èªç€Ÿä»æ§å"ããæè¡ #pmconf2025
daichi_yamashita
0
200
ã»ãã¥ãªãã£AIãšãŒãžã§ã³ãã®çŸåšãšæªæ¥ / PSS #2 Takumi Session
flatt_security
3
1.3k
Eight Engineering Unit 玹ä»è³æ
sansan33
PRO
0
5.7k
[ç¶ã»å¶æ¥åã 誰ã§ã話ããOCI ã»ãŒã«ã¹ããŒã¯] AWSããOCIã®åªäœæ§ãåãããªãç·š(2025幎11æ21æ¥éå¬)
oracle4engineer
PRO
1
220
ç§ãæèŠªäŒã¯èŠæã§ãã ïœèŠæã ããããæèŠªäŒã楜ããæ¹æ³ïœ / 20251127 Masaki Okuda
shift_evolve
PRO
4
540
Featured
See All Featured
Building Flexible Design Systems
yeseniaperezcruz
329
39k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.6k
Whatâs in a name? Adding method to the madness
productmarketing
PRO
24
3.8k
Designing for humans not robots
tammielis
254
26k
Site-Speed That Sticks
csswizardry
13
980
BBQ
matthewcrist
89
9.9k
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
140
34k
Visualization
eitanlees
150
16k
Code Review Best Practice
trishagee
73
19k
Writing Fast Ruby
sferik
630
62k
Transcript
Unlocking new capabilities for PWA PWA Night CONFERENCE 2020 @Takepepe
About Me ⪠Takefumi Yoshii / @Takepepe ⪠DeNA /
DeSC Healthcare ⪠Frontend Developer ⪠TypeScript Meetup JP member 2
Agenda ⪠1. PWA ã Web App ã§å©çšå¯èœãªãå®éšçæ©èœã«ã€ã㊠⪠2.
ãšããå®éšçæ©èœ ãå©çšããŠã¢ããªãäœã£ã話 ⪠3. ãšããå®éšçæ©èœ ã® API æŠèŠ âª 4. API åãæ±ããã€ã³ãã»React Redux ã«çµ±åãã話 3
1. Web Experimental Features
1-1. Bridging the NativeApp Gap ServiceWorker ã®ãã£ãã·ã¥æŠç¥ã«ããã PWA ã®ã¿ãªãããWebãã©ãŠãžã³ã°ã« å¿«é©ãª
UX ãããããããŠããŸãã 1. Web Experimental Features
1-1. Bridging the NativeApp Gap 1. Web Experimental Features ãã®å¿«é©ãªã¬ã¹ãã³ã¹ããã
Web ã¢ããªã±ãŒã·ã§ã³éçºæè¡ã§ã Native ã¢ããªãšåçæ©èœãæäŸããããšã«ã å€ãã®æåŸ ãå¯ããããŠããŸãã
1-1. Bridging the NativeApp Gap 1. Web Experimental Features ããããWeb
ãã©ãŠã¶ã«èš±å®¹ãããŠãã æ©èœã¯éå®çã§ãã端æ«åºæã®æ©èœã« ã¢ã¯ã»ã¹ãã Low-Level API ã®å€ãã¯ã JavaScript ã«ã¯è§£æŸãããŠããŸããã
1-1. Bridging the NativeApp Gap 1. Web Experimental Features ãã®ç¶æ³ãåé²ããã¹ãã
Google Chrome ã§ã¯ Low-Level API ãžã®æ©æž¡ãã ç©æ¥µçã«è¡ãªã£ãŠããŸãã Experimental FeaturesïŒå®éšçæ©èœïŒ ã«ã¯ããããªæ©èœã倿°æ§ããŠããŸãã
1-2. Origin Trial 1. Web Experimental Features chrome://flags ã§å®éšçæ©èœãæå¹ã«ããã°ã ãã®æ©èœã詊ãããšãã§ããŸãã
ãããŠãå®éšçæ©èœãæéä»ãã»ãã¡ã€ã³å¶éã§ æäŸãããOrigin TrialãããããŸãã https://developers.chrome.com/origintrials
1-2. Origin Trial 1. Web Experimental Features æšå¹Ž 5æã«éå¬ããããGoogle I/Oã
æšå¹Ž 11æã«éå¬ããããChrome Dev Summitãã§ã ãã®ãOrigin Trialãã«ã€ããŠç޹ä»ããããŸããã å¯èœæ§ã®åºããã«ãæåŸ ãé«ãŸããŸããïŒ
1-2. Origin Trial 1. Web Experimental Features 仿¥ã玹ä»ããã®ã¯ã çŸåšã®ç§ãã¡ã®ç掻ã«ã¯æ¬ ããããšã®ã§ããªã ãã®æè¡ã«ã€ããŠã§ãã
æãçŽè¿ã«è§£æŸããã API ã§ããããŸãã
Web NFC
2. Devlop Trial
2-1. Web NFC Media MEMO Web NFC ã®ãã©ã€ã¢ã«ãšããŠã ãã¢ã¢ããªãäœæããŸããã æ¬¡ã®æ€èšŒç°å¢ã§åäœç¢ºèªãããŠããŸãã
⪠Pixel 3aã⪠Android 9 ⪠Google Chrome Canary v81 2. Devlop Trial https://vimeo.com/388157513
2-1. Web NFC Media MEMO ãã¢ã¢ããªã¯é ä¿¡ãããŠããŸãã®ã§ã NFC æ©èœä»ã Android ããæã¡ã®æ¹ã¯
詊ããŠããã ãããšå¬ããã§ãã github ã«ã³ãŒããå ¬éããŠããŸãã https://webnfc-media-memo.netlify.com/ https://github.com/takefumi-yoshii/webnfc-media-memo 2. Devlop Trial
2-1. Web NFC Media MEMO ãã®ã¢ããªãèµ·åããŠããæã 端æ«ã§æ€åºããã NFC Tag ã®åŠçã¯
ãã©ã¢ã°ã©ãŠã³ãã®ãã©ãŠã¶ã«å§ããããŸãã 2. Devlop Trial
2-1. Web NFC Media MEMO 2. Devlop Trial ããã¹ãã¡ã¢æ©èœãå©çšã㊠NFC
Tag ã«æžã蟌ãã ããã¹ãã¯ã NFC Tag ã«æ°žç¶åãããŸãã
2-1. Web NFC Media MEMO 2. Devlop Trial ããã¹ããªãŒããŒç»é¢ã§ã¿ãããããšã æžã蟌ãã æååã衚瀺ãããŸãã
2byte æåãå¯èœã§ãã
2-1. Web NFC Media MEMO 2. Devlop Trial é³å£°ã¡ã¢æ©èœã¯ã é²é³ããåŸã«
NFC Tag ã«ã¿ãããããšã ä¿åããããšãã§ããŸãã
2-1. Web NFC Media MEMO ãããŠãä¿åæžã¿ã® NFC Tag ã«ã¿ãããããšã ã¢ããªäžã§é³å£°ã¡ã¢ãèªååçããŸãã
2. Devlop Trial
2-1. Web NFC Media MEMO åç»ããŒã¿ãé²ç»ã»åçãå¯èœã§ãã ä»ã®ãšãããé²ç»ã®å°ºã¯èšããŠããŸããã 2. Devlop Trial
2-1. Web NFC Media MEMO NFC Tag ã«ã¯ãã®ä»ã«ãã æ§ã ãªããŒã¿ã®ä¿åãå¯èœã§ãã ïŒãŠãœã§ãïŒçš®æããã¯æåŸã«ïŒ
2. Devlop Trial
2-2. Prepare
2-2. Prepare 2. Devlop Trial äžçªæ©ã API ã詊ãããšãåºæ¥ãæ¹æ³ã玹ä»ããŸãã NFC æ©èœãæèŒããã
Android端æ«ã«ã Google Chrome Canary ãã€ã³ã¹ããŒã«ã chrome://flags ã URL ããŒã«å ¥åãã Web-NFC ãæå¹ã«ããŸãã ïŒç«¯æ«ã® NFCæ©èœãæå¹ã«ããããšãå¿ããã«ïŒ
2-2. Prepare 2. Devlop Trial localhost ã§æåã確èªããããã ãã® Android 端æ«ã
PC ã«æ¥ç¶ããŸãã PC ã® Google Chrome ãèµ·åãã More tools > Remote devices ããã æ¥ç¶ããŠãã該åœç«¯æ«ãéžæã
2-2. Prepare 2. Devlop Trial Port forwarding ã«ãéçºãµãŒããŒã® localhost ãæå®ã
ã¢ãã€ã«ç«¯æ«ã® Developer Console ã«ã¢ã¯ã»ã¹ããŸãã
2-2. Prepare Developer Console ãããWeb NFC ãå©çšå¯èœãã確èªããŸãã å®çŸ©ãååšããã°ãWeb NFC ã詊ãç°å¢ãæŽããŸããã
2. Devlop Trial if ('NDEFReader' in window) { /* ... Scan NDEF Tags */ } if ('NDEFWriter' in window) { /* ... Write NDEF Tags */ }
3. API Overview
3-1. About NFC Tag
3-1. About NFC Tag API 詳现ã®è©±ã®åã«ã NFC Tag ã«ã€ããŠå°ã玹ä»ããŸãã NFC
Tag ã«ã¯æ§ã ãªçš®é¡ããããŸãã 3. API Overview
3-1. About NFC Tag Suica / Edy ãªã©ã«å°é ããé»åãããŒã¯ã NFC-FïŒType-FïŒã«ããããŸãã ããŒã¿ç®¡çãã»ãã¥ãªãã£æ©èœã
匷åãããŠãããã®ã§ãã 3. API Overview
3-1. About NFC Tag NFC-F ã«ã€ããŠã¯ãä»å調ã¹ããªãã§ã¯ã Web NFC ã§èªã¿æžãã¯ã§ããŸããã§ããã ïŒãã ã
æ€åºã¯å¯èœïŒ 3. API Overview
3-1. About NFC Tag Origin Trials ã® description ãåŒçšããŸãã Low-level
I/O operation ãªã©ã¯ãå¯Ÿå¿æªå®ãšã®ããšã 3. API Overview Low-level I/O operations (e.g. ISO-DEP, NFC-A/B, NFC-F) and Host-based Card Emulation (HCE) are not supported within the current scope.
3-1. About NFC Tag çŸç¶è©Šãããšãã§ãã API ã¯éå®çã§ããã NFC Tag ãéžã¹ã°ããã¢ã¢ããªã®æ§ãªããšãå¯èœã§ãã
3. API Overview Low-level I/O operations (e.g. ISO-DEP, NFC-A/B, NFC-F) and Host-based Card Emulation (HCE) are not supported within the current scope.
3-1. About NFC Tag ãã¢ã¢ããªã§å©çšæ³å®ããŠããã®ã¯ã NFC-AïŒType-AïŒã®ãã®ã§ãã ããã§ããã°ãWeb NFCãã§ã èªã¿æžããããããšãå¯èœã§ãã ã«ãŒãã¿ã€ãã»ã·ãŒã«ã¿ã€ããªã©ããããŸãã
3. API Overview äŸïŒã«ãŒãã¿ã€ã / Â¥600 / 12æãã·ãŒã«ã¿ã€ã / Â¥790 / 11æïŒ
3-1. About NFC Tag NPX 瀟ã®ãNTAG 215 ãããïŒNFC-A ïŒã ãæ¡çšããã
NFC Tag ã¯å€ãæµéããŠããã å®äŸ¡ã«å ¥æããããšãã§ããŸãã 3. API Overview äŸïŒã«ãŒãã¿ã€ã / Â¥600 / 12æãã·ãŒã«ã¿ã€ã / Â¥790 / 11æïŒ
3-1. About NFC Tag 圢ã ãã§ãªãã容éãæ§ã ãªãã®ããããŸãã ãããªã«å€§å®¹éã§ã¯ãããŸããã NTAG 213: 144Byte NTAG
215: 504Byte NTAG 216: 888Byte 3. API Overview äŸïŒã«ãŒãã¿ã€ã / Â¥600 / 12æãã·ãŒã«ã¿ã€ã / Â¥790 / 11æïŒ
3-1. About NFC Tag èªã¿èŸŒã¿å¯èœãª NFC Tag ã®ä»æ§ã«ã€ããŠã ããè©³çŽ°ãªæ å ±ã¯ä»¥äžãåç §ããŸãããã https://w3c.github.io/web-nfc/#x4-1-ndef-compatible-tag-types
3. API Overview
3-2. NDEFReader
3-2. NDEFReader ç°¡åãªèªã¿èŸŒã¿äŸã確èªããŠãããŸãããã 3. API Overview const reader = new
NDEFReader() reader.scan().then(() => { console.log("Scan started successfully.") reader.onreading = event => { console.log(`NDEF message read.${event.serialNumber}`) } }).catch(error => { console.log(`Error! Scan failed to start: ${error}.`) })
NDEFReader ã NFC èªã¿èŸŒã¿ã«å¿ èŠãªã€ã³ã¹ã¿ã³ã¹ã§ãã scan 颿°ã¯ Promise ãè¿ããŸãã 3-2. NDEFReader
3. API Overview const reader = new NDEFReader() reader.scan().then(() => { console.log("Scan started successfully.") reader.onreading = event => { console.log(`NDEF message read.${event.serialNumber}`) } }).catch(error => { console.log(`Error! Scan failed to start: ${error}.`) })
3-2. NDEFReader onreading ãã³ãã©ã® callback 㯠NDEFReadingEvent ãåãåããŸãã 3. API
Overview const reader = new NDEFReader() reader.scan().then(() => { console.log("Scan started successfully.") reader.onreading = event => { console.log(`NDEF message read.${event.serialNumber}`) } }).catch(error => { console.log(`Error! Scan failed to start: ${error}.`) })
3-2. NDEFReader serialNumber ã¯ãç©çã¿ã°åºè·æã« ä»äžãããŠããäžæã® ID ã§ãã 3. API Overview
const reader = new NDEFReader() reader.scan().then(() => { console.log("Scan started successfully.") reader.onreading = event => { console.log(`NDEF message read.${event.serialNumber}`) } }).catch(error => { console.log(`Error! Scan failed to start: ${error}.`) })
3-2. NDEFReader serialNumber ãå€å¥ããããšã§ ãäžæã® NFC Tag ãèªã¿èŸŒãã ãããšãå€å¥ããããšãã§ããŸãã 3. API
Overview const reader = new NDEFReader() reader.scan().then(() => { console.log("Scan started successfully.") reader.onreading = event => { console.log(`NDEF message read.${event.serialNumber}`) } }).catch(error => { console.log(`Error! Scan failed to start: ${error}.`) })
3-3. NDEFWriter
3-3. NDEFWriter æžã蟌ã¿ãããã£ãŠç°¡åã§ãã æååã NFC Tag ã«æžã蟌ãã§ã¿ãŸãã 3. API Overview
const writer = new NDEFWriter() writer.write("Hello World").then(() => { console.log("Message written.") }).catch(error => { console.log(`Write failed :-( try again: ${error}.`) })
3-3. NDEFWriter æžã蟌ã¿ã«ã¯ã æååãæž¡ãã ãã®æ¹æ³ããããŸãã 3. API Overview const writer =
new NDEFWriter() writer.write("Hello World").then(() => { console.log("Message written.") }).catch(error => { console.log(`Write failed :-( try again: ${error}.`) })
3-3. NDEFWriter ãã¡ãã®æ»ãå€ã Promise ã§ãã NFC Tag ãæ€åºãããã¿ã€ãã³ã°ã§ãæžã蟌ã¿ã詊ã¿ãŸãã 3. API
Overview const writer = new NDEFWriter() writer.write("Hello World").then(() => { console.log("Message written.") }).catch(error => { console.log(`Write failed :-( try again: ${error}.`) })
3-3. NDEFWriter æžã蟌ãã®ã¯æååã®ä»ã«ã NDEFMessage ãªããžã§ã¯ããæå®ããæ¹æ³ããããŸãã 3. API Overview const message:
NDEFMessage = { records: [{ recordType: "url", data: "https://w3c.github.io/web-nfc/" }] } const writer = new NDEFWriter() writer.write(message).then(() => { console.log("Message written.") }).catch(_ => { console.log("Write failed :-( try again.") })
3-3. NDEFWriter æžã蟌ãã®ã¯æååã®ä»ã«ã NDEFMessage ãªããžã§ã¯ããæå®ããæ¹æ³ããããŸãã 3. API Overview const message:
NDEFMessage = { records: [{ recordType: "url", data: "https://w3c.github.io/web-nfc/" }] } const writer = new NDEFWriter() writer.write(message).then(() => { console.log("Message written.") }).catch(_ => { console.log("Write failed :-( try again.") })
3-4. NDEFMessage
3-4. NDEFMessage NFC Tag ã®èªã¿èŸŒã¿æã«ããNDEFMessage ãåãåããŸãã ãã®å 容ãèªã¿åã£ãŠã¿ãŸãã 3. API Overview
function consoleNDEFRecords(message: NDEFMEssage) { if (message.records.length === 0) return message.records.map(record => { const decoder = new TextDecoder() console.log(`Text: ${decoder.decode(record.data)}`) }) }
3-4. NDEFMessage NFC Tag ã«æžã蟌ãŸããæååã¯ãçŽæ¥èªã¿åãããšãã§ããŸããã TextDecoder ã€ã³ã¹ã¿ã³ã¹ãå©çšãããã³ãŒããããå¿ èŠããããŸãã 3. API Overview
function consoleNDEFRecords(message: NDEFMEssage) { if (message.records.length === 0) return message.records.map(record => { const decoder = new TextDecoder() console.log(`Text: ${decoder.decode(record.data)}`) }) }
3-4. NDEFMessage 1byteæååã§ããã°ããã®ãŸãŸã§ãåé¡ãããŸãããã 2byteæåãå«ãæååã®å Žåãencoding ã®æå®ãå¿ èŠã§ãã 3. API Overview function consoleNDEFRecords(message:
NDEFMEssage) { if (message.records.length === 0) return message.records.map(record => { const decoder = new TextDecoder(record.encoding) console.log(`Text: ${decoder.decode(record.data)}`) }) }
3-4. NDEFMessage ãã®æ§ã«ãNFC-A ã® NFC Tag ã§ããã°ã ç°¡åã«èªã¿æžãå¯èœã§ããããšãããããŸãã 3. API
Overview function consoleNDEFRecords(message: NDEFMEssage) { if (message.records.length === 0) return message.records.map(record => { const decoder = new TextDecoder(record.encoding) console.log(`Text: ${decoder.decode(record.data)}`) }) }
3-5. NDEFRecord
3-5. NDEFRecord NDEFRecord ã«ã€ããŠãããå°ã詳ããã¿ãŠãããŸãããã Web IDL interface ã¯ã€ãã®æ§ã«å®çŸ©ãããŠããŸãã 3. API
Overview interface NDEFRecord { constructor(NDEFRecordInit recordInit) readonly attribute USVString recordType readonly attribute USVString? mediaType readonly attribute USVString? id readonly attribute DataView? data readonly attribute USVString? encoding readonly attribute USVString? lang sequence<NDEFRecord>? toRecords() }
3-5. NDEFRecord NDEFRecord ã®ãªãã§å¿ é ããããã£ã§ããã®ã¯ãrecordType ã§ãã NDEFRecord ã®è§£æã¯ããã確èªãããšããããå§ãŸããŸãã 3. API Overview
interface NDEFRecord { constructor(NDEFRecordInit recordInit) readonly attribute USVString recordType readonly attribute USVString? mediaType readonly attribute USVString? id readonly attribute DataView? data readonly attribute USVString? encoding readonly attribute USVString? lang sequence<NDEFRecord>? toRecords() }
3-5. NDEFRecord recordType ã¯ä»»æã®æååãš ããããšãã§ããŸããã Well-known type records ãšããŠåãæ±ºããããŠãã ã®ã¯æ¬¡ã®3çš®é¡ã§ãã
⪠text ⪠url ⪠smart-poster 3. API Overview
3-5. NDEFRecord recordType: "url" ã® record ã ä¿æãã NFC Tag
ãæ€åºãã 端æ«ã¯ãäœãã¢ããªã±ãŒã·ã§ã³ ãèµ·åããŠããªãå Žåã ãã©ãŠã¶ã®èµ·åãä¿ããŸãã 3. API Overview
3-5. NDEFRecord ãã®ãããWeb NFC ãå©çšã recordType: "url" ãæå®ãã NDEFRecord ãæžã蟌ãã°ã
ä»»æã® NFC Tag ã ãã©ãŠã¶ã©ã³ãã£ãŒãš ããããšãã§ããŸãã 3. API Overview
3-5. NDEFRecord recordType ã« ã¢ããªã±ãŒã·ã§ã³ç¹æã® æ¥é èŸãä»äžããæ€åºãã ã¿ã°ã®åŠçãçµã蟌ãäŸã 玹ä»ãããŠããŸãã ⪠https://w3c.github.io/web-nfc/
3. API Overview
4. Handling APIs in App
4-1. Permission Request
4-1. Permission Request Web NFC ã䜿ãã¢ããªã¯ã äœãããã¯ããã«ããŒããã·ã§ã³ã åŸãå¿ èŠããããŸãã 4. Handling
APIs in App const reader = new NDEFReader() await reader.scan()
4-1. Permission Request 泚æããªããã°ãããªãã®ã¯ã ããŒãžããŒããšåæã« API ãã³ãŒã«ããªãããšã§ãã 4. Handling APIs
in App const reader = new NDEFReader() await reader.scan()
4-1. Permission Request ãã®ã¿ã€ãã³ã°ã§ã³ãŒã«ãããšã ããŒããã·ã§ã³ã»ããã³ããã 衚瀺ãããŸããã 4. Handling APIs in
App const reader = new NDEFReader() await reader.scan()
4-1. Permission Request ããŒããã·ã§ã³ã»ããã³ããã 衚瀺ããããããæŒäžã³ãŒã«ããã¯ã§ API ãã³ãŒã«ããèšèšã«ããŸãããã 4. Handling APIs
in App const reader = new NDEFReader() await reader.scan()
4-1. Permission Request ãããŠãNDEFReader ã€ã³ã¹ã¿ã³ã¹ã è§£æŸããªãçæãå¿ èŠã§ããscan ãå®è¡ ãããŠããªããšãå¥ã¢ããªãæ€åºã«åå¿ãã ãã©ã¢ã°ã©ãŠã³ãã奪ãããŠããŸããŸãã 4.
Handling APIs in App const reader = new NDEFReader() await reader.scan()
4-1. Permission Request ãããã端æ«èšå®ã§ãNFC æ©èœãžã® ã¢ã¯ã»ã¹ãæåŠããŠããå ŽåããããŸãã ãããã®èæ ®ãšäœµããå©çšã§ããªãã±ãŒã¹ã ãŠãŒã¶ãŒã«æç€ºããŸãããã 4. Handling
APIs in App const reader = new NDEFReader() await reader.scan()
4-2. Permission Handling
4-2. Permission Handling ãµã³ãã«ã¢ããªã§ã¯ ã«ã¡ã©ã»ãã€ã¯ãå©çšããŠããã ãã¡ããããŒããã·ã§ã³ãå¿ èŠã«ãªããŸãã äžèšé¢æ°ãå©çšããããšã§ MediaStream ãç«ã¡äžãããŸããã ãã«ã¡ã©ã»ãã€ã¯ãã®ããŒããã·ã§ã³ããã³ãããåæã«è¡šç€ºãããŸãã
4. Handling APIs in App function getUserMedia(constraints: MediaStreamConstraints) { return navigator.mediaDevices.getUserMedia(constraints) }
4-2. Permission Handling 4. Handling APIs in App ã¢ã¯ã»ã¹æš©éç¶æ ã®èå¥ã¯éèŠã§ãã äžåºŠã§ãæ©èœãžã®ã¢ã¯ã»ã¹ããããã¯ãããšã
ãã以éããã®æ©èœã«ã¢ã¯ã»ã¹ããããšãã§ããŸããã ïŒèšå®è§£é€ãžã®èªå°ãå¿ èŠïŒ function getUserMedia(constraints: MediaStreamConstraints) { return navigator.mediaDevices.getUserMedia(constraints) }
4-2. Permission Handling ãµã³ãã«ã¢ããªã§ã¯ãPermission API ãå©çšãã Origin ã®æš©éç¶æ ãååŸããŠããŸãã ãããã¯ãããŠããç¶æ³ãªã©ãææ¡ããããã«ã Permission
API ã¯æå¹ã§ãã 4. Handling APIs in App const status = await navigator.permissions.query({ name: 'nfc' }) console.log(status.state) // "granted" | "denied" | "prompt" status.onchange = () => { // dosomething ex:) re render view }
4-2. Permission Handling ãµã³ãã«ã¢ããªã§ã¯ãPermission API ãå©çšãã Origin ã®æš©éç¶æ ãååŸããŠããŸãã ãããã¯ãããŠããç¶æ³ãªã©ãææ¡ããããã«ã Permission
API ã¯æå¹ã§ãã 4. Handling APIs in App const status = await navigator.permissions.query({ name: 'nfc' }) console.log(status.state) // "granted" | "denied" | "prompt" status.onchange = () => { // dosomething ex:) re render view }
4-2. Permission Handling query 颿°ã§ç¶æ ãç¥ãæ¹æ³ãšåãæ§ã«ã request 颿°ã§ããŒããã·ã§ã³ã»ããã³ããã衚瀺ããããšãã§ããŸãã ããããããã©ãŠã¶ã«ãã£ãŠãµããŒãç¶æ³ããŸã¡ãŸã¡ãªã®ã§ å©çšããåã«ç¢ºèªããŸãããã 4.
Handling APIs in App const status = await navigator.permissions.query({ name: 'nfc' }) console.log(status.state) // "granted" | "denied" | "prompt" status.onchange = () => { // dosomething ex:) re render view }
4-2. Permission Handling æš©éç¶æ³ããŠãŒã¶ãŒã«ç¥ããã View ããããšèŠªåã§ãã æš©é倿Žãããæã«çºç«ããããã³ãã©ãæå®ã§ããŸãã Native API ã®å€ãã¯ãPermission
ãæ±ãããã®ãå€ãã§ãã å©çšããã¢ããªã±ãŒã·ã§ã³ã§ã¯ãæåããµããŒãããŠãããŸãããã 4. Handling APIs in App const status = await navigator.permissions.query({ name: 'nfc' }) console.log(status.state) // "granted" | "denied" | "prompt" status.onchange = () => { // dosomething ex:) re render view }
4-3. Media Recorder
4-3. Media Recorder 4. Handling APIs in App ã¡ãã£ã¢ã®èšé²ã¯ãMediaRecorder ãå©çšããŠããŸãã
é²é³ã»é²ç»ããšãŠãç°¡åã«å®çŸã§ããŸãã const mediaRecorder = new MediaRecorder(stream, options) mediaRecorder.onstart = () => { console.log('start rec') } mediaRecorder.onstop = () => { console.log('stop rec') } mediaRecorder.ondataavailable = event => { console.log('data available') }
4-3. Media Recorder ã¡ãã£ã¢ã®èšé²ã«å¿ èŠãª MediaStream ãç«ã¡äžããåŸã«ã MediaRecorder ã€ã³ã¹ã¿ã³ã¹ãçæããŸãã 4. Handling
APIs in App const mediaRecorder = new MediaRecorder(stream, options) mediaRecorder.onstart = () => { console.log('start rec') } mediaRecorder.onstop = () => { console.log('stop rec') } mediaRecorder.ondataavailable = event => { console.log('data available') }
4-3. Media Recorder ãondataavailableããã³ãã©ã§ã¯ãé²ç»ããŒã¿ãåãåãããšãã§ããŸãã ãã®é²ç»ããŒã¿ããä»»æã®æ¹æ³ã§ä¿åããŸãã 4. Handling APIs in App
const mediaRecorder = new MediaRecorder(stream, options) mediaRecorder.onstart = () => { console.log('start rec') } mediaRecorder.onstop = () => { console.log('stop rec') } mediaRecorder.ondataavailable = event => { console.log('data available') }
4-4. SerialNumber & IndexedDB
4-4. SerialNumber & IndexedDB ãã¢ã¢ããªã§ã¯ãNFC Tag ã«ã¡ãã£ã¢ã®èšé²ãããŠãããã®æ§ã«ã æŒåºãæœããŠããŸããã ããã¯çš®æããããããšãNFC Tag
ã®ãserialNumberãã«çŽä»ãã ããŒã¿ãæ°žç¶åããŠããã ãã§ãã 4. Handling APIs in App localforageStore.getItem(id) localforageStore.setItem(id, blob)
4-4. SerialNumber & IndexedDB 4. Handling APIs in App ãã®äžæã®
ID ã key ã«ãIndexedDB ã« ã¡ãã£ã¢ SRC ã§ãã Blob ãæžã蟌ãã§ããŸãã ãã¢ã¢ããªã§ã¯ãlocalforage ãå©çšããŠããŸãã IndexedDB ã®ã©ãããŒã©ã€ãã©ãªã§ãã localforageStore.getItem(id) localforageStore.setItem(id, blob)
4-4. SerialNumber & IndexedDB IndexedDB ã®åãæ±ãã¯ããç ©éã§ãã localStorage ãšåãæèŠã§äœ¿ãããã¡ãã®ã©ã€ãã©ãªã Promise ãè¿ããŠããããããèšèšã«çã蟌ã¿ãããã§ãã
ïŒä»åã¯ã¹ããŒãéèŠã§éžå®ããŸããïŒ 4. Handling APIs in App localforageStore.getItem(id).then(...) localforageStore.setItem(id, blob).then(...)
4-5. Side Eï¬ect Handling
4-5. Side Eï¬ect Handling ããŠããããŸã§ã§ç޹ä»ããè€æ°ã® APIã ã³ãŒã«ããã¯ãã³ãã©ã Promise ãã»ãšãã©ã§ã éåæåŠçã®ãµã©ãããŠã«ã§ããã
ã²ãšã€ã²ãšã€ã®äœ¿ãæ¹ãåçŽã§ããé åºãå¶åŸ¡ãªã©ã ã¢ããªã±ãŒã·ã§ã³ãžã®çµ±åã«äžå·¥å€«ãå¿ èŠã«ãªããŸãã 4. Handling APIs in App
4-5. Side Eï¬ect Handling 4. Handling APIs in App å¯äœçšãæ··åšãã
Application ã¯ã å¯äœçšã«ç¹åããã©ã€ãã©ãªã䟿å©ã§ãã ç§ãæã«éŠŽæãã§ãã React ã§ã¯ã ä»åã®æ§ãª ã¢ããªè²ãæ¿ããã®ã®å Žåã Redux ãš redux-saga ã䜿ã£ãŠããŸãã
4-5. Side Eï¬ect Handling 4. Handling APIs in App Store
æ§æã¯ãå ±ææ©èœãã¡ã€ã³ããšãåããŒãžãã¡ã€ã³ã ã«åããŠãReducer ã Action ãããããèšããŠããŸãã ãããã®ãã¡ã€ã³ãããéããã²ãšã€ã® Store ãšããŸãã åããŒãžãã¡ã€ã³ã¯ãå ±ææ©èœãã¡ã€ã³ã®å©çšè ããšããäœçœ®ä»ãã§ãã ãã®æ§æã«ãããåã ã®å®è£ ãåçŽã«ãªã£ãŠããŸãã
4-5. Side Eï¬ect Handling MediaRecorder ãäŸã«èŠãŠã¿ãŸãããã é²ç»ã»é²é³ã®è²¬åã¯ãæ©èœãã¡ã€ã³ã§äžé管çããŸãã 4. Handling APIs
in App mediaRecorder.onstart = () => { store.dispatch(creators.onStartRecording()) } mediaRecorder.onstop = () => { store.dispatch(creators.onStopRecord()) } mediaRecorder.ondataavailable = event => { const blob = new Blob([event.data], { type: 'video/webm' }) store.dispatch(creators.onDataAvailable(blob)) }
4-5. Side Eï¬ect Handling 4. Handling APIs in App JavaScript
Native API ã³ãŒã«ããã¯ãã³ãã©ã®äžã§ã Redux Store ã® dispatch ãå®è¡ããŠããŸãã mediaRecorder.onstart = () => { store.dispatch(creators.onStartRecord()) } mediaRecorder.onstop = () => { store.dispatch(creators.onStopRecord()) } mediaRecorder.ondataavailable = event => { const blob = new Blob([event.data], { type: 'video/webm' }) store.dispatch(creators.onDataAvailable(blob)) }
4-5. Side Eï¬ect Handling åããŒãžã¯ãå ±ææ©èœãã¡ã€ã³ã® Action ã賌èªãããã å ±ææ©èœãã¡ã€ã³ ã« Action
ãçºè¡ããŸãã 4. Handling APIs in App switch (action.type) { case PermanentStorageTypes.ON_SUCCESS_PUT: return handleStateByMode(state, 'ready') case MediaRecorderTypes.ON_START_RECORDING: return handleStateByMode(state, 'recording') case MediaRecorderTypes.ON_DATA_AVAILABLE: return { ...state, blob: action.payload.blob } default: return state } Page Reducer Subscribe Actions
4-5. Side Eï¬ect Handling åããŒãžã¯ãå ±ææ©èœãã¡ã€ã³ã® Action ã賌èªãããã å ±ææ©èœãã¡ã€ã³ ã« Action
ãçºè¡ããŸãã 4. Handling APIs in App const handleClickIcon = React.useCallback(() => { switch (mode) { case 'ready': dispatch(startRecording({ audio: true, video: true })) break case 'recording': dispatch(stopRecording()) } }, [mode]) Page Component Dispatch Actions
4-5. Side Eï¬ect Handling ä»åã®ãã¢ã¢ããªã§ redux-saga ãæã圹ã«ãã£ãã·ãŒã³ã¯ã ã¡ãã£ã¢ã®é²ç»éå§æã«è¡šç€ºãããã«ãŠã³ãããŠã³æ©èœã§ãã ããã¯æŒåºä»¥å€ã«ããéèŠãªåœ¹å²ãæ ã£ãŠããŸãã ã«ã¡ã©ã®èµ·åçŽåŸïŒMediaStream
éå§çŽåŸïŒæãå Žæãªã©ã§ã¯ é²åºè£æ£ã®ããæ°ç§éæããªã£ãŠããŸãç¬éããããŸãã ãã®ã¿ã€ãã³ã°ã§é²ç»ãå§ããŠããŸããšãè¯ãç»ãæ®ããŸããã 4. Handling APIs in App
4-5. Side Eï¬ect Handling ã«ãŠã³ãããŠã³ãäžçš®ã®å¯äœçšã§ãããéåæåŠçãšãããŸãã ã«ãŠã³ãããŠã³äžã«çããå¥ã®å¯äœçšïŒç»é¢é·ç§»ãªã©ïŒãåé¡ã«ãªãåŸãŸãã 4. Handling APIs in
App let count = 4 while (count) { const [normal, abnormal] = yield race([ call(countDownStep), call(countDownCancel) ]) if (abnormal !== undefined) break count -= normal yield put(creators.onCountDown(count)) }
4-5. Side Eï¬ect Handling ãã®æ§ãªåé¡ã saga-effect ã®çµã¿åããã§å æããããšãã§ããŸãã ã€ã¬ã®ã¥ã©ãŒãªã±ãŒã¹ãã«ããŒããŠããããå¿åŒ·ã峿¹ã§ãã 4. Handling
APIs in App let count = 4 while (count) { const [normal, abnormal] = yield race([ call(countDownStep), call(countDownCancel) ]) if (abnormal !== undefined) break count -= normal yield put(creators.onCountDown(count)) }
ãŸãšã
æ©èœãè€éã»è€åçã«ãªããšã éåæåŠçãå ¥ãä¹±ããããšãåãããŸããã Reduxã»redux-saga ã®äŸã玹ä»ããŸãããã éåæåŠçã«åŒ·ãã©ã€ãã©ãªã¯æ§ã ãªãã®ããããŸãã®ã§ã æã«éŠŽæããã®ãèŠã€ããŠã¿ãŠãã ããã ãŸãšã
ãŸãšã Google Chrome ã® Experimental Features ã¯ã é¢çœããã®ãçãã ãããã§ãã Native API
ã«ã©ãã©ããªãŒãã§ããæ§ã«ãªã£ãŠããŸãã ã¢ã€ãã£ã¢æ¬¡ç¬¬ã§ã䟿å©ã»ãããããã ã¢ãŠãããããã§ãããã§ãã
ãŸãšã Experimental Features ã®ãã©ã€ã¢ã«ãã æ°ãããµãŒãã¹ã®çš®ã«ãªããããããŸããã ãã²ãææŠããŠã¿ãŠãã ããã
ãéèŽããããšãããããŸãã