diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml new file mode 100644 index 0000000..cd4737f --- /dev/null +++ b/.github/workflows/github-pages.yml @@ -0,0 +1,20 @@ +name: github-pages +on: + push: + branches: [master] +jobs: + main: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: build + run: | + git -c "user.name=bot" -c "user.email=bot@example" subtree add --prefix pages origin gh-pages + npx @marp-team/marp-cli README.md -o pages/index.html + - id: git_status + run: echo "::set-output name=mod::$(git status pages --porcelain)" + - name: push + if: steps.git_status.outputs.mod != '' + run: | + git -c "user.name=bot" -c "user.email=bot@example" commit -a -m update + git subtree push --prefix pages origin gh-pages diff --git a/README.md b/README.md new file mode 100644 index 0000000..d0dc99d --- /dev/null +++ b/README.md @@ -0,0 +1,354 @@ +--- +marp: true +paginate: true +--- + +# GraphQL概論 + +WebDINO Japan エンジニア +[渡邉浩平](https://github.com/kou029w) + +![w:200](https://github.com/kou029w.png) + +--- + +## [GraphQL](https://graphql.org)とは + +サーバーへの問い合わせ (Query) +```graphql +{ + pokemon(name: "Pikachu") { + classification + } +} +``` + +サーバーからの応答 (Response, JSON形式) +```json +{ + "data": { + "pokemon": { + "classification": "Mouse Pokémon" + } + } +} +``` + +https://graphql-pokemon2.vercel.app + +GraphQLとはAPIのクエリ言語 + +--- + +## GraphQLとは + +- APIのクエリ言語 +- クエリ言語の型を宣言するGraphQLスキーマ言語 +- Webクライアントとサーバーのためのアプリケーション層の仕様 + +:::info +GraphQL以外の身近な言語の例: +- クエリ言語: SQL +- スキーマ言語: [JSON Schema](https://json-schema.org/), [XSD](http://www.w3.org/TR/xmlschema11-1/) +::: + +--- + +## 歴史 + +- 2012年 Facebookによる開発 +- 2015年 オープンソース化 +- 2019年 [GraphQL Foundation](https://graphql.org/foundation/)に移管 + +オープンソースな仕様になっており、自由に[貢献可能](https://github.com/graphql/graphql-spec/blob/main/CONTRIBUTING.md) + +--- + +## 主な仕様 + +1. サーバー: [使用可能なデータの構造とその操作を宣言するための言語 (スキーマ言語)](https://graphql.org/learn/introspection/) +2. クライアント: [サーバーにデータを要求するための言語 (クエリ言語)](https://graphql.org/learn/queries/) +3. サーバー: [クエリの実行方法 (Resolvers)](https://graphql.org/learn/execution/) +4. クライアント: [受け取るデータ形式 (JSON)](https://graphql.org/learn/serving-over-http/#response) + +--- + +## 何でないか + +- データベースではない +- JavaScriptではない + +--- + +## なぜGraphQLを使うのか + +1. 単一リクエスト +2. 型システム +3. 便利な開発ツール + +--- + +### 1. 単一リクエスト + +効率的なデータ読み込み + +オーバーフェッチを最小限に抑え、サーバーへのラウンドトリップを少なくする +FacebookがGraphQLを開発した理由は、[モバイルネイティブアプリへの移行のため](https://reactjs.org/blog/2015/05/01/graphql-introduction.html) +スマホの普及に伴う低速、省電力なデバイスの利用の増加が背景 + +--- + +REST + +![REST](https://imgur.com/VRyV7Jh.png) + +https://www.howtographql.com/basics/1-graphql-is-the-better-rest/ + +--- + +GraphQL + +![GraphQL](https://imgur.com/z9VKnHs.png) + +https://www.howtographql.com/basics/1-graphql-is-the-better-rest/ + +--- + +REST + +1. `GET /users/` +1. `GET /users//posts` +1. `GET /users//followers` + +GraphQL + +1. `GET /?query={user(id:){name,posts{title},followers(last:){name}}}` + +--- + +### 2. 型システム + +さまざまなフロントエンド環境のサポート + +単一APIの構築と正確なデータ構造の維持 +クライアントアプリケーションを実行するフロントエンドフレームワークとプラットフォームの多様化が背景 + +--- + +```graphql= +"""ポケモンを表します""" +type Pokemon { + """このオブジェクトのID""" + id: ID! + + """このポケモンの全国図鑑No.""" + number: String + + """このポケモンの名前""" + name: String + + """このポケモンの重さの最大と最小""" + weight: PokemonDimension + + """このポケモンの高さの最大と最小""" + height: PokemonDimension + + """このポケモンの分類""" + classification: String + + # ... +} +``` + +特定のプログラミング言語に依存しないGraphQLスキーマ言語 + +--- + +```graphql +"""ポケモンを表します""" +type Pokemon { +} + +"""ポケモンの寸法を表します""" +type PokemonDimension { +} +``` + +オブジェクトの種類 + +--- + +```graphql +"""ポケモンを表します""" +type Pokemon { + """このオブジェクトのID""" + id: ID! + + """このポケモンの名前""" + name: String + + """このポケモンの分類""" + classification: String + + """このポケモンの高さの最大と最小""" + height: PokemonDimension +} +``` + +オブジェクトに含まれるフィールド + +--- + +```javascript +// JavaScript +const pokemonQuery = `{ + pokemon(name: "Pikachu") { + classification + } +}`; + +fetch(`http://example/?${new URLSearchParams({ query: pokemonQuery })}`) + .then(r => r.json()) + .then(({ data }) => console.log(data?.pokemon?.classification)); +// => "Mouse Pokémon" +``` + +```kotlin +// Kotlin +val response = apolloClient.query(pokemonQuery).await() +Log.d(response?.data?.pokemon?.classification) +``` + +```swift +// Swift +apollo.fetch(query: pokemonQuery) { result in + guard let data = try? result.get().data else { return } + print(data.pokemon?.classification) +} +``` + +https://www.apollographql.com + +--- + +### 3. 便利な開発ツール + +短期間での開発 + +クライアントアプリケーションの設計変更に対応するためのツールが提供されている +継続的デプロイ (CD) が背景 + +--- + +IDE + +![GraphiQL](https://raw.githubusercontent.com/graphql/graphiql/main/packages/graphiql/resources/graphiql.jpg) + +[GraphiQL](https://github.com/graphql/graphiql), [GraphQL Playground](https://github.com/graphql/graphql-playground), etc. + +--- + +コードの生成 + +```console +$ graphql-codegen +``` + +使う + +```typescript +import { usePokemonQuery } from "./generated"; + +export default () => { + const { data } = usePokemonQuery(); + return data?.pokemon?.classification; +}; +``` + +[GraphQL Code Generator](https://www.graphql-code-generator.com/) +[React](https://www.graphql-code-generator.com/docs/plugins/typescript-react-query), [Vue](https://www.graphql-code-generator.com/docs/plugins/typescript-vue-apollo), [Kotlin](https://www.graphql-code-generator.com/docs/plugins/kotlin), etc. + +--- + +## まとめ + +- GraphQLとはデータを問い合わせるクエリ言語仕様と周辺技術 +- 単一リクエスト/型システム/便利な開発ツール + +--- + +## 後付 + +--- + +### より理解を深めるための知識 + +- [山本陽平「Webを支える技術」](https://gihyo.jp/book/2010/978-4-7741-4204-3) - HTTPの基礎知識、REST +- [GraphQL \| A query language for your API](https://graphql.org/) +- [How to GraphQL \- The Fullstack Tutorial for GraphQL](https://www.howtographql.com/) + +--- + +### 何を話していないか + +- [言語仕様](https://spec.graphql.org/) +- [エラーレスポンス](http://spec.graphql.org/June2018/#sec-Errors) +- [Validation](https://graphql.org/learn/validation/) +- [Execution](https://graphql.org/learn/execution/) +- [Subscription](https://spec.graphql.org/June2018/#sec-Subscription) +- [Introspection](https://graphql.org/learn/introspection/) + +--- + +### JSON Serialization + +GraphQL Value |JSON Value +---|--- +Map |Object +List |Array +Null |null +String |String +Boolean |true or false +Int |Number +Float |Number +Enum Value |String + +https://spec.graphql.org/June2018/#sec-JSON-Serialization + +--- + +### セキュリティ + +セキュリティの懸念事項は一般的なWebサービスと同様に存在 + +- [OWASP Top Ten](https://owasp.org/www-project-top-ten/) +- [GraphQL \- OWASP Cheat Sheet Series](https://cheatsheetseries.owasp.org/cheatsheets/GraphQL_Cheat_Sheet.html) + +--- + +### 認証・認可 + +GraphQL仕様に含まないので一般的なWebの認証・認可の設計と同様に行う + +- [OpenID](https://openid.net/) +- [OAuth](https://oauth.net/) +- [JWT](https://jwt.io/) + +--- + +### キャッシュ + +HTTP GETメソッドによる一般的な[HTTP キャッシュ](https://developer.mozilla.org/ja/docs/Web/HTTP/Caching)に加え、GraphQLでは[グローバルなオブジェクトの識別子の宣言](https://graphql.org/learn/global-object-identification/)による[キャッシュ](https://graphql.org/learn/caching/)が存在 + +--- + +### (参考程度) 導入するか迷ったら… + +```graphviz +digraph { +apps[shape=diamond,label="モバイルアプリ?"] +apps->GraphQL[label=Yes] +apps->REST[label=No] +{rank=same;apps;GraphQL} +} +```