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
Real World Virtual DOM
React, Flux, Isormorphic そして現実
Koutarou Chikuba
February 16, 2015
More Decks by Koutarou Chikuba
See All by Koutarou Chikuba
CI/CD 改善の勘所
mizchi
0
170
極限環境で最終ビルドを絞るためのフロントエンド設計
mizchi
16
5.9k
Server Side JavaScript のためのバンドル最適化
mizchi
5
7.7k
V8 as a container on CDN Edge worker
mizchi
6
2.5k
Edge Side Frontend という新領域
mizchi
35
14k
バンドル最適化マニアクス at tfconf
mizchi
8
4.6k
「たかがJavaScript」のその先 #TECHPLAY
mizchi
47
20k
Deno Node 両刀
mizchi
7
2.6k
「フロントエンド領域」を再定義する
mizchi
50
37k
Other Decks in Technology
See All in Technology
JAWS DAYS 2026でAIの「もやっと」感が解消された話
smt7174
1
130
プロダクトを触って語って理解する、チーム横断バグバッシュのすすめ / 20260411 Naoki Takahashi
shift_evolve
PRO
0
110
ADOTで始めるサーバレスアーキテクチャのオブザーバビリティ
alchemy1115
2
140
マルチモーダル非構造データとの闘い
shibuiwilliam
1
180
GitHub Advanced Security × Defender for Cloudで開発とSecOpsのサイロを超える: コードとクラウドをつなぐ、開発プラットフォームのセキュリティ
yuriemori
1
130
AgentCore RuntimeからS3 Filesをマウントしてみる
har1101
2
200
Podcast配信で広がったアウトプットの輪~70人と音声発信してきた7年間~/outputconf_01
fortegp05
0
230
20260326_AIDD事例紹介_ULSC.pdf
findy_eventslides
0
520
BIツール「Omni」の紹介 @Snowflake中部UG
sagara
0
190
Kubernetes基盤における開発者体験 とセキュリティの両⽴ / Balancing developer experience and security in a Kubernetes-based environment
chmikata
0
170
Strands Agents × Amazon Bedrock AgentCoreで パーソナルAIエージェントを作ろう
yokomachi
2
150
OpenClaw初心者向けセミナー / OpenClaw Beginner Seminar
cmhiranofumio
0
310
Featured
See All Featured
Code Reviewing Like a Champion
maltzj
528
40k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
350
KATA
mclloyd
PRO
35
15k
Bash Introduction
62gerente
615
210k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
64
53k
New Earth Scene 8
popppiees
2
2k
A Tale of Four Properties
chriscoyier
163
24k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.1k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
68
38k
Paper Plane (Part 1)
katiecoart
PRO
0
6.4k
Principles of Awesome APIs and How to Build Them.
keavy
128
17k
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