frontend_bearbash_3.pdf

 frontend_bearbash_3.pdf

8ad58ff2bfccf7b4c07b34000c1d6afd?s=128

Kodai Nakamura

August 04, 2018
Tweet

Transcript

  1. ©2018 Wantedly, Inc. "QPMMPͷ঺հͱ͜Ε͔Β *OUSPEVDUJPOPG"QPMMPBOEUIF'VUVSF JSϑϨʔϜϫʔΫ × ϏΞόογϡ ॳ৺ऀษڧձ in

    ळ༿ݪ 4th.Aug.2018 - Kodai Nakamura
  2. ©2018 Wantedly, Inc. "QPMMPͷ঺հͱ͜Ε͔Β *OUSPEVDUJPOPG"QPMMPBOEUIF'VUVSF JSϑϨʔϜϫʔΫ × ϏΞόογϡ ॳ৺ऀษڧձ in

    ळ༿ݪ 4th.Aug.2018 - Kodai Nakamura
  3. ©2018 Wantedly, Inc. Kodai Nakamura Github: @kdnk Twitter: @kdnk__ Software

    Engineer at Wantedly, inc. ৽ଔ JavaScript, TypeScript, React, Rails, Ruby
  4. ©2018 Wantedly, Inc. (SBQI2-ͷͨΊͷϥΠϒϥϦͷ঺հͰ͢

  5. ©2018 Wantedly, Inc. ໨࣍ ‣(SBQI2- "QPMMP ‣"QPMMPͷ͜Ε͔Β

  6. ©2018 Wantedly, Inc. (SBQI2- ‣ ωοτϫʔΫͷ஗͍ϞόΠϧར༻ͷ૿Ճ  3&45ͩͱɺҰͭͷը໘ͷσʔλΛऔಘ͢Δͷʹෳ਺ͷϦΫΤετ͕ඈͿ  ඞཁͷͳ͍ϑΟʔϧυ΋ؚ·Εͯ͠·͏

     (SBQI2-ͩͱɺ౓ͷϦΫΤετͰඞཁͳϑΟʔϧυͷΈΛऔಘͰ͖Δ ‣ 'SPOUFOE'SBNFXPSL1MBUGPSNͷ૿Ճ  3FBDU7VF"OHVMBSJ04"OESPJEʜ  ֤ը໘͝ͱʹඞཁͳσʔλ͸ҟͳΔ ‣ ։ൃαΠΫϧͷߴ଎Խ  ϑϩϯτΤϯυͷཁ๬ʹ߹Θͤͯ3&45ͷ"1*͢Δඞཁ͕͋Δˠ։ൃαΠΫϧͷ௿Լ
  7. ©2018 Wantedly, Inc. (SBQI2- ‣ ωοτϫʔΫͷ஗͍ϞόΠϧར༻ͷ૿Ճ  3&45ͩͱɺҰͭͷը໘ͷσʔλΛऔಘ͢Δͷʹෳ਺ͷϦΫΤετ͕ඈͿ  ඞཁͷͳ͍ϑΟʔϧυ΋ؚ·Εͯ͠·͏

     (SBQI2-ͩͱɺ౓ͷϦΫΤετͰඞཁͳϑΟʔϧυͷΈΛऔಘͰ͖Δ ‣ 'SPOUFOE'SBNFXPSL1MBUGPSNͷ૿Ճ  3FBDU7VF"OHVMBSJ04"OESPJEʜ  ֤ը໘͝ͱʹඞཁͳσʔλ͸ҟͳΔ ‣ ։ൃαΠΫϧͷߴ଎Խ  ϑϩϯτΤϯυͷཁ๬ʹ߹Θͤͯ3&45ͷ"1*͢Δඞཁ͕͋Δˠ։ൃαΠΫϧͷ௿Լ
  8. ©2018 Wantedly, Inc. (SBQI2- ‣ ωοτϫʔΫͷ஗͍ϞόΠϧར༻ͷ૿Ճ  3&45ͩͱɺҰͭͷը໘ͷσʔλΛऔಘ͢Δͷʹෳ਺ͷϦΫΤετ͕ඈͿ  ඞཁͷͳ͍ϑΟʔϧυ΋ؚ·Εͯ͠·͏

     (SBQI2-ͩͱɺ౓ͷϦΫΤετͰඞཁͳϑΟʔϧυͷΈΛऔಘͰ͖Δ ‣ 'SPOUFOE'SBNFXPSL1MBUGPSNͷ૿Ճ  3FBDU7VF"OHVMBSJ04"OESPJEʜ  ֤ը໘͝ͱʹඞཁͳσʔλ͸ҟͳΔ ‣ ։ൃαΠΫϧͷߴ଎Խ  ϑϩϯτΤϯυͷཁ๬ʹ߹Θͤͯ3&45ͷ"1*͢Δඞཁ͕͋Δˠ։ൃαΠΫϧͷ௿Լ
  9. ©2018 Wantedly, Inc. (SBQI2- ‣ ωοτϫʔΫͷ஗͍ϞόΠϧར༻ͷ૿Ճ  3&45ͩͱɺҰͭͷը໘ͷσʔλΛऔಘ͢Δͷʹෳ਺ͷϦΫΤετ͕ඈͿ  ඞཁͷͳ͍ϑΟʔϧυ΋ؚ·Εͯ͠·͏

     (SBQI2-ͩͱɺ౓ͷϦΫΤετͰඞཁͳϑΟʔϧυͷΈΛऔಘͰ͖Δ ‣ 'SPOUFOE'SBNFXPSL1MBUGPSNͷ૿Ճ  3FBDU7VF"OHVMBSJ04"OESPJEʜ  ֤ը໘͝ͱʹඞཁͳσʔλ͸ҟͳΔ ‣ ։ൃαΠΫϧͷߴ଎Խ  ϑϩϯτΤϯυͷཁ๬ʹ߹Θͤͯ3&45ͷ"1*͢Δඞཁ͕͋Δˠ։ൃαΠΫϧͷ௿Լ
  10. ©2018 Wantedly, Inc. (SBQI2- ‣ 2VFSZ ‣ .VUBUJPO ‣ 4VCTDSJQUJPO

  11. ©2018 Wantedly, Inc. (SBQI2- 2VFSZ type Person { name: String!

    age: Int! posts: [Post!]! } type Post { title: String! author: Person! } ‣ 3&45Ͱ͍͏ͱ(&5 TDIFNBఆٛ { allPersons { name age } } 2VFSZ
  12. ©2018 Wantedly, Inc. (SBQI2- 2VFSZ type Person { name: String!

    age: Int! posts: [Post!]! } type Post { title: String! author: Person! } { allPersons { name age } } ‣ 3&45Ͱ͍͏ͱ(&5 TDIFNBఆٛ { "data": { "allPersons": [ { "name": "Johnny", "age": 23 }, { "name": "Sarah", "age": 20 }, { "name": "Alice", "age": 20 } ] } } 2VFSZ ฦΓ஋
  13. ©2018 Wantedly, Inc. (SBQI2- 2VFSZ type Person { name: String!

    age: Int! posts: [Post!]! } type Post { title: String! author: Person! } ‣ 3&45Ͱ͍͏ͱ(&5 TDIFNBఆٛ { allPersons { name age posts { title } } } 2VFSZ
  14. ©2018 Wantedly, Inc. (SBQI2- 2VFSZ type Person { name: String!

    age: Int! posts: [Post!]! } type Post { title: String! author: Person! } ‣ 3&45Ͱ͍͏ͱ(&5 TDIFNBఆٛ "data": { "allPersons": [ { "name": "Johnny", "age": 23, "posts": [ { "title": "GraphQL is awesome" }, { "title": "Relay is a powerful …" } ] }, { "name": "Alice", "age": 20, "posts": [] } ] } ฦΓ஋ { allPersons { name age posts { title } } } 2VFSZ
  15. ©2018 Wantedly, Inc. (SBQI2- 2VFSZ type Person { name: String!

    age: Int! posts: [Post!]! } type Post { title: String! author: Person! } ‣ 3&45Ͱ͍͏ͱ(&5 TDIFNBఆٛ { "data": { "allPersons": [ { "name": "Alice" }, { "name": "Bob" } ] } } ฦΓ஋ { allPersons(last: 2) { name } } 2VFSZ
  16. ©2018 Wantedly, Inc. (SBQI2- .VUBUJPO type Person { name: String!

    age: Int! posts: [Post!]! } type Post { title: String! author: Person! } TDIFNBఆٛ mutation { createPerson(name: "Bob", age: 36) { name age } } 2VFSZ ‣ 3&45Ͱ͍͏ͱ(&5Ҏ֎
  17. ©2018 Wantedly, Inc. (SBQI2- .VUBUJPO type Person { name: String!

    age: Int! posts: [Post!]! } type Post { title: String! author: Person! } TDIFNBఆٛ mutation { createPerson(name: "Bob", age: 36) { name age } } ฦΓ஋ 2VFSZ { "data": { "createPerson": { "name": "Bob", "age": 36 } } } ‣ 3&45Ͱ͍͏ͱ(&5Ҏ֎
  18. ©2018 Wantedly, Inc. (SBQI2- 3FBDU ‣ "QPMMPͰ͸2FVSZ .VUBUJPO͕
 $PNQPOFOUͱͯ͠༻ҙ͞Ε͍ͯΔ ‣

    ͦͷ$PNQPOFOUͷQSPQTͱͯ͠औಘͨ͠ σʔλ͕౉ͬͯ͘Δ const Dogs = ({ onDogSelected }) => ( <Query query={GET_DOGS}> {({ loading, error, data }) => { if (loading) return "Loading..."; if (error) return `Error! ${error.message}`; return ( <select name="dog" onChange={onDogSelected}> {data.dogs.map(dog => ( <option key={dog.id} value={dog.breed}> {dog.breed} </option> ))} </select> ); }} </Query> );
  19. ©2018 Wantedly, Inc. (SBQI2- 3FBDU ‣ "QPMMPͰ͸2FVSZ .VUBUJPO͕
 $PNQPOFOUͱͯ͠༻ҙ͞Ε͍ͯΔ ‣

    ͦͷ$PNQPOFOUͷQSPQTͱͯ͠औಘͨ͠ σʔλ͕౉ͬͯ͘Δ const Dogs = ({ onDogSelected }) => ( <Query query={GET_DOGS}> {({ loading, error, data }) => { if (loading) return "Loading..."; if (error) return `Error! ${error.message}`; return ( <select name="dog" onChange={onDogSelected}> {data.dogs.map(dog => ( <option key={dog.id} value={dog.breed}> {dog.breed} </option> ))} </select> ); }} </Query> ); const GET_DOGS = gql` { dogs { id breed } } `;
  20. ©2018 Wantedly, Inc. (SBQI2- 3FBDU ‣ "QPMMPͰ͸2FVSZ .VUBUJPO͕
 $PNQPOFOUͱͯ͠༻ҙ͞Ε͍ͯΔ ‣

    ͦͷ$PNQPOFOUͷQSPQTͱͯ͠औಘͨ͠ σʔλ͕౉ͬͯ͘Δ const Dogs = ({ onDogSelected }) => ( <Query query={GET_DOGS}> {({ loading, error, data }) => { if (loading) return "Loading..."; if (error) return `Error! ${error.message}`; return ( <select name="dog" onChange={onDogSelected}> {data.dogs.map(dog => ( <option key={dog.id} value={dog.breed}> {dog.breed} </option> ))} </select> ); }} </Query> );
  21. ©2018 Wantedly, Inc. (SBQI2- 3FBDU ‣ "QPMMPͰ͸2FVSZ .VUBUJPO͕
 $PNQPOFOUͱͯ͠༻ҙ͞Ε͍ͯΔ ‣

    ͦͷ$PNQPOFOUͷQSPQTͱͯ͠औಘͨ͠ σʔλ͕౉ͬͯ͘Δ const Dogs = ({ onDogSelected }) => ( <Query query={GET_DOGS}> {({ loading, error, data }) => { if (loading) return "Loading..."; if (error) return `Error! ${error.message}`; return ( <select name="dog" onChange={onDogSelected}> {data.dogs.map(dog => ( <option key={dog.id} value={dog.breed}> {dog.breed} </option> ))} </select> ); }} </Query> );
  22. ©2018 Wantedly, Inc. (SBQI2- 3FBDU ‣ "QPMMPͰ͸2FVSZ .VUBUJPO͕
 $PNQPOFOUͱͯ͠༻ҙ͞Ε͍ͯΔ ‣

    ͦͷ$PNQPOFOUͷQSPQTͱͯ͠औಘͨ͠ σʔλ͕౉ͬͯ͘Δ const Dogs = ({ onDogSelected }) => ( <Query query={GET_DOGS}> {({ loading, error, data }) => { if (loading) return "Loading..."; if (error) return `Error! ${error.message}`; return ( <select name="dog" onChange={onDogSelected}> {data.dogs.map(dog => ( <option key={dog.id} value={dog.breed}> {dog.breed} </option> ))} </select> ); }} </Query> );
  23. ©2018 Wantedly, Inc. ͜Ε͔ΒͲ͏ͳΔʁ

  24. ©2018 Wantedly, Inc. 4VTQFOTF ‣ 3FBDUͰඇಉظϨϯμϦϯάΛ؆୯ʹ
 Ͱ͖Δ࢓૊Έ ‣ ϨϯμϦϯάΛ஗ΒͤΔ͜ͱ͕Ͱ͖Δ const

    Photo = ({ breed }) => ( <Query suspend query={GET_DOG_PHOTO} variables={breed && { breed }}> {({ data }) => { return <Image src={data.dog.displayImage} />; }} </Query> ); IUUQTTQFBLFSEFDLDPNLEOLSFBDUTVTQFOTFPOBQPMMP
  25. ©2018 Wantedly, Inc. 4VTQFOTF ‣ 3FBDUͰඇಉظϨϯμϦϯάΛ؆୯ʹ
 Ͱ͖Δ࢓૊Έ ‣ ϨϯμϦϯάΛ஗ΒͤΔ͜ͱ͕Ͱ͖Δ const

    Photo = ({ breed }) => ( <Query suspend query={GET_DOG_PHOTO} variables={breed && { breed }}> {({ data }) => { return <Image src={data.dog.displayImage} />; }} </Query> ); IUUQTTQFBLFSEFDLDPNLEOLSFBDUTVTQFOTFPOBQPMMP
  26. ©2018 Wantedly, Inc. 4UBUF.BOBHFNFOU ‣ 3FEVYͰ΍͍ͬͯΔΑ͏ͳঢ়ଶ؅ཧΛ"QPMMPͩ ͚ͰͰ͖Δ ‣ (SBQI2-͸TFSWFSʹܨ͕͍ͬͯͳͯ͘΋͍͍ ‣

    σʔλͷͨΊͷීวతͳΫΤϦݴޠ ‣ BQPMMMJOLTUBUFͱ͍͏΋ͷΛ࢖͏ ‣ ঢ়ଶ؅ཧͷ࢓ํ  "QPMMP͸ࣗલͰDBDIFͷ࢓૊ΈΛ͍࣋ͬͯΔ  SFEVYͩͱBDUJPOΛEJTQBUDI  BQPMMPͩͱNVUBUJPO TFSWFSͰ͸ͳ͘DBDIFʹରͯ͠ export const resolvers = { Mutation: { visibilityFilter: (_, { filter }, { cache }) => { cache.writeData({ data: { visibilityFilter: filter } }); return null; }, addTodo: (_, { text }, { cache }) => { const query = gql` query GetTodos { todos @client { id text completed } } `; const previous = cache.readQuery({ query }); const newTodo = { id: nextTodoId++, text, completed: false, __typename: 'TodoItem', }; const data = { todos: previous.todos.concat([newTodo]), }; cache.writeData({ data }); return newTodo; }, } }
  27. ©2018 Wantedly, Inc. 4UBUF.BOBHFNFOU export const resolvers = { Mutation:

    { visibilityFilter: (_, { filter }, { cache }) => { cache.writeData({ data: { visibilityFilter: filter } }); return null; }, addTodo: (_, { text }, { cache }) => { const query = gql` query GetTodos { todos @client { id text completed } } `; const previous = cache.readQuery({ query }); const newTodo = { id: nextTodoId++, text, completed: false, __typename: 'TodoItem', }; const data = { todos: previous.todos.concat([newTodo]), }; cache.writeData({ data }); return newTodo; }, } } ‣ 3FEVYͰ΍͍ͬͯΔΑ͏ͳঢ়ଶ؅ཧΛ"QPMMPͩ ͚ͰͰ͖Δ ‣ (SBQI2-͸TFSWFSʹܨ͕͍ͬͯͳͯ͘΋͍͍ ‣ σʔλͷͨΊͷීวతͳΫΤϦݴޠ ‣ BQPMMMJOLTUBUFͱ͍͏΋ͷΛ࢖͏ ‣ ঢ়ଶ؅ཧͷ࢓ํ  "QPMMP͸ࣗલͰDBDIFͷ࢓૊ΈΛ͍࣋ͬͯΔ  SFEVYͩͱBDUJPOΛEJTQBUDI  BQPMMPͩͱNVUBUJPO TFSWFSͰ͸ͳ͘DBDIFʹରͯ͠
  28. ©2018 Wantedly, Inc. 4UBUF.BOBHFNFOU export const resolvers = { Mutation:

    { visibilityFilter: (_, { filter }, { cache }) => { cache.writeData({ data: { visibilityFilter: filter } }); return null; }, addTodo: (_, { text }, { cache }) => { const query = gql` query GetTodos { todos @client { id text completed } } `; const previous = cache.readQuery({ query }); const newTodo = { id: nextTodoId++, text, completed: false, __typename: 'TodoItem', }; const data = { todos: previous.todos.concat([newTodo]), }; cache.writeData({ data }); return newTodo; }, } } ‣ 3FEVYͰ΍͍ͬͯΔΑ͏ͳঢ়ଶ؅ཧΛ"QPMMPͩ ͚ͰͰ͖Δ ‣ (SBQI2-͸TFSWFSʹܨ͕͍ͬͯͳͯ͘΋͍͍ ‣ σʔλͷͨΊͷීวతͳΫΤϦݴޠ ‣ BQPMMMJOLTUBUFͱ͍͏΋ͷΛ࢖͏ ‣ ঢ়ଶ؅ཧͷ࢓ํ  "QPMMP͸ࣗલͰDBDIFͷ࢓૊ΈΛ͍࣋ͬͯΔ  SFEVYͩͱBDUJPOΛEJTQBUDI  BQPMMPͩͱNVUBUJPO TFSWFSͰ͸ͳ͘DBDIFʹରͯ͠
  29. ©2018 Wantedly, Inc. 4UBUF.BOBHFNFOU export const resolvers = { Mutation:

    { visibilityFilter: (_, { filter }, { cache }) => { cache.writeData({ data: { visibilityFilter: filter } }); return null; }, addTodo: (_, { text }, { cache }) => { const query = gql` query GetTodos { todos @client { id text completed } } `; const previous = cache.readQuery({ query }); const newTodo = { id: nextTodoId++, text, completed: false, __typename: 'TodoItem', }; const data = { todos: previous.todos.concat([newTodo]), }; cache.writeData({ data }); return newTodo; }, } } ‣ 3FEVYͰ΍͍ͬͯΔΑ͏ͳঢ়ଶ؅ཧΛ"QPMMPͩ ͚ͰͰ͖Δ ‣ (SBQI2-͸TFSWFSʹܨ͕͍ͬͯͳͯ͘΋͍͍ ‣ σʔλͷͨΊͷීวతͳΫΤϦݴޠ ‣ BQPMMMJOLTUBUFͱ͍͏΋ͷΛ࢖͏ ‣ ঢ়ଶ؅ཧͷ࢓ํ  "QPMMP͸ࣗલͰDBDIFͷ࢓૊ΈΛ͍࣋ͬͯΔ  SFEVYͩͱBDUJPOΛEJTQBUDI  BQPMMPͩͱNVUBUJPO TFSWFSͰ͸ͳ͘DBDIFʹରͯ͠
  30. ©2018 Wantedly, Inc. ·ͱΊ ‣ SFBDUBQPMMPศར ‣ 3FBDU4VTQFOTFͱ߹Θͤͯඇಉظ௨৴Ͱ͖ΔΑ͏ʹͳΔ ‣ BQPMMPMJOLTUBUF࢖͑͹ɺSFEVYͳͯ͘΋TUBUF؅ཧָ͕ʹͳΔ͔΋