$30 off During Our Annual Pro Sale. View Details »

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

cockscomb
October 02, 2017

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

cockscomb

October 02, 2017
Tweet

More Decks by cockscomb

Other Decks in Programming

Transcript

  1. ΠΧϦϯάʹ͓͚Δ

    γϯάϧϖʔδΞϓϦέʔγϣϯ

    View Slide

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

    View Slide

  3. ˜/JOUFOEP

    View Slide

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

    View Slide

  5. ࠾༻ٕज़
    w ϑϩϯτΤϯυ͸41"
    w 5ZQF4DSJQU
    w 3FBDU3FEVY
    w ཪଆʹ͸ΦʔέετϨʔγϣϯ૚ͱͯ͠ͷ"1*αʔόʔ
    w 1FSM
    w %PDLFSͰಈ͍͍ͯΔ

    View Slide

  6. લఏ
    w ͳΜͰ΋Ͱ͖ΔνʔϜ
    w 8FCΞϓϦέʔγϣϯ
    w J04"OESPJEͷωΠςΟϒΞϓϦ
    w 41"͸ॳΊͯ
    w σβΠφʔ͕3FBDU$PNQPOFOUΛ৮ΕΔ

    View Slide

  7. w ٕज़બఆ
    w 3FBDUͱ3FEVYʹΑΔεςʔτϑϧΞϓϦέʔγϣϯ
    w 3FEVY4BHB
    w 8FCϖʔδͱͯ͠ͷ41"

    View Slide

  8. ٕज़બఆ

    View Slide

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

    View Slide

  10. 41"ʹ͢Δཧ༝
    w αʔϏεͷಛੑ
    w ࠶๚͕ଟ͍

    ˠΫϥΠΞϯταΠυΩϟογϡͷޮՌ͕ߴ͍
    w 17ηογϣϯൺ͕େ͖͍

    ˠॳճͷಡΈࠐΈ଎౓ΑΓͦͷޙͷମݧΛॏࢹ

    View Slide

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

    View Slide

  12. ࠷ޙ͸༐ؾ
    w ͍ͥͬͨʹࣗ෼ͰͳΜͱ͔͢Δܾҙ

    View Slide

  13. 3FBDUͱ3FEVYʹΑΔ

    εςʔτϑϧΞϓϦέʔγϣϯ

    View Slide

  14. εςʔτϑϧΞϓϦέʔγϣϯ
    w )551ϦΫΤετʹରͯ͠)551ϨεϙϯεΛฦ͢

    ˠεςʔτϨε
    w σʔλϕʔεͰӬଓԽ
    w ηογϣϯʹΑͬͯ࿈ଓੑΛอͭ
    w 41"͸(6*ΞϓϦέʔγϣϯ

    ˠεςʔτϑϧ

    View Slide

  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Λ
    ग़ྗ͢Δ

    View Slide

  16. σʔλϑϩʔ
    w 1SPQT

    ˠ֎෦͔Βͷೖྗ
    w 4UBUFT

    ˠ$PNQPOFOU಺ͷঢ়ଶ
    w $POUFYU

    ˠࢠଙ$PNQPOFOUʹ఻ΘΔঢ়ଶ

    View Slide

  17. ࣌ࠁ
    import * as React from 'react';
    interface TimeProps {
    time: Date,
    }
    export const Time: React.SFC = ({time}) => {
    return {time.toLocaleString()};
    };

    View Slide

  18. ͭͷ$PNQPOFOU
    w 4UBUFMFTT'VODUJPOBM$PNQPOFOU
    w 1VSF$PNQPOFOU
    w $PNQPOFOU

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  24. *NNVUBCMF
    w 0CKFDUBTTJHO

    const newObj = Object.assign({}, oldObj, { key: value })
    w 4QSFBE0QFSBUPS

    const newObj = { ...oldObj, key: value }
    w *NNVUBCMFKT

    View Slide

  25. Store
    Reducer State
    Action dispatch subscribe
    3FEVY
    w ୯Ұͷ4UPSFʹશͯͷঢ়ଶ
    w TVCTDSJCFͰมԽΛݕ஌Ͱ͖Δ
    w 0CTFSWFSύλʔϯ
    w ঢ়ଶΛม͍͑ͨͱ͖͸

    4UPSFʹ"DUJPOΛૹΔ
    w 3FEVDFS͕"DUJPOʹԠͯ͡

    ঢ়ଶΛมߋ͢Δ

    View Slide

  26. "DUJPO͸ϝιουσΟεύον
    w "DUJPO͸ϝιουͱύϥϝʔλΛ߹Θͤͨ΋ͷ
    w "DUJPO$SFBUPSͱݺ͹ΕΔϑΝΫτϦʔؔ਺Ͱ࡞Δ
    w 3FEVDFS͸4UPSFΛมߋ͢ΔͨΊͷϨγʔό
    w DPNCJOF3FEVDFSTͰෳ਺ͷ3FEVDFSΛ૊Έ߹Θͤͯ
    4UPSFΛ෼ׂ౷࣏͢Δ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  30. ࣌ࠁ
    import * as React from 'react';
    interface TimeProps {
    time: Date,
    }
    export const Time: React.SFC = ({time}) => {
    return {time.toLocaleString()};
    };

    View Slide

  31. ࣌ࠁ
    import * as React from 'react';
    import {connect} from 'react-redux';
    interface TimeProps {
    time: Date,
    }
    const Time: React.SFC = ({time}) => {
    return {time.toLocaleString()};
    };
    export default connect(state => ({ time: state.time }))(Time);

    View Slide

  32. 3FEVY
    w ΞϓϦέʔγϣϯશମͷঢ়ଶ
    w 0CTFSWFSύλʔϯͱ%*
    w 4UPSFͷઃܭ͕ॏཁ
    w 3FEVDFSͷ૊Έ߹ΘͤͰ෼ׂ౷࣏
    w Կ΋͔΋3FEVYͷ4UPSFʹೖΕΔඞཁ͸ͳ͍

    View Slide

  33. 8FC"1*ͷϨεϙϯε
    w 3FEVYͷ4UPSFʹͲ͏อ࣋͢Δͷ͔
    w ϦιʔεͷεςʔτϚγϯ
    w ະऔಘɾ௨৴தɾऔಘࡁΈɾऔಘࣦഊ
    w RemoteResource

    View Slide

  34. 3FNPUF3FTPVSDF5 &
    empty pending resolved
    failed
    request succeeded
    failed
    reload
    reload

    View Slide

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

    RemoteResource.map((T) -> U) -> RemoteResource

    View Slide

  36. 3FNPUF3FTPVSDF5 &
    enum State {
    EMPTY = "empty",
    PENDING = "pending",
    RESOLVED = "resolved",
    FAILED = "failed",
    }
    abstract class RemoteResource {
    abstract state: State;
    abstract latestValue: T | null;
    abstract error: E | null;
    }

    View Slide

  37. 3FNPUF3FTPVSDF5 &
    w ݱࡏͷঢ়ଶʹΑΒͣ࣍ͷঢ়ଶΛද͢࢓૊Έ΋࡞Δ

    RemoteResource.apply(Next) -> RemoteResource
    w "DUJPOʹ͸Next͚ͩ࣋ͨͤΔ
    w 3FEVDFS͕apply͢Δ

    View Slide

  38. 3FEVY4BHB

    View Slide

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

    View Slide

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

    View Slide

  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),
    ]);
    }

    View Slide

  42. ࣌ࠁ
    const sagaMiddleware = createSagaMiddleware();
    const store = createStore(
    combineReducers({
    time: timeReducer,
    }),
    applyMiddleware(sagaMiddleware)
    );
    sagaMiddleware.run(rootSaga);

    View Slide

  43. ࣌ࠁ
    import * as React from 'react';
    import {connect} from 'react-redux';
    interface TimeProps {
    time: Date,
    }
    const Time: React.SFC = ({time}) => {
    return {time.toLocaleString()};
    };
    export default connect(state => ({ time: state.time }))(Time);

    View Slide

  44. 3FEVY4BHB
    w 8FC"1*΁ͷΞΫηε
    w takeF⒎FDUͰGetSomeRequested"DUJPOΛ଴ͭ
    w ϦΫΤετ͢Δ
    w putF⒎FDUͰSomeRecieved"DUJPOΛ౤͛Δ

    View Slide

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

    View Slide

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

    View Slide

  47. 63-
    w 3FBDU3PVUFSW
    w શͯͷϖʔδʹ63-ΛׂΓৼΔ
    w MPDBUJPOͷมԽʹԠͯ͡$PNQPOFOUΛ੾Γସ͑Δ
    w ։ൃதʹϦϩʔυͰ͖ͯศར
    w (PPHMF"OBMZUJDTͳͲͱ΋૬ੑ͕Α͍

    View Slide

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

    View Slide

  49. )JTUPSZ
    w ʮ໭Δʯઌ͕௚લͷϖʔδͳΒ

    window.history.back()
    w ʮ໭Δʯઌ͕௚લͷϖʔδͰͳ͚Ε͹

    window.history.replaceState()
    A1 A2 A3 B1 B2 C1 C2
    A1 A2 B2

    View Slide

  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");

    View Slide

  51. ·ͱΊ

    View Slide

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

    View Slide