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
8.1k
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
15
4.9k
Server Side JavaScript のためのバンドル最適化
mizchi
5
6.6k
V8 as a container on CDN Edge worker
mizchi
6
2k
Edge Side Frontend という新領域
mizchi
34
14k
バンドル最適化マニアクス at tfconf
mizchi
7
4.2k
「たかがJavaScript」のその先 #TECHPLAY
mizchi
47
20k
Deno Node 両刀
mizchi
6
2.4k
「フロントエンド領域」を再定義する
mizchi
50
36k
光を超えるためのフロントエンドアーキテクチャ
mizchi
91
23k
Other Decks in Technology
See All in Technology
alecthomas/kong はいいぞ / kamakura.go#7
fujiwara3
1
300
マイクロサービスにおける容易なトランザクション管理に向けて
scalar
0
140
10個のフィルタをAXI4-Streamでつなげてみた
marsee101
0
170
podman_update_2024-12
orimanabu
1
280
OpenAIの蒸留機能(Model Distillation)を使用して運用中のLLMのコストを削減する取り組み
pharma_x_tech
4
560
小学3年生夏休みの自由研究「夏休みに Copilot で遊んでみた」
taichinakamura
0
170
LINEヤフーのフロントエンド組織・体制の紹介【24年12月】
lycorp_recruit_jp
0
530
オプトインカメラ:UWB測位を応用したオプトイン型のカメラ計測
matthewlujp
0
180
Microsoft Azure全冠になってみた ~アレを使い倒した者が試験を制す!?~/Obtained all Microsoft Azure certifications Those who use "that" to the full will win the exam! ?
yuj1osm
2
110
Oracle Cloudの生成AIサービスって実際どこまで使えるの? エンジニア目線で試してみた
minorun365
PRO
4
290
WACATE2024冬セッション資料(ユーザビリティ)
scarletplover
0
210
生成AIのガバナンスの全体像と現実解
fnifni
1
190
Featured
See All Featured
A Tale of Four Properties
chriscoyier
157
23k
Scaling GitHub
holman
458
140k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
2
290
Mobile First: as difficult as doing things right
swwweet
222
9k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
Fireside Chat
paigeccino
34
3.1k
Statistics for Hackers
jakevdp
796
220k
No one is an island. Learnings from fostering a developers community.
thoeni
19
3k
Docker and Python
trallard
42
3.1k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.1k
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