PWAã®å®è£ ããã¦ã¿ã
ä¸å¹´ä»¥ä¸åã®è¨äºãªã®ã§ãã³ã¼ããå¤ãã§ããæ°ãã¤ãã¦èªãã§ãã ããã
ããããã°PWAã®å®è£ ãããã¨ããªãã£ããªã¨æã£ãã®ã§å°ã触ã£ã¦ã¿ãã
PWAã¨ã¯ï¼
PWA(Progressive Web Apps)
ã¤ã³ã¹ãã¼ã«ãä¸è¦ã§ãä¸å®å®ãªãããã¯ã¼ã¯ã§ãç´ æ©ãèµ·åããããã·ã¥éç¥ãå¯è½ã«ãã¾ãã
ã¾ãããã¼ã ç»é¢ã«ã¢ã¤ã³ã³ã表示ã§ããã¢ããªã¨åæ§ã®æ±ãããããã¨ãå¯è½ã¨ãªãã¾ãã
ã¤ã¾ããã¢ããªã«è¿ã¥ããwebã§ããã
以ä¸ã®è¨äºã詳ããã®ã§ãã¡ããè¦ã¦ãã ãã;)
ç®ç
- https, localhostã§ããService Workerã¯åããªãã®ã§å¸¸ã«å®å ¨
- Service Workerã®æ´æ°ããã»ã¹ã«ãã常ã«ææ°
- App Shellã¢ãã«ã«ããæ§æã§UIããã¤ãã£ãã«ããã«è¿ã¥ãã
- ããã·ã¥éç¥ã«ããåã¨ã³ã²ã¼ã¸ã¡ã³ã
- ãã£ãã·ã¥ãããã¨ã«ããããããã¯ã¼ã¯ã®ä¾å度ãä¸ãã
æè¡ã¹ã¿ãã¯
Service Worker
対å¿ç¶æ³ã¯ä»¥ä¸ã®éã
Can I use... Support tables for HTML5, CSS3, etc
代表çãªæä¾æ©è½
- ãªãã©ã¤ã³æ©è½
- pushéç¥
- ããã¯ã°ã©ã¦ã³ãã³ã³ãã³ãã®æ´æ°
- ã³ã³ãã³ããã£ãã·ã¥
ã¬ã·ã: ServiceWorker Cookbook
PWAã®view
PWAã«ã¯App Shellã¨Contentã¨ãããã®ãããã¾ãã
以ä¸ã®å³ãè¦ãã¨ããããããã¨æãã¾ãã
ã¤ã¾ããã¢ããªã±ã¼ã·ã§ã³ã·ã§ã«ã¨ããã®ã¯ãã¤ãããã¯ã³ã³ãã³ããããªãé¨åãæãã¾ãã
App Shell
ä¸çªãPWAã®å®ç¾ã§é£ããé¨åã§ãããä¸çªããã©ã¼ãã³ã¹ã®åä¸ãå³ããã¨ãæå¾
ãããé¨å(ããã)
ã·ã³ãã«ãªãã¶ã¤ã³ã³ã³ã»ããã§è¨è¨ããã¾ãã
Service Workerã®ãã£ãã·ã³ã°æ©è½ã«ãããããã©ã¼ãã³ã¹ã®åä¸ãå¯è½ã§ãã
æä¸ä½ã®ã¢ããªã®ãã¸ãã¯ãã«ã¼ã¿ã¼ãªã©ãããã¾ãã
Content
åçãªãã¥ã¼ã§ããä¾ãã°Twitterã®ã¿ã¤ã ã©ã¤ã³ã¨ãã
ãããããããã®ã³ã³ãã³ãã§å¿
è¦ã«å¿ãã¦JSã®ãã£ã³ã¯ã¯ç´°ããåããã¾ãã
ãã£ãã·ã¥æ¦ç¥
åºæ¬çã«ãApp Shellã¨Contentã®JSã¯å¥ãã£ã³ã¯ã«ããã¹ãã§ãã
Service Workerã«ããããã®ãã£ã³ã¯ãä¿æããããã¨ã«ãããã¦ã¼ã¶ãåã®ãã¼ã¸ã«æ»ã£ãæã«æ©ãèªã¿è¾¼ããã¨ãå¯è½ã§ãã
çè«ä¸ãApp Shellã®èªã¿è¾¼ã¿ã¨Contentã®èªã¿è¾¼ã¿ãå¥ã«ãããã¨ã«ãããããã©ã¼ãã³ã¹ã¨ã¦ã¼ã¶ããªãã£ã®åä¸ãå³ãããããã§ãã
App Shellã¯ã©ã®ãã¼ã¸ã§ã常ã«èªã¿è¾¼ã¾ããContentã¯å¿
è¦ã«å¿ãã¦èªã¿è¾¼ãã¨ããæãã§ãã
èªã¿è¾¼ã¿ããã¼
PWAã¯å
ã«ãã®æã«å¿
è¦ãªãã®ã ããåããããããã£ãã·ã¥ããä»çµã¿ã§ãã
ãªã®ã§webpackã§ãã£ã³ã¯ãç´°ããåããã¨ã«ãããå¿
è¦ãªãªã½ã¼ã¹ã ããèªã¿è¾¼ããããã«è¨è¨ãã¾ãã
ãã®å¾ãService Workerå´ã§è¿½å ã®ãªã½ã¼ã¹ãäºåã«åå¾ãã¦ãå°æ¥çãªèªã¿è¾¼ã¿ãè¡ãã¾ãã
ã¾ãããã¼ãã£ã³ã°ã®é åºã¯App Shellã§åºæ¬çãªUIãæ§ç¯ãããã®å¾ã«ã³ã³ãã³ãã§ãã
Web App Manifest
manifest.json
ã«ååãã«ã©ã¼ããã¼ã ç»é¢ã«ç½®ãã¢ã¤ã³ã³ã®è¨å®çãæ¸ãã¾ãã
PWAã«ã¯å¿
é ã§ãã
以ä¸ã®ãããªã¹ãã¼ãã«ãªãã¾ãã
{ "name": "My PWA Sample", "orientation": "portrait", "display": "standalone", "start_url": ".", "short_name": "MyPWA", "description": "This is a sample App!", "background_color": "#f5f5f5" }
ã¾ããHTMLã§ã¯ä»¥ä¸ã®ããã«æå®ãã¾ãã
<link rel="manifest" href="/manifest.json">
ä»åã¯ãwebpack-pwa-manifestã¨ãããã©ã°ã¤ã³ããã£ãã®ã§ããã使ãã¾ããã
ãã¶ã¤ã³
PRPL patternã¨ããã®ãããã¾ãã
ããé«éã«ã¢ãã¤ã«ã§webã®ã¨ã¯ã¹ããªã¨ã³ã¹ãæä¾ãã¾ãã
PushãRenderãPre-cacheãLazy-loadã§æ§æããã¾ãã
以ä¸ã®Addy Osmaniã®è¨äºãã¨ã¦ãããããããã§ãï¼
The PRPL Pattern | Web Fundamentals | Google Developers
ã¾ãä»åº¦ãããã°ã«ã§ãæ¸ãããã¨æãã¾ãã
Firefoxã¨ChromeããService Workerãªããã©ã©ãããã®ï¼
æ®éã®HTMLãCSSãJSãªã®ã§åé¡ã¯ããã¾ããã
Service Workerã¯ããã¾ã§ããã¤ãã£ãæ©è½ã«è¿ã¥ããå®ç¾æ¹æ³ãªã®ã§ä»ã¾ã§ã©ããã«ãã©ã¼ã«ããã¯ãã¾ãã
ãããã¯ã¼ã¯
Twitter Liteã§http/2, GraphQLã使ããã¦ãã¾ãã
å®è£
ä¸è¨ã®ãªãã¸ããªã§éçºãã¦ã¿ã¾ããã
SPA + Service Workerã§å®ç¾ãã¦ãã¾ãã
ä»åã¯CSRã®ã¿ã§ãã
ã©ã¤ãã©ãª
react, react-routerã§æ§ç¯ãã¾ããã
詳ããã¯ããªãã¸ããªã®webpack.config.js
ã¨ããè¦ã¦ãã ããã
webpack-offline
Service Workerã®ãã¡ã¤ã«åãåºãã¨çµåãè¡ã£ã¦ããããã©ã°ã¤ã³ã
注æç¹ã¨ãã¦ããã£ãã·ã¥ãã¡ã¤ã«ã®ä¿å容éãè¶
ããæã®ã¨ã©ã¼ããããã¥ããã
Uncaught (in promise) DOMException: Quota exceeded. service worker
ã¯å¤åãã®ã¨ã©ã¼ã
ãªã®ã§ãåºæ¬çã«ã¯devã§ã¯offlineã使ããªãã§ãããã¯ã·ã§ã³ã®ã¨ãã«ã ã使ãããã«ããã»ããããã(HMRãããããã§ããªãã®ã§)
ãã ããã¡ããswã«æ¬å½ã«æ¥ç¶ã§ãã¦ããã確èªãããã¨ãã¯ããã®ã§ãã®ã¨ãã¯ã©ã¤ãã©ãªç¾¤ã®ãã£ã³ã¯ããã£ãã·ã¥ããå¤ãã¦ãããã°ãã¦ããã
æ§ã ãªãªãã·ã§ã³ãããã®ã§ãã¥ã¼ãã³ã°ã«ããããã©ã¼ãã³ã¹ã¨ãã®å¤åã¯ããããã
æ§æ
ãã¡ã¤ã«
Asset Size Chunks Chunk Names vendor.2a193704.js 806 kB 5 [emitted] [big] vendor node-8f3bc311d3d7fbab90a659d57e126fbf.png 3.73 kB [emitted] Boron.content.bundle.2a193704.js 2.3 kB 1 [emitted] Boron.content Argon.content.bundle.2a193704.js 2.3 kB 2 [emitted] Argon.content List.content.bundle.2a193704.js 1.89 kB 3 [emitted] List.content bundle.2a193704.js 9.28 kB 4 [emitted] bundle Carbon.content.bundle.2a193704.js 2.3 kB 0 [emitted] Carbon.content manifest.json 367 bytes [emitted] index.html 462 bytes [emitted] sw.js 23.2 kB [emitted] appcache/manifest.appcache 265 bytes [emitted] appcache/manifest.html 3.3 kB [emitted]
ãã¡ã¤ã«ã¯ä¸è¨ã®ããã«åãã¾ããã
vendor.js
ã§ã¯ã©ã¤ãã©ãªã®ã³ã¼ãã®ã¿ãå
¥ã£ã¦ãã¾ãã
ãªã®ã§ä¸çªãµã¤ãºã大ããã§ãã
ã©ã¤ãã©ãªã®ãã¼ã¸ã§ã³ãé »ç¹ã«å¤ãããªãããã³ã¢ã³ã¼ãããéé¢ãã¾ãã
bundle.js
ãApp Shellã§ãã
ã«ã¼ãã£ã³ã°ã¨Toolbarãæã£ã¦ãã¾ãã
ãã¹ããã©ã¯ãã£ã¹ãããããªãã§ãããããã¯ä¸ç·ã«ããªãã»ããããããã§ãã
*.content.bundle.js
ãcontentã§ãã
ä»åã¯ãArgon, Boron, Carbonã®ä¸ç¨®é¡ã¨ã«ã¼ããã¼ã¸ã®ãªã¹ããåè¨4ãã£ã³ã¯ããã¾ãã
ã¡ãªã¿ã«Nodeã®LTSã®ååããã®ä¸ç¨®é¡ã§ã(v4, v6, v8)
ã«ã¼ãã£ã³ã°
æ
£ãã¦ããreact-routerã使ãã
å¿
è¦ãªæã«contentã®ãã£ã³ã¯ãåå¾ããããã«lazy loadã使ãã¾ãã
react-routerã«ã¯æ
£ãã¦ããã¤ããã ã£ãããv4ããgetComponent
ããªããªã£ã¦ãããã¨ã«æ°ä»ãã¦ãªãã£ããã
æã¯ã
<Route path="/" getComponent={(location, callback) => { require.ensure([], require => { callback(null, require('./Root')) }, 'Root') }} />
ã¿ããã«æ¸ããã¯ããªã®ã«ä»ã¯æ¸ããªããªã£ã¦ããã
調ã¹ãéãå¤åãFBã®æ¹ãæ¸ãã¦ããããä¸çªãã¬ã¤ãªæ¸ãæ¹ã
Quick and dirty code splitting with React Router v4 · GitHub
ãã¼ãããã ã©ããã¼ãæ¸ããªãã¨ãããªãã®ãã(ãã¨react-routerã®ãªãã¡ã¬ã³ã¹èªã¿ã¥ãããã ãããã)
ã¨ãããã¨ã§ããããã©ãããã¦ãã©ã¤ãã©ãªããã£ãã®ã§ä»åã¯ããã使ã£ãã
ãã ãæ®å¿µãªãã¨ã«<Switch>
ã対å¿ãã¦ãªãã¦ãã¤ãããã
ä»PRãåºã¦ããã®ã§ããå¾
ã¡ã¨ããç¶æ
ã§ãã
Can not use with Switch · Issue #4 · mhaagens/lazy-route · GitHub
ãããããªãã®ã§ã/
ã«å¯¾ãã¦exact
ãä»ãããã¨ã«ããã
// é·ãã®ã§çç¥é¨ãã const Routes = () => ( <App> <Route exact path="/" render={() => <LazyRoute component={ import(/* webpackChunkName: 'List.content' */ './components/contents/List') } /> } /> <Route path="/argon" render={() => <LazyRoute component={ import(/* webpackChunkName: 'Argon.content' */ './components/contents/Argon') } /> } /> </App> );
Appã¯Viewå
¨ä½ãæ§ç¯ãã¾ãã
ãã®ä¸ã«Toolbarãå
¥ã£ã¦ãããthis.props.children
ãä¸è¨ã«å½ã¦ã¯ã¾ã£ãã«ã¼ãã«ãªããããã¬ã³ããªã³ã°ãã¾ãã
ããreact-routerã§ããé¨åçæ´æ°ã®ææ³ã§ããã
ããããä»åã¯ã¬ã³ããªã³ã°æã«ãã¡ã¤ã«ãåå¾ãèªã¿è¾¼ã¿æµãããã®ã§åçã«åå¾ããå®è£
ãå¿
è¦ã§ãã
ãªã®ã§stage-3ã®dynamic importã使ãå¿
è¦ãããã¾ãã(webpack2以éã¯ããã©ã«ãã§å
¥ã£ã¦ãã¾ã)
ã¢ã»ããã®ã¤ã³ã¹ãã¼ã«
ãã®ãããªæãã§ä¿åãããã
ãã£ãã·ã¥ã®ç¨®é¡ã¯ main
, additional
, optional
ã®ä¸ç¨®é¡ããã
main
ã¯installã¤ãã³ãæã«service workerã«ãã£ãã·ã¥ããããã失æãããå
¨é¨ã®ãã£ãã·ã¥ã¯ããã¾ããã
additional
ã¯main
ãæ£å¸¸ã«ãã¼ããããå¾ããã¼ãããã¾ãã
optional
ã¯ãµã¼ãããfetchãããã¨ãã®ã¿ãã£ãã·ã¥ãããã®ã§ãäºåã«ãã¦ã³ãã¼ããã¾ããã
ä»åã¯index.html
ã¨å種JS,ç»åãä¿åãã¦ããã®ã§ãããã§ãã¨ãserveãã¦ããªãã£ããããããåã£ã¦ããç¶æ
ã§ãæç«ãç¾ããã®ã§ã¯ãªãé常ã®ãã¼ã¸ã表示ããã¾ãã
ãããã¯ã¼ã¯ã¿ã¤ã ã©ã¤ã³ã¯ãã®ããã«ãªãã¾ãã
sizeã®ã¨ãããè¦ãã¨ãããã¾ãããService Workerããã³ã¼ããåå¾ãã¦ãã¾ãã
ãããã¯ã¼ã¯ãåãã¦ããã®ã§ãsw.jsã®åå¾ã¯å¤±æãã¾ããã³ã¢ã³ã¼ãã¯ãã§ã«åå¾æ¸ã¿ãªã®ã§ããããçãã¦ããããã«ã¬ã³ããªã³ã°ãããã
ã¾ãé«éã§ãã(vendor.jsã¨ãéãã®ã«ãã)
APIå¨ã
ä»åã¯ãéä¿¡å¨ãã®å®è£
ãè¡ã£ã¦ããªãã®ã§ã³ã¼ãã¯ããã¾ãããã
Twitter Liteã§ã¯APIãå©ããå¾Normalizrãéãã¦Reduxã«å¹çãããã¼ã¿ã渡ãã¦ãã¾ãã
ã¾ããIndexedDBã«ããã®çµæãä¿åãã¾ãã
SSR
ä»åã®ãµã³ãã«ã§ã¯ãã£ã¦ãã¾ããããåºæ¬çã«ã¯ãã£ãã»ããããã¨æã£ã¦ãã¾ãã
Twitter Liteã§ã¯ãèªè¨¼ãããåæç¶æ
ã®æ§æãããApp Shellã®ã¬ã³ããªã³ã°ãããè¨è¨ã«ãªã£ã¦ãã¾ãã
Twitter Liteãã¤ã³ã¹ãã¯ã¿ã§è²ã
è¦ãã¨æ¥½ããããã
è³æ
The PRPL Pattern | Web Fundamentals | Google Developers
ãããã«
ææ¢ãã§ãã£ã¦ãã¦ããããã¹ã¦ãã¹ããã©ã¯ãã£ã¹ã§ã¯ãªãã£ããã誤èªããããããããªãã®ã§ãä½ãããã°PRãIssueãã³ã¡ã³ããªã©åºãã¦ããããã¨å©ããã¾ã:p