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
8.5k
43
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Real World Virtual DOM
React, Flux, Isormorphic そして現実
Koutarou Chikuba
February 16, 2015
More Decks by Koutarou Chikuba
See All by Koutarou Chikuba
技術記事、 専門家としてのプログラマ、 言語化
mizchi
14
7.7k
CI/CD 改善の勘所
mizchi
0
240
極限環境で最終ビルドを絞るためのフロントエンド設計
mizchi
16
6.1k
Server Side JavaScript のためのバンドル最適化
mizchi
5
7.9k
V8 as a container on CDN Edge worker
mizchi
6
2.6k
Edge Side Frontend という新領域
mizchi
35
14k
バンドル最適化マニアクス at tfconf
mizchi
8
4.7k
「たかがJavaScript」のその先 #TECHPLAY
mizchi
47
21k
Deno Node 両刀
mizchi
7
2.6k
Other Decks in Technology
See All in Technology
PLaMo 3.0 Primeの事後学習
pfn
PRO
0
240
オートマトンと字句解析でRoslynを読む
tomokusaba
0
130
事業成長とAI活用を止めないデータ基盤アーキテクチャの設計思想
hiracky16
0
790
toio・myCobotでフィジカルAIっぽいことを行うための検討(とりあえず調査) / フィジカルAI LT(IoTLTによる開催)
you
PRO
0
220
AI時代の強いチームの作り方
yuukiyo
23
13k
なぜ、あなたのAPIは使われないのか? AX時代の設計原則、ガードレール、運用体制
yokawasa
1
1.2k
信頼できるテスティングAIをどう育てるか?
odan611
0
180
Power Automateアップデート情報
miyakemito
0
290
侵入は突然に 〜 IoTマルウェアと悪用される家庭の機器 ~ / When Intrusion Strikes: IoT Malware and the Abuse of Home Devices
nttcom
0
640
VPCセキュリティ対応の最新事情
nagisa53
2
350
テックカンファレンス三大ステークホルダーの文化人類学 ─ 違いを認め合う関係性作り
bash0c7
5
1.5k
AIツールを導入しても生産性はあがらない? カオナビが直面した 3つの壁と乗り越え方。/ Overcoming 3 Barriers to AI-Driven Productivity at kaonavi
kaonavi
0
1.3k
Featured
See All Featured
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.7k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
450
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.8k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
420
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
470
Are puppies a ranking factor?
jonoalderson
1
3.7k
HDC tutorial
michielstock
2
760
A Modern Web Designer's Workflow
chriscoyier
698
190k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
520
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