Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Real World Virtual DOM
Search
Koutarou Chikuba
February 16, 2015
Technology
43
8k
Real World Virtual DOM
React, Flux, Isormorphic そして現実
Koutarou Chikuba
February 16, 2015
Tweet
Share
More Decks by Koutarou Chikuba
See All by Koutarou Chikuba
極限環境で最終ビルドを絞るためのフロントエンド設計
mizchi
14
4.4k
Server Side JavaScript のためのバンドル最適化
mizchi
5
6.1k
V8 as a container on CDN Edge worker
mizchi
5
1.8k
Edge Side Frontend という新領域
mizchi
33
13k
バンドル最適化マニアクス at tfconf
mizchi
7
4k
「たかがJavaScript」のその先 #TECHPLAY
mizchi
47
20k
Deno Node 両刀
mizchi
6
2.2k
「フロントエンド領域」を再定義する
mizchi
50
35k
光を超えるためのフロントエンドアーキテクチャ
mizchi
84
21k
Other Decks in Technology
See All in Technology
Git 研修 Advanced【MIXI 24新卒技術研修】
mixi_engineers
PRO
0
200
目標設定は好きですか? アジャイルとともに目標と向き合い続ける方法 / Do you like target Management?
kakehashi
10
3k
さらに高品質・高速化を目指すAI時代のテスト設計支援と、めざす先 / AI Test Lab vol.1
shift_evolve
0
190
ACRiルーム最新情報とAMD GPUサーバーのご紹介
anjn
0
160
推薦システムを本番導入する上で一番優先すべきだったこと~NewsPicks記事推薦機能の改善事例を元に~
morinota
0
130
スタートアップにおける組織設計とスクラムの長期戦略 / Scrum Fest Kanazawa 2024
yoshikiiida
13
3.6k
AIエージェントを現場に導入する目線とは
masahiro_nishimi
1
1.5k
大規模ドラレコデータ収集・機械学習基盤を支える AWS CDK 〜導入・運用事例紹介〜
pemugi
0
110
ギークの理想が7つ集まるエムスリーで夢を叶えよう - エムスリー株式会社
m3_engineering
1
260
[2024最新版]AWS Control Towerを使ったセキュアなマルチアカウント環境の作り方
hiashisan
0
270
AI研修【MIXI 24新卒技術研修】
mixi_engineers
PRO
0
130
初中級者用如何使用backlog -VALE TUDOEDITION-
in0u
0
140
Featured
See All Featured
Fontdeck: Realign not Redesign
paulrobertlloyd
79
5.1k
Reflections from 52 weeks, 52 projects
jeffersonlam
346
19k
Principles of Awesome APIs and How to Build Them.
keavy
124
16k
A designer walks into a library…
pauljervisheath
201
24k
Thoughts on Productivity
jonyablonski
64
4.1k
Why You Should Never Use an ORM
jnunemaker
PRO
51
8.9k
How To Stay Up To Date on Web Technology
chriscoyier
784
250k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
245
1.2M
Side Projects
sachag
451
42k
The Art of Programming - Codeland 2020
erikaheidi
48
13k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
277
13k
Gamification - CAS2011
davidbonilla
78
4.9k
Transcript
Real World Virtual DOM React, Flux, Isormorphic… ͦͯ͠ݱ࣮ ɹ @mizchi
/ Increments Inc
ࣗݾհ ☞ id:mizchi | അޫଠ ☞ Qiitaͷํ͔Βདྷ·ͨ͠ ☞ ۀΤϯδχΞྺ3 ☞
ੵΈήʔ͕ऴΘΒΜ
ࠓ·Ͱࣄ͖ͯͨ͠ڥ ৽ଔͰ࠷ॳʹॻ͍ͨݴޠ Haskell ͱ Clojure ͱ͋ΔήʔϜͷUnity͔ΒHTML5ͷҠ২Λͯ͠Ҏ དྷɺSPAͷઃܭΛߟ͑ଓ͚͍ͯΔ
Virtual DOM ʹ͍ͭͯͷ׆ಈ ☞ VirtualDOM Advent Calendar 2014 - Qiita
ͷओ࠵ ☞ ͋ͳ͕ͨReactΛ͏͖ཧ༝ ☞ ͳͥԾDOMͱ͍͏֓೦͕ԶୡͷࠢΛ͑ͤ͞Δ ͷ͔ - Qiita ☞ #13 Virtual DOM | mozaic.fm ͷήετ
Έͳ͞Μ
ࠢ͑ͯ·͢ʁ
͕Reactʹ͍ͭͯ ใൃ৴͍ͯͨ͠ཧ༝
ཧ༝ ☞ ʮԶ͕ϓϩμΫγϣϯͰ͍͍͔ͨΒʯʹܾ·ͬ ͯΜ͡ΌΜʂ ☞ Έͳ͞Μ͝ڠྗ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂʂʂʂ
݁Ռ yaottiʮXXX Λ AtomShellͰWindows ͚ʹ࡞Εͳ ͍ʁʯ mizchiʮ͋͊ʈʙ͍͍ͬ͢Ͷʙʯ ɹ mizchiʮϓϩτͰ React
͚ͬͨͲ͜Μ··͍͖·͠ ΐ͏ʯ => Go
ʮͬͯΈͨʯ ☞ ਓபʹͳͬͨ ☞ ͱ͍͏Θ͚ͰReactΛݱͰͬͯΈͨΛ͠·͢ (ΈΜͳVirtual DOM ༧शࡁΈͩΑͶʁ)
ࠓͷςʔϚ Real World Virtual DOM ☞ ୈҰষ: Kobito on AtomShell
☞ ୈೋষ: Arda - MetaFlux Framework ☞ ୈࡾষ: Isormorphicͷ࣮ફ ☞ ࠷ޙʹ: Virtual DOM ΛͱΓ·͘ݱ࣮
ୈҰষ Kobito on Atom Shell
Kobitoͱ ☞ Increments͕։ൃ ☞ MarkdownͰϝϞΛॻ͚ΔMacΞϓϦ ☞ Qiita(·ͨQiita:Team)ͷಉظػೳ͕͋Δ ☞ Objective-C
Mac൛
Kobito "on AtomShell" ☞ Kobito Λ AtomShell Ͱ࣮ͯ͠Windows൛ͩͦ ͏͍ͥͬͯ͏ϓϩδΣΫτ ☞
ࠓ͕ॳެ։
Kobito "on AtomShell" ☞ ։ൃಈػ: WindowsͷKobito͕ͳ͍ ☞ σεΫτοϓΞϓϦ ☞ طଘͷKobitoͷΫϩʔϯͰͳ͘ɺ͍͔ͭ͘ͷ՝
Λղܾͭͭ͠։ൃ ☞ View React Component + ࣗ࡞Flux Framework
(ը໘։ൃதͷͷͰ͢)
(ը໘։ൃதͷͷͰ͢)
σϞ
Ճཁૉ ☞ Qiita / Qiita:Team ͱͷಉظػೳΛڧԽ ☞ ϩʔΧϧʹดͨ͡InboxͷՃ ☞ ୯७ͳϝϞπʔϧͱͯ͠ͷ͍উखΛڧԽ
☞ Vim ΩʔόΠϯυϞʔυͷՃ(։ൃऀͷझຯ)
Kobito for Windows ☞ ϦϦʔε༧ఆ: 2015 4݄~5݄ ☞ => Kobito
for Windows Newsletter
։ൃաఔ ☞ اը / ϓϩτ 10݄ޙ ~ ☞ ઃܭ -
11݄ ~ ☞ ࣮ - 12݄~ ☞ όάચ͍ग़͠ͱϦϑΝΫλ(͍·͜͜) ΤϯδχΞ1ਓ(mizchi) 1݄͔ΒϚʔΫΞοϓ1ਓ
ϥΠϒϥϦͷ༻ײ
݁ہReactͱͳΜͩͬͨͷ͔
Just the UI ☞ ୯ͳΔʮσʔλόΠϯυ͖ςϯϓϨʔτΤϯδ ϯʯͰɺඳըޙ࠶ར༻Մೳͳίϯϙʔωϯτ ☞ ඞཁेʹ͍(͕͢͞ʹ৬ਓܳతͳDOMνϡʔχ ϯάʹྼΔ) ☞
ࠓ·Ͱۤ࿑͍ͯͨ͠ঢ়ଶભҠ͕ࢮ͵΄Ͳ୯७Խ͞ ΕΔ
ԾDOMͱͯ͠ͷReactબఆཧ༝ ☞ ใ͕ेʹ͋Δ(ͨͩ͠ւ֎த৺) ☞ ϔουϨεڥ(node)Ͱͷςετέʔεͷॻ͖ ͢͞ॏࢹ ɹ ଞͷڥͳΒͬͱখ͍͞ϥΠϒϥϦΛ͍ͬͯ ͔ͨɻQiita ʹ·ͩೖΕͯͳ͍ɻ
ʮຊ࣭తͳ෦ʯʹूதͰ͖Δ ☞ ઃܭ͕୯७Խ͞Εͨ݁ՌɺΞϓϦέʔγϣϯυϝ Πϯ͕໌֬ʹҙࣝͰ͖ΔΑ͏ʹ ☞ Pure JavaScript, ͍ΘΏΔʮIsomorphicԽʯՄೳͳ ՕॴʹྗͰ͖Δ(͋ͱͰৄ͘͢͠)
QiitaͷϑΟʔυόοΫ(༧ఆ) ☞ ։ൃͨ͠ίϯϙʔωϯτ܈Λॱ࣍ϑΟʔυόοΫ ͍͖͍ͯͨ͠ ☞ ͨͱ͑…
Markdown ϋΠϥΠτ͖ͷΤσΟλ
Atom ͷ Cmt+T తͳΠϯΫϦϝϯλϧαʔν
AtomShellʹ͍ͭͯ
AtomShell ☞ Atom Editorͷج൫ ☞ Multi Platform (Win/Mac/Debian) ☞ σεΫτοϓΞϓϦͷҝͷChromium
ϥούʔ
AtomShellͰ࡞ΔϝϦοτ ☞ nodeͷϞδϡʔϧΛݺΔ ☞ ΫϩεΦϦδϯΛ͑ΕΔ ☞ σεΫτοϓΞϓϦͱͯ͠Ͱ͖Δ ☞ ϒϥβετϨʔδͷ্ݶΛҙʹ૿ͤΔ ☞
(BlinkҎ֎ͷಈ࡞֬ೝΛαϘΕΔ)
AtomShellΛબͿڥཁҼ ☞ Webք۾ͩͱWindowsͷݟΛͨΊͯ׆༻͠ʹ ͘͘ɺWPFͷࣝΛ͑Δಈػ͕ͳ͍ ☞ node/HTMLͷϊϋΛ׆͔ͤΔ ☞ HTML/JSͰQiitaͱίϯϙʔωϯτΛڞ༗Ͱ͖Δ
σεΫτοϓΞϓϦέʔγϣϯ ʹͳΔͱͲ͏ͳΔ͔
Ͷ্͕Δظ ☞ Δ͜ͱ࣮࣭SPA ͕ͩ… ☞ ωΠςΟϒΞϓϦͱͯ͠ͷUXΛظ͞ΕΔ ☞ ͦͷͨΊͷ React
ઃܭ࣌ʹʹͳͬͨ͜ ͱ
1. JSX
JSXͱ ☞ ReactͷԾDOMʹ࠷దԽ͞ΕͨJavaScript ͷจ๏ ֦ு var div = <div/>; Έ͍ͨͳͭ
JSXͷ. 1 ☞ JavaScriptͷࣝΛཁٻ͗͢͠Δ ☞ items.map(item => <Item data=item.data/>) ͕Ϧετཁૉ࡞ͬͯΔͷ
Θ͔Δʁ ☞ ඇJSΤϯδχΞͱڠௐ͢Δʹݫ͍͠
JSXͷ. 2 ☞ ଞͷAltJSͱ૬ੑ͕Α͘ͳ͍ ☞ ࠓճCoffeeScriptͱTypeScriptΛ͍ͬͯΔͷͰ ࠷ѱ
JSXͷ. 3 ☞ ςϯϓϨʔτͱີ݁߹͗͢͠Δ ☞ ViewModel Λڧ͘ҙࣝͯ͠ςϯϓϨʔτͱϓϩύ ςΟΛΛࢼΈͨ
ղܾࡦ: react-jade jadejs/react-jade ☞ jadeςϯϓϨʔτ͔ΒReactͷVirtual DOM ͕ు͚ Δ ☞ jadeͷ։ൃݩ͕ఏڙ͍ͯ͠ΔͷͰɺϝϯς͞ΕΔ
ͩΖ͏ͱ͍͏ظ͕͋Δ
react-jade ͷྫ .container h1(onClick=onClickTitle)= This is title ↓ React.createElement('div', {className:
'container'}, [ React.createElement('h1', {onClick: onClickTitle}, 'This is title') ]) // ϔομলུ ͍ΘΏΔhamlܥςϯϓϨʔτ
react-jade ͷ݁Ռ ☞ JSৄ͘͠ͳ͍ਓʮͳΜ͔Α͘Θ͔ΒΜϓϩύςΟ ͕͋Δ͕৮ΕΔʯఔʹམͪண͘ ☞ (Qiitaຊମslim ͍ͬͯ͏എܠ͕͋Δ͔)
։ൃݴޠ ☞ UI: React Component / Dispatcher ☞ CoffeeScriptͰߴʹTry &
Error Λճ͢ ☞ ςϯϓϨʔτreact-jade ☞ Store / Domain ☞ TypeScript ͷ common.jsϞʔυ ☞ CoffeeScript ʹ require ͞ΕΔ(ٯͳ͍)
2. ͲͷઃܭΛ࠾༻͢Δ?
Flux ☞ ୯ํσʔλϑϩʔ ☞ ঢ়ଶཧίετ͕͍VirtualDOMʹ͍ͨઃܭΛ ࣮ݱ͢Δࢥ. (࣮Ͱͳ͍) ☞ ৄ͘͠୭͔͕ͯ͘͠Ε(Δ/ͨ)Ͱ͠ΐ͏ or
͙͙ Ε
ཚཱ͢Δ Flux ࣮ ☞ Fluxxor ☞ Reflux ☞ Alt ☞
Fluxible ☞ Facebook's flux ☞ Deloerean ☞ etc...
Flux࣮ͷݱ࣮ ☞ ബ͍ ☞ Ͳͷ࣮Idiomatic ☞ ͲΕ͕ੜ͖Δ͔Θ͔ΒΜ
ͳΜ͔ͬ͘͠Γ͢Δͷ͕ͳ͍
ʮ͏ࣗ࡞͢Δ͔͠ͳ͍ʂʯ
ͱ͍͏Θ͚Ͱ…
ୈೋষ: Arda - MetaFlux
Arda ☞ mizchi/arda - Github ☞ ݩʑ Kobito on Atom
Shell ͷঢ়ଶཧͱը໘ભ ҠΛநԽͨ͠ͷ ☞ ͦͦ͜͜ςετॻ͍ͯɺ͍ͩͿυοάϑʔσΟϯ ά͍ͯ͠ΔͷͰ࣮༻ʹ͑͏Δͣ
Ardaͷ༝དྷ ☞ JɾRɾRɾτʔϧΩϯͷʮࢦྠޠʯͷੈքͷ໊ લͰ͋ΓٿͦͷͷͰ͋Δ ☞ VirtualDOMͷԾͳੈքͱݱ࣮͕༥߹͢Δॴ͙ Β͍ͷχϡΞϯε ☞ ͿͬͪΌ͚͚ΓΌͳΜͰΑ͔ͬͨ
։ൃͷಈػ ☞ طଘͷFlux࣮ʮը໘ભҠʯ͕දݱ͠ʹ͔ͬ͘ ͨ ☞ react-router͕͍ʹ͔ͬͨ͘/త͕ҧͬͨ ☞ StoreΛTypeScriptϑϨϯυϦʔʹܕͰอޢͰ͖ ΔΑ͏ʹ͔ͨͬͨ͠
ҙࣝͨ͠ͷ ☞ Store/View/DispatcherͷմΛʮContextʯͱ͍͏୯ ҐͰཧ ☞ ContextͷελοΫͰঢ়ଶΛදݱ ☞ React ͷState/Props ͷ֓೦ܧঝ
☞ ͯ͢ͷঢ়ଶભҠΛPromiseԽ
Ґஔ͚ͮ ☞ ୯ͳΔFluxͰͳ͘FluxΛแͨ͠ΑΓ্Ґͷ Framework
None
ϞδϡʔϧΛ୯७ʹ ☞ View୯ͳΔReact.Component ☞ Dispatcher୯ͳΔEventEmitter ☞ StoreEventΛड͚ͯঢ়ଶΛߋ৽
Context ͷσʔλϑϩʔ ➀ Router ͔Βॳظೖྗ(Props)Λड͚ͯॳظԽ͞ΕΔ ➁ Props͔ΒॳظState(Contextঢ়ଶ)Λ࡞Δ ➂ Props ͱ
State ͔ΒɺComponentʹ͢ϓϩύς Ο(ComponentProps)Λੜ ➃ Component ʹ͢ ➄ ঢ়ଶ͕ߋ৽͞ΕͨΒ3ʹΔ
None
Arda.Router ☞ pushContext ☞ popContext ☞ replaceContext ☞ APIͰͯ͠ ☞
ContextͷੜͱഁغΛ୲(SPAͦ͜ΒΜݫ͠ ͍)
ΫϦοΫͰ͕૿͑Δαϯϓϧ class Clicker extends Arda.Component render: -> React.createElement 'button', {onClick:
@onClick.bind(@)}, @props.cnt onClick: -> @dispatch 'clicker:++' class ClickerContext extends Arda.Context @component: Clicker initState: (props) -> cnt: 0 expandComponentProps: (props, state) -> cnt: state.cnt delegate: (subscribe) -> super subscribe 'clicker:++', => @update((s) => cnt: s.cnt+1) router = new Arda.Router(Arda.DefaultLayout, document.body) router.pushContext(ClickerContext, {})
ΫϦοΫͰ͕૿͑Δαϯϓϧ class Clicker extends Arda.Component render: -> React.createElement 'button', {onClick:
@onClick.bind(@)}, @props.cnt onClick: -> @dispatch 'clicker:++' #<= EventEmitterൃՐ class ClickerContext extends Arda.Context @component: Clicker initState: (props) -> cnt: 0 expandComponentProps: (props, state) -> cnt: state.cnt delegate: (subscribe) -> super subscribe 'clicker:++', => #<= EventEmitterͷEventड৴ @update((s) => cnt: s.cnt+1) router = new Arda.Router(Arda.DefaultLayout, document.body) router.pushContext(ClickerContext, {}) Event Ұํ௨ߦ
ΫϦοΫͰ͕૿͑Δαϯϓϧ class Clicker extends Arda.Component render: -> React.createElement 'button', {onClick:
@onClick.bind(@)}, @props.cnt onClick: -> @dispatch 'clicker:++' class ClickerContext extends Arda.Context @component: Clicker initState: (props) -> cnt: 0 #<= ॳظঢ়ଶ expandComponentProps: (props, state) -> cnt: state.cnt #<= ComponentͷProps delegate: (subscribe) -> super subscribe 'clicker:++', => @update((s) => cnt: s.cnt+1) #<= ঢ়ଶͷߋ৽ router = new Arda.Router(Arda.DefaultLayout, document.body) router.pushContext(ClickerContext, {}) Mutable ͳͷ State ͚ͩ
Context Λ TypeScript Ͱهड़͢Δ ͱԿ͕خ͍͠ʁ ☞ ܕʹΑ༷͕ͬͯ໌֬ʹͳΔ ☞ Props ը໘Λ࠶ߏங͢Δͷʹඞཁͳใ
☞ State ͦͷը໘ͷதͰมԽ͢Δঢ়ଶ ☞ ComponentProps ࣮ࡍʹComponent ʹ͞Ε Δͷ
ComponentProps ͕ଘࡏ͢Δҙਤ ☞ ؔ৺ͷ ☞ Component͕Δ͖ঢ়ଶ͚ͩʹมܗ͍ͨ͠ ☞ ܕͰอޢ͠ʹ͍͘Component ʹ Props
ͱ State Λ͢ͷخ͘͠ͳ͍
ͨͱ͑ ☞ Stateͱͯ͠Կ͔ͷ id ͚ͩ࣋ͬͯ DBωοτϫʔ ΫΛୟ͘ͱɺ݁Ռʹ࠶ݱੑ͕ͳ͘ State ͱͯ࣋͠ ͪͨ͘ͳ͍
buildTimelineByGroupId(state.selectedGroupId).then((items) = { this.render(items); // ͜͜Λ࣋ͪͨ͘ͳ͍ });
࠶ݱՄೳͳϏϡʔ ☞ ComponentProps͕ಉ͡ͳΒඞͣಉ͡ϏϡʔΛঢ় ଶΛ࠶ݱͰ͖Δ(ͱ͢Δ) ☞ Component ͱ Props ͷΈ߹Θͤͷ URLͷγ
ϦΞϥΠζ/σγϦΞϥΠζ Λ࣮͢Ε Browser Hisotry ʹରԠՄೳ ☞ Agnosticʹ͍ͨ͠ͷͰArdaͰϒϥβώετϦ ʔΛؔ͠ͳ͍
ଞɺৄ͍͠API ☞ arda.d.ts ͷܕఆٛϑΝΠϧ͕APIυΩϡϝϯτΛ ݉ͶͯΔ ☞ ArdaࣗcoffeescriptͰهड़ ☞ ࠷ॳtypescriptͰॻ͍͕ͨɺϝλϓϩͩΒ͚Ͱܕ ͕ੜ͖ͣɺΘΓʹςετΛଟΊʹॻ͍ͨ
Kobito on Atom Shell Ͱͷ Arda ☞ Context Λ TypeScript
ͰܕͰอޢ͢Δɻ ☞ Component CoffeeScript Ͱࡶʹॻ͍ͯ Event Λ dispatch ͢Δ ☞ EventͷߪಡଆTypeScript Ͱॻ͍͍ͯΔ͕ɺड ͚औΔҾʹ͍͓ͭͯଋఔ
Arda with TypeScript interface Props {firstName: string; lastName: string;} interface
State {age: number;} interface ComponentProps {greeting: string;} class MyContext extends Arda.Context<Props, State, ComponentProps> { initState(props){ return new Promise<State>(done => { setTimeout(done({age:10}), 1000) }) } expandComponentProps(props, state) { return {greeting: 'Hello, '+props.firstName+', '+state.age+' years old'} } } # தུ router.pushContext(MyContext, {firstName: 'Jonh', lastName: 'Doe'})
Arda ͷॻ͖৺ ☞ طଘͷFluxͷऑ͍ΛΧόʔͰ͖ͨͱࢥ͏ ☞ ࣗʹͱͬͯ࠷ߴͳΜͰྲྀߦΒ͍ͤͨ ☞ API֮͑Δ͜ͱগͳ͍ͷͰͬͯ͘Ε!
͍·͙͢ npm install arda --save
ୈࡾষ: Isomorphicͷ࣮ફ
Isomorphicͱ ☞ ʮಉ͡ϥΠϒϥϦ͕nodeͰϒϥβͰಈ͚ ͍͍ΑͶʯͱ͍͏ൃ ☞ browserify/webpackʹΑ࣮ͬͯݱՄೳʹͳͬͨ
ͳͥIsomorphicΛҙࣝͯ͠։ൃ͢ Δ͔ ➀ ͨͱ͑node(iojs)Θͳͯ͘ɺ୯ମςετ nodeͰΔͷ͕؆୯Ͱߴ ➁ ϑϩϯτΤϯυͷ֤छϓϦίϯύΠϥλεΫϥ ϯφʔnode ➂ ىಈίετ͕ߴ͘ෆ҆ఆͳϔουϨεϒϥβ
(phantomjs)ͷ༻Λۃྗආ͚͍ͨ ɹ
Qiita ͱ Atom Shell ಛ༗ͷࣄ ☞ node ͷ global ͱ
ϒϥβͷ window ͕ڞଘ͢Δ ಛघͳڥ ☞ Ռ͍ͣΕQiita࣋ͪࠐΈ͍ͨ ͱ͍͏Θ͚ͰKobito on Atom Shell Ͱ Isomorphic Λڧ͘ҙࣝͯ͠ઃܭͨ͠
Isomorphic ͷҝͷநԽ ☞ ετϨʔδ ☞ DOM
ετϨʔδͷ IsomorphicԽ
minimongo mWater/minimongo ☞ mongodb෩ͷAPIΛ࣋ͬͨӬଓετϨʔδ ☞ อଘઌΛΓସ࣮͑ͯߦڥΛબΔ(IndexedDB/ ΦϯϝϞϦ/MongoDb) ☞ ࠾༻ཧ༝: ݩʑ
meteor ͷҰ෦ͰΑ͘ςετ͞Εͯ ͍Δ
ଞͷީิ ☞ PouchDB, the JavaScript Database that Syncs! ☞ Lightweight
javascript in-memory database: LokiJS
Isomorphic తӡ༻ ☞ ςετڥԼͰΦϯϝϞϦϞʔυʹͯ͠ىಈ ͠ɺςετέʔε͝ͱʹੜ/ഁغ
ଞɺࣗ࡞ϥΠϒϥϦ܈ ☞ mizchi/minimongo-schema εΩʔϚఆٛͷJSON ͔ΒDBॳظԽ ☞ mizchi/factory-dog ↑༻ͷεΩʔϚ͔ΒμϛʔΦϒ δΣΫτͷੜ(ࡶͳfactory-girl࣮) ☞
mizchi/mz-repository ϦϙδτϦύλʔϯ࣮ ☞ mizchi/noo ES6ProxyΛ༻͍ͨ rspec ͷ null object ͬΆ͍ͭͷ࣮
mochaͰͷ࣮ࡍͷίʔυͷҰ෦ schema.databases[0].type = 'memoryDb' global.stubDatabases = -> # helper beforeEach
-> initDatabasesBySchema(schema).then ([db]) -> global.db = new Repository.Database(db) global.Item = db.getCollection('items') global.Team = db.getCollection('teams') afterEach -> delete global.db delete global.Item delete global.Team
React ͷ IsomorphicԽ
Headless React ☞ ϒϥβڥ͕ͳͯ͘ಈ͘(Server Side Rendering ͷҝ) ☞ jsdom Ͱ݁ߏಈ͘
renderToString(...) var Component = React.createClass({ render: function(){return React.createElement('div', {}, 'this
is title');} }); var html = React.renderToString(React.createFactory(Component)()); assert.ok(html.indexOf('this is title') > -1); componentWillMount ·ͰݺΕΔͷ͕ϙΠϯτ (componentDidMountݺΕͳ͍)
JSDOM jsdom = require('jsdom').jsdom; global.document = jsdom('<html><body></body></html>'); global.window = document.parentWindow;
global.navigator = window.navigator; React = require('react/addons'); var el = React.createElement('div'); component = React.addons.TestUtils.renderIntoDocument(el) αʔόʔ(node)ͰΫϦοΫΠϕϯτൃՐςετͰ͖ Δɻ ࢀߟ: JSDOMͱReact.addons.TestUtilsͰReactΛϔου Ϩεʹςετ͢Δ - Qiita
IsomorphicʹΑΔ ࣮ߦϞʔυΓସ͑ͷ࣮ݱ
Kobitoͷ Isomorphic ͷ࣮ફ ☞ src/(.ts, .jade, .coffee) Λ૬ରύεΛҡ࣋ͨ͠··ί ϯύΠϧ͠ lib/(**.js)
☞ browserifyͰ lib/index.js Λ શ෦ೖΓ (node_modulesҎԼͷґଘؚΉ)ͷ bundle.js ͱ͠ ͯϏϧυ (gulpͰ֦ுࢠ͝ͱʹࢹͯࠩ͠Ϗϧυ)
src/ - main.coffee - foo.ts - template.jade lib/ - main.js
- foo.js - template.js public/ - bundle.js # lib node_modules ͷґଘશ෦ೖΓ - index.html node_modules/ - ... test/ - main-test.coffee
Isomorphic ͕Մೳʹͨ͜͠ͱ ☞ ༻్ʹԠ࣮ͨ͡ߦํࣜͷΓସ͑ ☞ ϞδϡϥϦςΟͷ্
࣮ߦϞʔυ1: AtomShell:production ☞ ༻ʹϏϧυࡁΈͷbundle.jsΛͬͯαΠζ ݮ(85MB → 1.8MB) ɹ ݩαΠζ͕େ͖͍ཧ༝ɺnode_modules/* ͷґଘ͕
શ෦ೖ͍ͬͯΔ͍ͤɻ
࣮ߦϞʔυ2: AtomShell:development ☞ AtomShellଂͷnodeΛͬͯɺlib/index͔Β૬ ରύεͰղܾɻ ☞ ֻ͕͔࣌ؒΔbrowserifyΛεΩοϓͰ͖Δ
࣮ߦϞʔυ3: ϒϥβ࣮ߦ ☞ ϒϥβͰbundle.jsΛಡΈࠐΉindex.html ͔Βී ௨ʹىಈ͢Δ͚ͩ ☞ ΫϩεΦϦδϯ੍ʹͻ͔͔ͬΒͳ͍ͷɺωΠ ςΟϒΛݺͿػೳҎ֎࣮ߦՄೳ ☞
Կ͔ʹ͑ͳ͍͔ߟ͍͑ͯΔ…(ମݧ൛ͱ͔ʁ)
࣮ߦϞʔυ4: ୯ମςετ ☞ lib ҎԼͷϑΝΠϧΛ test/**/* ͔Β૬ରύεͰ require࣮ͯ͠ߦ ☞ ϔουϨεͳͷͰͱʹ͔͍҆͘͠ఆ͢Δ
࣮ߦϞʔυ5: End to End Test ☞ ϒϥβϏϧυͱಉ͡Α͏ʹߏங ☞ AtomShell༻ͷSeleniumΞμϓλʔͷઃఆΛαϘ Δ͜ͱ͕Ͱ͖ͨ
͓·͚: browsrify vs webpack webpack͍ΖΜͳ͜ͱ͕ग़དྷա͗ͯɺnode ʹͳ͍ ڍಈ͕ՄೳͳͷͰ Isomorphic ੑΛकΔͨΊʹ͋͑ͯ browserifyΛ͍ͬͯΔɻ
ୈ࢛ষ Virtual DOM ΛͱΓ·͘ݱ࣮
࣮ࡍReactͲ͏ͳΜ ☞ ը໘ʹมԽΛى͜͢/ى͜͠ଓ͚Δͷ͕ѹతʹָ ☞ ͱ͍͑पลϥΠϒϥϦ͕ރΕͯͳ͍ ☞ IssueͰόάใࠂ͠·ͬͨ͘ΓࣗͰforkͯ͠ύο ν͋ͯͨΓͯ͠Δ
Reactͷݒ೦ ☞ αΠζ͕େ͖͍(.min.js Ͱ127k)(jQueryͱಉ͡ ͙Β͍) ☞ ΑΓখ͞ͳ࣮ virtual-dom/deku/mithril/ riot ߟྀʹ͍ΕΔ͖͔ʁ
☞ ͱ͍͑Ұ൪ރΕͯΔ
ʮͲ͏͍͏ઃܭ͕͍͍͔Θ͔ΒΜʯ ☞ Ardaͷେن͚ϓϩδΣΫτεέϧτϯஔ͍ͱ ͘ΜͰͲ͏ͧ ☞ mizchi-sandbox/arda-starter-project ☞ ࣮ࡍͷ Kobito on
AtomShell ͱ΄΅ಉ༷
React vs jQuery ☞ ࢥͷஈ֊ͰίϯϑϦΫτ͍ͯ͠ΔͷͰڠௐ͕ ͍͠ ☞ طଘࢿ࢈ͷҎ͔߱ΒͷɺҰ൪ͷϘτϧωοΫͰ͋ Δ͜ͱ൱Ίͳ͍ ☞
͑ͳ͍Θ͚Ͱͳ͘ ϦʔυΦϯϦʔ ͩͱߟ͑Δ ͱࣗવ
ͦͦjQueryඞཁ? ☞ ͦͷ50ߦͷεύήςΟίʔυɺReactͩͬͨΒ10ߦ ͷComponentʹͳΒͳ͍ʁ ☞ ͦ͏͍͏ࢹΛৗʹ࣋ͭ ☞ खΛಈ͔ͦ͏ʂ
ʮͳʹ͕ͳΜͰjQuery ϓϥάΠϯࣺͯΒΕͳ͍ Μ͡Όʙʯ ☞ <div key='hogefuga'></div> ͰϢχʔΫͳkey ଐੑΛ࣋ͭԾDOMͳΒফ͑ͳ͍ ☞ ίϯςφͷதΛjQueryͷྖҬͱ͢Δ
Kobito on AtomShell ͰjQuery Λ ͬͨՕॴ ☞ εΫϩʔϧྔͷಡΈग़͠ͱߋ৽ ☞ ٖࣅΫϦοΫΠϕϯτͷൃՐ
☞ aλάΛશͯΦʔόʔϥΠυͯ͠AtomShellͷ֎ʹ ग़ͯ͠·Θͳ͍Α͏ʹ
ݱతͳJavaScriptΤϯδ χΞʹٻΊΒΕΔͷ
IsomorphicͷൃͱnodeͷεΩϧ ☞ ΑΓαʔόʔαΠυݴޠͷൃʹۙ͘ͳΔ ☞ σβΠφʔʹͱͬͯͷֶशίετ্͕ΓɺΤ ϯδχΞʹͱͬͯԼ͕Δ ☞ దͳۀମ੍͕ඞཁ ☞ Δ͖͜ͱαʔόʔαΠυnodeΤϯδχΞͱ
શ͘ಉ͡(࣮ߦڥ͕ҟͳΔ)
େنSPAͷઃܭ ☞ ը໘ͷߏஙʹඞཁͳൃɺωΠςΟϒͷΞϓϦ έʔγϣϯΤϯδχΞͱಉ͡ ☞ ࣗήʔϜ։ൃͱAndroidͷܦݧ͕ੜ͖ͨ ☞ ετϨʔδΛѻ͏ͱσʔλཧ͕γϏΞʹ ☞ υϝΠϯۦಈΛҙࣝ͢Δ
☞ RP/FRP
ʮ࠷ۙͷJS֮͑Δ͜ͱ͕ଟ͗͢ ͯΘ͔ΒΜʯ ☞ ͬͱΑ͘ฉ͘ ☞ ಉ͡ײ͕ͩͦͦཁٻ͕ෳࡶԽ͍ͯ͠Δͷ Ͱ… ☞ ͱ͍͑VirtualDOM ઃܭͷ୯७Խํʹಇ͘
ͷͰݱ࣮తʹ࠾༻Մೳ
ࠓͷ·ͱΊ
☞ ݱͰͬͯΈ͚ͨͲେৎ ☞ Reactઃܭͷ୯७Խʹํʹಇ͘ ☞ ϑϩϯτΤϯυIsomorphicԽ͞Ε, node(iojs)ͷ εΩϧʹΑͬͯޮԽ͞ΕΔ ☞ Arda
ʹΑͬͯը໘ભҠΛཧ͠ɺܕʹΑΔʮߗ ͞ʯΛௐઅͰ͖ΔΑ͏ʹͨ͠
Kobito for Windows ΑΖ͓͘͠ئ ͍͠·͢ʂ ☞ 4݄தʹग़͍ͨ͠ ☞ => Kobito
for Windows Newsletter
Increments Ͱ σβΠφ͕Γͳ ͍ ☞ σβΠφͷख͕Γͳͯ͘ਏ͍ ☞ Qiita/Kobito ͷσβΠϯ͍ͨ͠ਓ͖ͯ͘Εʂʂʂ QiitaQiita:TeamͷΛՃͯ͘͠ΕΔσβΠφ
ʔืूʂ - Increments(Qiita)ͷٻਓ - Wantedly