Upgrade to Pro — share decks privately, control downloads, hide ads and more …

イカリング2におけるシングルページアプリケーション

58b40ae3b0db6cf0202a3802e9dd70fe?s=47 cockscomb
October 02, 2017

 イカリング2におけるシングルページアプリケーション

58b40ae3b0db6cf0202a3802e9dd70fe?s=128

cockscomb

October 02, 2017
Tweet

Transcript

  1. ΠΧϦϯάʹ͓͚Δ
 γϯάϧϖʔδΞϓϦέʔγϣϯ

  2. id:cockscomb Ճ౻ਘथ גࣜձࣾ͸ͯͳ γχΞΞϓϦέʔγϣϯΤϯδχΞ ΠΧϦϯάͷ5FDI-FBE

  3. ˜/JOUFOEP

  4. ΠΧϦϯά w /JOUFOEP4XJUDI0OMJOFΞϓϦ಺෦ͷαʔϏε w 4QMBUPPOͷϓϨΠσʔλΛݟΔ͜ͱ͕Ͱ͖Δ

  5. ࠾༻ٕज़ w ϑϩϯτΤϯυ͸41" w 5ZQF4DSJQU w 3FBDU 3FEVY w ཪଆʹ͸ΦʔέετϨʔγϣϯ૚ͱͯ͠ͷ"1*αʔόʔ

    w 1FSM w %PDLFSͰಈ͍͍ͯΔ
  6. લఏ w ͳΜͰ΋Ͱ͖ΔνʔϜ w 8FCΞϓϦέʔγϣϯ w J04"OESPJEͷωΠςΟϒΞϓϦ w 41"͸ॳΊͯ w

    σβΠφʔ͕3FBDU$PNQPOFOUΛ৮ΕΔ
  7. w ٕज़બఆ w 3FBDUͱ3FEVYʹΑΔεςʔτϑϧΞϓϦέʔγϣϯ w 3FEVY4BHB w 8FCϖʔδͱͯ͠ͷ41"

  8. ٕज़બఆ

  9. 41"ʹ͢Δཧ༝ w /JOUFOEP4XJUDI0OMJOFΞϓϦ಺ͷαʔϏε w ΞϓϦʹظ଴͞ΕΔϦονͳମݧ w J04"OESPJEͷ8FC7JFXͰදࣔͰ͖Ε͹Α͍

  10. 41"ʹ͢Δཧ༝ w αʔϏεͷಛੑ w ࠶๚͕ଟ͍
 ˠΫϥΠΞϯταΠυΩϟογϡͷޮՌ͕ߴ͍ w 17ηογϣϯൺ͕େ͖͍
 ˠॳճͷಡΈࠐΈ଎౓ΑΓͦͷޙͷମݧΛॏࢹ

  11. Ұൠతʹ41"Λ࠾༻Ͱ͖Δ͔ w 41"ʹ͢ΔϢʔβʔϝϦοτͱ։ൃ޻਺ͷఱṝ w ૝ఆ͞ΕΔར༻ύλʔϯ͕41"ʹϚον͢Δ͔ w ηογϣϯ೔ɺ17ηογϣϯ͕ଟ͚Ε͹૬ੑ͕͍͍ w ݕࡧ΍4/4͔ΒͷϏδλʔ͕ଟ͚Ε͹ॳճͷಡΈࠐΈΛૣ͘͢Δ w

    αϙʔτର৅ͷϒϥ΢β w 4&0ͷॏཁੑ
  12. ࠷ޙ͸༐ؾ w ͍ͥͬͨʹࣗ෼ͰͳΜͱ͔͢Δܾҙ

  13. 3FBDUͱ3FEVYʹΑΔ
 εςʔτϑϧΞϓϦέʔγϣϯ

  14. εςʔτϑϧΞϓϦέʔγϣϯ w )551ϦΫΤετʹରͯ͠)551ϨεϙϯεΛฦ͢
 ˠεςʔτϨε w σʔλϕʔεͰӬଓԽ w ηογϣϯʹΑͬͯ࿈ଓੑΛอͭ w 41"͸(6*ΞϓϦέʔγϣϯ


    ˠεςʔτϑϧ
  15. Component Props Component Component Component Component Component Virtual DOM Virtual

    DOM Virtual DOM Props Props 3FBDU w ΞϓϦέʔγϣϯ͸
 $PNQPOFOUͷू߹ମ w $PNQPOFOU͸ೖྗΛݩʹ
 ৽ͨͳ$PNQPOFOUΛग़ྗ͢Δ
 ؔ਺ͱΈͳͤΔ w ࠷ऴతʹ͸%0.$PNQPOFOUΛ ग़ྗ͢Δ
  16. σʔλϑϩʔ w 1SPQT
 ˠ֎෦͔Βͷೖྗ w 4UBUFT
 ˠ$PNQPOFOU಺ͷঢ়ଶ w $POUFYU
 ˠࢠଙ$PNQPOFOUʹ఻ΘΔঢ়ଶ

  17. ࣌ࠁ import * as React from 'react'; interface TimeProps {

    time: Date, } export const Time: React.SFC<TimeProps> = ({time}) => { return <time dateTime={time.toISOString()}>{time.toLocaleString()}</time>; };
  18. ͭͷ$PNQPOFOU w 4UBUFMFTT'VODUJPOBM$PNQPOFOU w 1VSF$PNQPOFOU w $PNQPOFOU

  19. 4UBUFMFTT'VODUJPOBM$PNQPOFOU w ؔ਺ w ঢ়ଶΛ࣋ͨͳ͍ Component Props Component Component Props

  20. 1VSF$PNQPOFOU w Ϋϥε w ঢ়ଶΛ࣋ͭ w 4UBUFT͸JNNVUBCMFͳΦϒδΣΫτ Component Props Component

    Component Props States
  21. $PNQPOFOU w Ϋϥε w ঢ়ଶΛ࣋ͭ w 4UBUFT͸JNNVUBCMFͱ͸ݶΒͳ͍ Component Props Component

    Component Props States
  22. ͭͷ$PNQPOFOU w 4UBUFMFTT'VODUJPOBM$PNQPOFOU͕࠷΋୯७ w 1VSF$PNQPOFOUΛ࢖͏͜ͱ͕ଟ͍

  23. *NNVUBCMF w σʔλ͕JNNVUBCMFͰ͋Δํ͕౎߹͕͍͍ w ݹ͍஋ͱ৽͍͠஋͕ಉ͡ͳΒԿ΋͠ͳ͍͍ͯ͘ w *NNVUBCMFͳΦϒδΣΫτ͸===ͰൺֱͰ͖Δ

  24. *NNVUBCMF w 0CKFDUBTTJHO
 const newObj = Object.assign({}, oldObj, { key:

    value }) w 4QSFBE0QFSBUPS
 const newObj = { ...oldObj, key: value } w *NNVUBCMFKT
  25. Store Reducer State Action dispatch subscribe 3FEVY w ୯Ұͷ4UPSFʹશͯͷঢ়ଶ w

    TVCTDSJCFͰมԽΛݕ஌Ͱ͖Δ w 0CTFSWFSύλʔϯ w ঢ়ଶΛม͍͑ͨͱ͖͸
 4UPSFʹ"DUJPOΛૹΔ w 3FEVDFS͕"DUJPOʹԠͯ͡
 ঢ়ଶΛมߋ͢Δ
  26. "DUJPO͸ϝιουσΟεύον w "DUJPO͸ϝιουͱύϥϝʔλΛ߹Θͤͨ΋ͷ w "DUJPO$SFBUPSͱݺ͹ΕΔϑΝΫτϦʔؔ਺Ͱ࡞Δ w 3FEVDFS͸4UPSFΛมߋ͢ΔͨΊͷϨγʔό w DPNCJOF3FEVDFSTͰෳ਺ͷ3FEVDFSΛ૊Έ߹Θͤͯ 4UPSFΛ෼ׂ౷࣏͢Δ

  27. 3FBDU3FEVY Component Component Component Component Virtual DOM Virtual DOM Virtual

    DOM Props Props Component Component
  28. 3FBDU3FEVY Connected Provider Connected Component Component Component Component Virtual DOM

    Virtual DOM Virtual DOM Props Props Component Component
  29. 3FBDU3FEVY w 1SPWJEFS͕DPOUFYUͰ4UPSFΛࢠଙ$PNQPOFOUʹఏڙ w DPOOFDUؔ਺Ͱ$PNQPOFOUΛ4UPSFͱ઀ଓ w 4UPSFΛTVCTDSJCFͯ͠1SPQTʹม׵͢Δ w ΠϕϯτΛ"DUJPOͱͯ͠4UPSFʹ఻͑Δ w

    ˠ%*
  30. ࣌ࠁ import * as React from 'react'; interface TimeProps {

    time: Date, } export const Time: React.SFC<TimeProps> = ({time}) => { return <time dateTime={time.toISOString()}>{time.toLocaleString()}</time>; };
  31. ࣌ࠁ import * as React from 'react'; import {connect} from

    'react-redux'; interface TimeProps { time: Date, } const Time: React.SFC<TimeProps> = ({time}) => { return <time dateTime={time.toISOString()}>{time.toLocaleString()}</time>; }; export default connect(state => ({ time: state.time }))(Time);
  32. 3FEVY w ΞϓϦέʔγϣϯશମͷঢ়ଶ w 0CTFSWFSύλʔϯͱ%* w 4UPSFͷઃܭ͕ॏཁ w 3FEVDFSͷ૊Έ߹ΘͤͰ෼ׂ౷࣏ w

    Կ΋͔΋3FEVYͷ4UPSFʹೖΕΔඞཁ͸ͳ͍
  33. 8FC"1*ͷϨεϙϯε w 3FEVYͷ4UPSFʹͲ͏อ࣋͢Δͷ͔ w ϦιʔεͷεςʔτϚγϯ w ະऔಘɾ௨৴தɾऔಘࡁΈɾऔಘࣦഊ w RemoteResource<T, E>

  34. 3FNPUF3FTPVSDF5 & empty pending resolved<T> failed<E> request succeeded failed reload

    reload
  35. 3FNPUF3FTPVSDF5 & w latestValueͱͯ͠࠷ޙͷ஋Λอ͓࣋ͯ͘͠ w Ϧϩʔυதʹ஋͕ফ͑ͳ͍ w औಘʹ੒ޭͨ࣌͠ࠁ΋อ͓࣋ͯ͘͠ͱศར w ߴ֊ؔ਺


    RemoteResource<T, E>.map<U>((T) -> U) -> RemoteResource<U, E>
  36. 3FNPUF3FTPVSDF5 & enum State { EMPTY = "empty", PENDING =

    "pending", RESOLVED = "resolved", FAILED = "failed", } abstract class RemoteResource<T, E> { abstract state: State; abstract latestValue: T | null; abstract error: E | null; }
  37. 3FNPUF3FTPVSDF5 & w ݱࡏͷঢ়ଶʹΑΒͣ࣍ͷঢ়ଶΛද͢࢓૊Έ΋࡞Δ
 RemoteResource<T, E>.apply(Next<T, E>) -> RemoteResource<T, E>

    w "DUJPOʹ͸Next<T, E>͚ͩ࣋ͨͤΔ w 3FEVDFS͕apply͢Δ
  38. 3FEVY4BHB

  39. 3FEVY w 3FEVY͸ঢ়ଶͷ؅ཧʹಛԽ͍ͯ͠Δ w ࡞༻ w ݱ࣮ͷΞϓϦέʔγϣϯ͸෭࡞༻Λ࣋ͭ

  40. 3FEVY4BHB w 3FEVYNJEEMFXBSF w ෭࡞༻΍ඇಉظੑΛղܾ͢Δ w (FOFSBUPSGVODUJPO

  41. ࣌ࠁ const updateTime = createAction('UPDATE_TIME',
 (time: Date) => ({ time:

    time })); const timeReducer = handleAction(updateTime,
 (state, action) => action.payload!.time, new Date() ); function * ticktack() { while (true) { yield put(updateTime(new Date())); yield delay(1000); } } function * rootSaga() { yield all([ fork(ticktack), ]); }
  42. ࣌ࠁ const sagaMiddleware = createSagaMiddleware(); const store = createStore( combineReducers({

    time: timeReducer, }), applyMiddleware(sagaMiddleware) ); sagaMiddleware.run(rootSaga);
  43. ࣌ࠁ import * as React from 'react'; import {connect} from

    'react-redux'; interface TimeProps { time: Date, } const Time: React.SFC<TimeProps> = ({time}) => { return <time dateTime={time.toISOString()}>{time.toLocaleString()}</time>; }; export default connect(state => ({ time: state.time }))(Time);
  44. 3FEVY4BHB w 8FC"1*΁ͷΞΫηε w takeF⒎FDUͰGetSomeRequested"DUJPOΛ଴ͭ w ϦΫΤετ͢Δ w putF⒎FDUͰSomeRecieved"DUJPOΛ౤͛Δ

  45. 8FCϖʔδͱͯ͠ͷ41"

  46. 8FCϖʔδͱͯ͠ͷ41" w 41"͸8FCϒϥ΢βͰಈ࡞͢Δ w 8FCϒϥ΢βʹ͸8FCಛ༗ͷࣄ৘͕͋Δ w 63- w )JTUPSZ

  47. 63- w 3FBDU3PVUFSW w શͯͷϖʔδʹ63-ΛׂΓৼΔ w MPDBUJPOͷมԽʹԠͯ͡$PNQPOFOUΛ੾Γସ͑Δ w ։ൃதʹϦϩʔυͰ͖ͯศར w

    (PPHMF"OBMZUJDTͳͲͱ΋૬ੑ͕Α͍
  48. )JTUPSZ w ϒϥ΢βͷʮ໭Δʯ͸௚લͷ৔ॴʹ໭Δ w φϏήʔγϣϯͷʮ໭ΔʯϘλϯ w ҙຯ্ͷ্Ґ֊૚ʹ໭ͬͯ΄͍͠ w ͦ͜Ͱ͞Βʹϒϥ΢βͷʮ໭ΔʯΛԡͨ͠Βʁ ໭Δ

  49. )JTUPSZ w ʮ໭Δʯઌ͕௚લͷϖʔδͳΒ
 window.history.back() w ʮ໭Δʯઌ͕௚લͷϖʔδͰͳ͚Ε͹
 window.history.replaceState() A1 A2 A3

    B1 B2 C1 C2 A1 A2 B2
  50. )JTUPSZ w MPDBUJPOʹIJTUPSZTUBUF΋ؚΊΔ w QVTI4UBUFͰIJTUPSZTUBUFʹ௚લ ͷMPDBUJPOΛอଘ͢Δ w IJTUPSZTUBUF͸ʮ໭ΔʯʮਐΉʯ Ͱ෮ݩ͞ΕΔ w

    ৗʹ௚લͷϖʔδ͕ಘΒΕΔ export interface Location { pathname: Pathname; search: Search; state: LocationState; hash: Hash; key: LocationKey; } window.history.pushState({ lastLocation: location, }, "A2", "/a/2");
  51. ·ͱΊ

  52. w 41"͸(6*ΞϓϦέʔγϣϯ w ঢ়ଶͷ؅ཧ͕ॏཁ w 3FBDU 3FEVYͳͲΛ͏·͘࢖͏ w ߴ౓ͳϢʔβʔΠϯλʔϑΣʔεΛ࣮ݱͰ͖Δ