Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Angular Universal on Google App Engine
Search
Kenji Imamula
November 23, 2018
Technology
1.3k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Angular Universal on Google App Engine
東京Node学園祭2018での発表資料です。
Kenji Imamula
November 23, 2018
More Decks by Kenji Imamula
See All by Kenji Imamula
ビルドプロセスから考えるCSSアンチパターン
kimamula
3
1.7k
Other Decks in Technology
See All in Technology
LLM-as-a-Judgeは本当に信頼できるのか――評価器を評価する話
taka_aki
3
1k
「私が一番顧客に詳しい」を捨てる~ 全員が一次情報に精通する開発チームをつくり、PMが次のボトルネックへ染み出すまで
kaminashi
3
1.2k
Persisting Massive Data with Rails ~Designing for 60 billion rows, and fighting the bottlenecks~ Railsで挑む大量データ永続化 〜600億件を永続化するための設計とボトルネックとの戦い〜
occhi
0
780
CTO Night|NotionのAIエージェントとFDE
kzkhykw1991
0
300
その Valkey 使いこなしていますか?
onk
PRO
5
1.8k
freeeにおけるSoftware Factory
freee
PRO
0
270
Gemini Intelligence 入門 ― AppFunctions と Gemini Nano
takuroabe
0
350
生成AI時代、PMは事業責任者に進化するともっと面白い〜PMだからこそ事業構造を動かせる時代に〜
kakehashi
PRO
0
240
僕のハーネスを紹介します
watany
5
1.4k
[EMNLP26] RIGEL: Self-Distilled Score Adaptation for Image and Video Captioning Evaluation
keio_smilab
PRO
0
110
Tofu-Controller lightning talk @ Containerday 2026
gionn
0
170
野良MCPサーバーを排除せよ!MCPサーバーのガバナンス
yukiogawa
1
150
Featured
See All Featured
Chasing Engaging Ingredients in Design
codingconduct
0
370
Skip the Path - Find Your Career Trail
mkilby
1
260
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
640
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
1k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
50
10k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
460
Into the Great Unknown - MozCon
thekraken
41
2.8k
How to Think Like a Performance Engineer
csswizardry
28
2.9k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
490
Java REST API Framework Comparison - PWX 2021
mraible
34
9.8k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
310
Transcript
Angular Universal on Google App Engine ౦ژNodeֶԂࡇ2018 2018/11/23
גࣜձࣾΧϒΫ ࠓଜݠ࢜ @kimamula ˞("&߇͑Ί
About me •ࠓଜݠ࢜ •@kimamula •גࣜձࣾΧϒΫ •લ৬React->ݱ৬Angular •TypeScript ❤
Topics 1. What is Angular Universal 2. How to Angular
Universal 3. Hack Angular Universal
1. What is Angular Universal
Angular Universal https://github.com/angular/universal AngularΞϓϦέʔγϣϯͷSSRʢserver-side renderingʣΛՄೳʹ͢ΔͨΊͷϓϩδΣΫτ Server • Node.js • ASP.NET
• (Python, Go, PHP) Page Request Browser "OHVMBS 6OJWFSTBM Rendered HTML • SEO • Performance
Our use case SSRαʔόʔ ʢGAE SE/Node.jsʣ APIαʔόʔ ʢGAE SE/Pythonʣ Ӷҙ։ൃத
Google App EngineͱNode.js • 2018/06ɺSE (Standard Environment)Ͱ Node.jsΞϓϦͷσϓϩΠ͕Մೳʹ • ͨͩ͠ϕʔλ
• Node.js 8, 10ʹରԠ • majorόʔδϣϯΛࢦఆͯ͠σϓϩΠ • minor, patchόʔδϣϯউखʹ্͕Δ༷
2. How to Angular Universal
2-1. Getting Started
Quick Start Prerequisite: Angular CLI ؆୯ʂʂ $ ng new my-project
$ cd my-project $ ng add @nguniversal/express-engine --clientProject my-project $ npm run build:ssr && npm run serve:ssr # … Node Express server listening on http://localhost:4000
Slow Start https://angular.io/guide/universal • ެࣜυΩϡϝϯτ • આ໌ΛಡΈͳ͕ΒखॱΛͳͧΔ͜ͱͰɺ͋ ΔఔΈΛཧղͰ͖Δ • ऴ൫ͰQuick
Startʹॻ͍ͨखॱ͕ग़͖ͯͯ3 ΫοΩϯάײ͕͋Δ
Slow Start https://github.com/angular/universal-starter • ࠷খߏͷAngular UniversalΞϓϦ • angular.ioͷهࡌ༰ΑΓҰาઌΛߦͬͯ ͍ΔײʢϏϧυͷํ͕ҧͬͨΓ͢Δʣ •
Prerenderingʢޙड़ʣͷ࣮͋Γ
2-2. Angular Universal ։ൃͷجຊ
αʔόʔͱΫϥΠΞϯτͰίʔ υ͕ڞ௨ʹͳΔ͜ͱʹҙ͢Δ • αʔόʔ/ΫϥΠΞϯτͷͲͪΒ͔Ͱ͔͠ಈ͔ ͨ͘͠ͳ͍ॲཧΛదʹ੍ޚ͢Δ • αʔόʔͰ࣮ߦࡁΈͷॲཧ͕ΫϥΠΞϯτͰ ॏෳ࣮ͯ͠ߦ͞Εͳ͍Α͏ʹ͢Δ
αʔόʔͱΫϥΠΞϯτͰίʔ υ͕ڞ௨ʹͳΔ͜ͱʹҙ͢Δ • αʔόʔ/ΫϥΠΞϯτͷͲͪΒ͔Ͱ͔͠ಈ͔ ͨ͘͠ͳ͍ॲཧΛదʹ੍ޚ͢Δ • αʔόʔͰ࣮ߦࡁΈͷॲཧ͕ΫϥΠΞϯτͰ ॏෳ࣮ͯ͠ߦ͞Εͳ͍Α͏ʹ͢Δ
isPlatformBrowser, isPlatformServer • ॳظԽॲཧ྆ڥͰجຊతʹશ෦ಈ͘ • constructor, ngOnInit, … • ReactͷcomponentDidMountͷΑ͏ͳͷ
ͳ͍ • αʔόʔͷΈorΫϥΠΞϯτͷΈͰಈ͔ͨ͠ ͍ॲཧ͕͋Δ߹దٓఆ͕ඞཁ
isPlatformBrowser, isPlatformServer import { PLATFORM_ID } from '@angular/core'; import {
isPlatformBrowser, isPlatformServer } from '@angular/common'; constructor( @Inject(PLATFORM_ID) private platformId: Object ) {} ngOnInit() { if (isPlatformBrowser(this.platformId)) { // Client only code. } if (isPlatformServer(this.platformId)) { // Server only code. } }
αʔόʔͱΫϥΠΞϯτͰίʔ υ͕ڞ௨ʹͳΔ͜ͱʹҙ͢Δ • αʔόʔ/ΫϥΠΞϯτͷͲͪΒ͔Ͱ͔͠ಈ͔ ͨ͘͠ͳ͍ॲཧΛదʹ੍ޚ͢Δ • αʔόʔͰ࣮ߦࡁΈͷॲཧ͕ΫϥΠΞϯτͰ ॏෳ࣮ͯ͠ߦ͞Εͳ͍Α͏ʹ͢Δ
Transferstate αʔόʔαΠυͰॳظԽͨ͠ঢ়ଶΛΫϥΠΞϯ ταΠυʹ͢Έ • HTML͚ͩͰΫϥΠΞϯτͰ࠶औಘ͕ඞཁ Server Page Request Browser ঢ়ଶͷॳظԽ
"1*ίʔϧ ֤छܭࢉॲཧ Rendered HTML including State ແବͳ"1*ίʔϧɺ ࠶ܭࢉΛ͙
Transferstate: αʔόʔ import { TransferState } from '@angular/platform-browser'; import {
TRANSFER_STATE_KEY } from './transfer-state-key'; constructor(transferState: TransferState) { // … transferState.onSerialize(TRANSFER_STATE_KEY, () => { return state; }); } import { makeStateKey } from '@angular/platform-browser'; export const TRANSFER_STATE_KEY = makeStateKey('MY_KEY'); ঢ়ଶڞ༗ͷͨΊ ͷΩʔͷ࡞ ԿΒ͔ͷํ๏ͰΞϓϦέʔγϣϯͷ ঢ়ଶΛऔಘͯ͠ฦ͢ʢFH/H3Yʣ
Transferstate: ΫϥΠΞϯτ import { TransferState } from '@angular/platform-browser'; import {
TRANSFER_STATE_KEY } from './transfer-state-key'; constructor(transferState: TransferState) { if (transferState.hasKey(TRANSFER_STATE_KEY)) { const state = transferState.get( TRANSFER_STATE_KEY, defaultValue ); this.transferState.remove(TRANSFER_STATE_KEY); } } ͞Εͨ ঢ়ଶͷऔಘ
2-3. ϋϚͬͨͱ͜Ζɺ ࠔͬͨͱ͜Ζ
styles.cssͷSSR https://github.com/angular/universal/issues/974
styles.cssͷSSR: • ίϯϙʔωϯτ͝ͱͷCSS • SSR͞ΕΔʢHTMLʹΠϯϥΠϯల։͞Ε Δʣ -> ॳظදࣔͷ࣌Ͱਖ਼͘͠ద༻͞ΕΔ •
styles.cssʢάϩʔόϧͳCSSʣ • SSR͞ΕͣɺJSͷॲཧͷதͰΠϯϥΠϯల։ ͞ΕΔ -> ద༻·Ͱʹϥά͕Ͱ͖Δ
styles.cssͷSSR: workaround • ԼͷΑ͏ͳSCSSͷΈͷίϯϙʔωϯτΛ࡞Γ • AppServerModuleͷbootstrapͰࢦఆ͢Δ ৄࡉ: https://github.com/Angular-RU/angular-universal-starter/commit/dbb413b // inline-style.component.scss
@import 'path/to/styles.scss'; @NgModule({ // ... bootstrap: [AppComponent, InlineStyleComponent] }) export class AppServerModule { // ... }
watchϞʔυͰ։ൃ͍ͨ͠ https://github.com/angular/universal-starter/issues/490
DX with a CSR Angular app ng serveͰ؆୯ʹwatchϞʔυʹͳΔ 1.ίʔυฤू 2.ࣗಈϦϏϧυ
3.ϥΠϒϦϩʔυ
DX with a SSR Angular app ެࣜͷखॱʹهࡌͷscript͚ͩΛ͏߹ 1.ίʔυฤू 2.खಈͰϏϧυίϚϯυ࣮ߦ •
1͔ΒϏϧυͳͷͰΠϯΫϦϝϯλϧ͡Όͳ͍ 3.खಈͰNode.jsαʔόʔ࠶ىಈ 4.खಈͰϒϥβϦϩʔυ
ͭΒ͍
ࣗલͰͬͯΈΔ ”ng build --watchͨ͠ͷΛ͞Βʹhookͯ͠ExpressͳͲʹܨ͛ΔͱΑͦ͞͏”
Ϗϧυ͢Δͷ3ͭ 1. ΫϥΠΞϯτ͚AngularΞϓϦ 2. αʔόʔ͚AngularΞϓϦ 3. Express࣮ߦίʔυ • 2ͷϏϧυ࢈ʹґଘ ->
1, 2Angular CLIͷΈͰɺ 3webpackͷwatchϞʔυͰwatch͢Δ
ϏϧυͷྲྀΕ ίʔυฤू -> ΫϥΠΞϯτ͚AngularΞϓϦͷϏϧυ -> αʔόʔ͚AngularΞϓϦͷϏϧυ -> Express࣮ߦ༻ίʔυͷϏϧυ -> αʔόʔ࠶ىಈʢnodemonʣ
-> ϒϥβϦϩʔυʢbrowser-syncʣ
ࠓͷͱ͜Ζ͋·ΓշదͰͳ͍ ίʔυฤू -> ΫϥΠΞϯτ͚AngularΞϓϦͷϏϧυ -> αʔόʔ͚AngularΞϓϦͷϏϧυ -> Express࣮ߦ༻ίʔυͷϏϧυ -> αʔόʔ࠶ىಈʢnodemonʣ
-> ϒϥβϦϩʔυʢbrowser-syncʣ ͓͓ΉͶ~30ඵ HMRʹ͖͢ʁ
3. Hack Angular Universal
3-1. Prerender
Prerender or SSR https://github.com/angular/universal-starter#build-time-prerendering-vs-server-side-renderingssr Ϗϧυ࣌ʹੜͨ͠)5.-Λ ࣮ߦ࣌ʹ੩తʹ৴͢Δ
How to prerender universal-starterϦϙδτϦͷprerender.tsΑΓൈਮʢҰ෦վมʣ ['/', '/lazy', '/lazy/nested'].forEach(route => { const
fullPath = join(BROWSER_FOLDER, route); previousRender = previousRender .then(_ => renderModuleFactory(AppServerModuleNgFactory, { document: index, url: route, extraProviders: [ provideModuleMap(LAZY_MODULE_MAP) ] }) ).then(html => writeFileSync(join(fullPath, 'index.html'), html) ); });
How to prerender universal-starterϦϙδτϦͷprerender.tsΑΓൈਮʢҰ෦վมʣ ['/', '/lazy', '/lazy/nested'].forEach(route =>
{ const fullPath = join(BROWSER_FOLDER, route); previousRender = previousRender .then(_ => renderModuleFactory(AppServerModuleNgFactory, { document: index, url: route, extraProviders: [ provideModuleMap(LAZY_MODULE_MAP) ] }) ).then(html => writeFileSync(join(fullPath, 'index.html'), html) ); }); QSFSFOEFS ͢ΔύεͷҰཡ ύεʹର͢Δ )5.-Λੜ ੜ͞Εͨ)5.-Λ ϑΝΠϧʹग़ྗ
CSR vs SSR vs Prerender $43 443 1SFSFOEFS ΫϥΠΞϯτ ෛՙ
º ̋ ̋ αʔόʔ ෛՙ ̋ º ̋ ॊೈੑ ̋ ̋ º
CSR vs SSR vs Prerender $43 443 1SFSFOEFS ΫϥΠΞϯτ ෛՙ
º ̋ ̋ αʔόʔ ෛՙ ̋ º ̋ ॊೈੑ ̋ ̋ º ͜͜Λ̋ʹ Ͱ͖ͳ͍͔
ಈతίϯςϯπͷPrerender Server • ೝূ • ೝՄ • ݴޠ ͷఆ /some/path
PrerenderࡁΈHTML ঢ়گʹԠͯ͡దͳ HTMLΛฦ͢ ͜͏͍͏͜ͱ͕Ͱ͖ͨΒૉఢ͔…ʁ ʢݕ౼தʣ
3-2. HTTP/2 Server Push
HTTP/2 Server Push 4FSWFS #SPXTFS GET /css1.css Without Push 4FSWFS
#SPXTFS GET /index.html Index.html With Push /css1.css (push) GET /index.html Index.html /css1.css
Server Push with Angular CLI ະαϙʔτ https://github.com/angular/angular-cli/issues/11946
Server Push with Other FWs ͍ͬͯΔݶΓͰ • Polymer • Preact
• Nuxt.js
࡞ͬͯΈΔ 2௨Γͷ࡞Γํ • Preload link headersΛ͏ํ๏ -> ࠾༻ • ؆୯ʢৄࡉ࣍ͷεϥΠυͰʣ
• Node.jsͷAPI Λ͏ํ๏ • v10Ͱexperimentalϑϥάͳ͠Ͱ͑Δ Α͏ʹͳͬͨ • ExpressͰͷ͍উख͕ࠓͻͱͭ
Preload link headers 3FWFSTF QSPYZ #SPXTFS GET /index.html Index.html /css1.css
(push) /PEFKT GET /index.html Index.html Link: </css1.css>; rel=preload;
ͦͷύεͰඞཁͳϦιʔεʁ ҎԼͷํ๏Ͱఆ • Ϗϧυ࣌ͷwebpackͷstats͔ΒɺϞδϡʔ ϧͱchunkͷඥ͚ใΛಘΔ • SSRͷࡍ͜ͷใΛݩʹɺϩʔυ͞ΕͨϞ δϡʔϧ͕ଐ͢ΔchunkΛpreload link headersʹՃ͢Δ
ngx-server-push https://github.com/kimamula/ngx-server-push/ • ޭ • angular.ioͷखॱͰ࡞͍ͬͯΕɺߦखΛՃ ͑ΕಋೖͰ͖ΔΑ͏ʹ࡞ͬͨ • ͨͩ͠ɺࡉ͔͍ͱ͜Ζ͕৭ʑέΞͰ͖͍ͯͳ ͍ͷͰɺ࣮ઓೖͰ͖ΔϨϕϧͰͳ͍
·ͱΊ • Angular UniversalΛ࢝ΊΔʹ͋ͨͬͯಡΉ • https://angular.io/guide/universal • https://github.com/angular/universal- starter •
αʔόʔͱΫϥΠΞϯτͰίʔυ͕ڞ௨ʹͳ Δ͜ͱʹҙ͢Δ
·ͱΊ • αΫαΫwatchϞʔυͰ͖Δਓ͕͍ͨΒڭ͑ͯ ͍ͩ͘͞ • Prerenderݕ౼ͯ͠Έ·͠ΐ͏
Thank you!