从 REST 迁移到 GraphQL 的一些思考与实践(响应嵌套的列表结构),参考 Shopify

1、参考:从 REST 迁移到 GraphQL 的一些思考与实践,参考 GitHub。在左侧为模板文件的顶级目录结构。针对每一个顶级目录,需要设置其是否允许新增文件。如图1

图1

2、本计划借鉴 Shopify 的 GraphQL 的响应结构,但是其是直接响应 html 的结构,并未使用 GraphQL。如图2

图2

3、借鉴 Shopify 的 GraphQL 的 products,其中每一个产品皆具有其自身的 图片列表。如图3

图3

{
  products(first: 3) {
    edges {
      node {
        id
        title
        images(first: 3) {
          edges {
            node {
              id
              width
            }
          }
        }
      }
    }
  }
}
{
  "data": {
    "products": {
      "edges": [
        {
          "node": {
            "id": "gid://shopify/Product/6944715342030",
            "title": "commercial kitchen quality",
            "images": {
              "edges": [
                {
                  "node": {
                    "id": "gid://shopify/ProductImage/30455717036238",
                    "width": 1920
                  }
                },
                {
                  "node": {
                    "id": "gid://shopify/ProductImage/30455718838478",
                    "width": 1920
                  }
                }
              ]
            }
          }
        },
        {
          "node": {
            "id": "gid://shopify/Product/6944715636942",
            "title": "Easter Photographing Dress-up Acessories",
            "images": {
              "edges": []
            }
          }
        },
        {
          "node": {
            "id": "gid://shopify/Product/6944715702478",
            "title": "Perfect Pet Hair Remover",
            "images": {
              "edges": []
            }
          }
        }
      ]
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 20,
      "actualQueryCost": 13,
      "throttleStatus": {
        "maximumAvailable": 1000,
        "currentlyAvailable": 987,
        "restoreRate": 50
      }
    }
  }
}

4、Shopify 的 products 相当于模板文件的顶级目录列表。而 每一个产品皆具有其自身的 图片列表,相当于 每一个顶级目录皆具有其自身的 模板文件列表。最终实现了类似的响应结构。如图4

图4

query{
  onlineStoreTheme(themeId: "vogue"){
    ...____
  }
}

fragment ____ on OnlineStoreTheme {
  themeFirstLevelAssets {
    name
    creatable
    themeAssets {
      id
      key
    }
  }
}

{
  "data": {
    "onlineStoreTheme": {
      "themeFirstLevelAssets": [
        {
          "name": "Assets",
          "creatable": false,
          "themeAssets": [
            {
              "id": "1",
              "key": "assets/iconfont/iconfont.css"
            },
            {
              "id": "2",
              "key": "assets/iconfont/iconfont.js"
            },
            {
              "id": "3",
              "key": "assets/iconfont/iconfont.json"
            },
            {
              "id": "4",
              "key": "assets/iconfont/iconfont.woff2"
            }
          ]
        },
        {
          "name": "Auth",
          "creatable": false,
          "themeAssets": [
            {
              "id": "5",
              "key": "auth/login.blade.php"
            },
            {
              "id": "6",
              "key": "auth/register.blade.php"
            }
          ]
        },
        {
          "name": "Components",
          "creatable": false,
          "themeAssets": [
            {
              "id": "7",
              "key": "components/carousel.blade.php"
            },
            {
              "id": "8",
              "key": "components/collections.blade.php"
            },
            {
              "id": "9",
              "key": "components/combinationRecommendation.blade.php"
            },
            {
              "id": "10",
              "key": "components/css.blade.php"
            },
            {
              "id": "11",
              "key": "components/foot.blade.php"
            },
            {
              "id": "12",
              "key": "components/footInfo.blade.php"
            },
            {
              "id": "13",
              "key": "components/footMenu.blade.php"
            },
            {
              "id": "14",
              "key": "components/footSubscribe.blade.php"
            },
            {
              "id": "15",
              "key": "components/footTextImg.blade.php"
            },
            {
              "id": "16",
              "key": "components/header.blade.php"
            },
            {
              "id": "17",
              "key": "components/hotSales.blade.php"
            },
            {
              "id": "18",
              "key": "components/image.blade.php"
            },
            {
              "id": "19",
              "key": "components/imageText.blade.php"
            },
            {
              "id": "20",
              "key": "components/megaMenu.blade.php"
            },
            {
              "id": "21",
              "key": "components/menuCollapsible.blade.php"
            },
            {
              "id": "22",
              "key": "components/publicity.blade.php"
            },
            {
              "id": "23",
              "key": "components/singlecommodity.blade.php"
            },
            {
              "id": "24",
              "key": "components/text.blade.php"
            },
            {
              "id": "25",
              "key": "components/video.blade.php"
            }
          ]
        },
        {
          "name": "Config",
          "creatable": false,
          "themeAssets": [
            {
              "id": "26",
              "key": "config/settings_data.json"
            },
            {
              "id": "27",
              "key": "config/settings_schema.json"
            }
          ]
        },
        {
          "name": "Js",
          "creatable": false,
          "themeAssets": [
            {
              "id": "28",
              "key": "js/address.js"
            },
            {
              "id": "29",
              "key": "js/app.js"
            },
            {
              "id": "30",
              "key": "js/cart.js"
            },
            {
              "id": "31",
              "key": "js/collectionItem.js"
            },
            {
              "id": "32",
              "key": "js/collections.js"
            },
            {
              "id": "33",
              "key": "js/common/banner.vue"
            },
            {
              "id": "34",
              "key": "js/common/cartFreeSpTips.vue"
            },
            {
              "id": "35",
              "key": "js/common/navbar.vue"
            },
            {
              "id": "36",
              "key": "js/common/sortselector.vue"
            },
            {
              "id": "37",
              "key": "js/custom.js"
            },
            {
              "id": "38",
              "key": "js/error404.js"
            },
            {
              "id": "39",
              "key": "js/home.js"
            },
            {
              "id": "40",
              "key": "js/index.js"
            },
            {
              "id": "41",
              "key": "js/login.js"
            },
            {
              "id": "42",
              "key": "js/order.js"
            },
            {
              "id": "43",
              "key": "js/page.js"
            },
            {
              "id": "44",
              "key": "js/productDetail.js"
            },
            {
              "id": "45",
              "key": "js/register.js"
            },
            {
              "id": "46",
              "key": "js/search.js"
            },
            {
              "id": "47",
              "key": "js/view/account/accountbodyaddress.vue"
            },
            {
              "id": "48",
              "key": "js/view/account/accountbodyorder.vue"
            },
            {
              "id": "49",
              "key": "js/view/account/accounttop.vue"
            },
            {
              "id": "50",
              "key": "js/view/account/addressfrom.vue"
            },
            {
              "id": "51",
              "key": "js/view/account/index.vue"
            },
            {
              "id": "52",
              "key": "js/view/cart/index.vue"
            },
            {
              "id": "53",
              "key": "js/view/collections/card.vue"
            },
            {
              "id": "54",
              "key": "js/view/collections/index.vue"
            },
            {
              "id": "55",
              "key": "js/view/product/descriptabs.vue"
            },
            {
              "id": "56",
              "key": "js/view/product/index.vue"
            },
            {
              "id": "57",
              "key": "js/view/product/MediaFlat.vue"
            },
            {
              "id": "58",
              "key": "js/view/product/MediaLeft.vue"
            },
            {
              "id": "59",
              "key": "js/view/product/scrollSlideVertical.vue"
            },
            {
              "id": "60",
              "key": "js/view/product/slideVertical.vue"
            },
            {
              "id": "61",
              "key": "js/view/productlist/index.vue"
            },
            {
              "id": "62",
              "key": "js/view/search/index.vue"
            }
          ]
        },
        {
          "name": "Layouts",
          "creatable": false,
          "themeAssets": [
            {
              "id": "63",
              "key": "layouts/basic.blade.php"
            }
          ]
        },
        {
          "name": "Pages",
          "creatable": false,
          "themeAssets": [
            {
              "id": "64",
              "key": "pages/address.blade.php"
            },
            {
              "id": "65",
              "key": "pages/cart.blade.php"
            },
            {
              "id": "66",
              "key": "pages/collections.blade.php"
            },
            {
              "id": "67",
              "key": "pages/collectiontitem.blade.php"
            },
            {
              "id": "68",
              "key": "pages/custom.blade.php"
            },
            {
              "id": "69",
              "key": "pages/home.blade.php"
            },
            {
              "id": "70",
              "key": "pages/index.blade.php"
            },
            {
              "id": "71",
              "key": "pages/order.blade.php"
            },
            {
              "id": "72",
              "key": "pages/product_detail.blade.php"
            },
            {
              "id": "73",
              "key": "pages/search.blade.php"
            }
          ]
        },
        {
          "name": "Sass",
          "creatable": false,
          "themeAssets": [
            {
              "id": "74",
              "key": "sass/app.scss"
            },
            {
              "id": "75",
              "key": "sass/applications.scss"
            },
            {
              "id": "76",
              "key": "sass/banner.scss"
            },
            {
              "id": "77",
              "key": "sass/collectionItems.scss"
            },
            {
              "id": "78",
              "key": "sass/collections.scss"
            },
            {
              "id": "79",
              "key": "sass/components.scss"
            },
            {
              "id": "80",
              "key": "sass/fonts.scss"
            },
            {
              "id": "81",
              "key": "sass/foot.scss"
            },
            {
              "id": "82",
              "key": "sass/global.scss"
            },
            {
              "id": "83",
              "key": "sass/header.scss"
            },
            {
              "id": "84",
              "key": "sass/hotsales.scss"
            },
            {
              "id": "85",
              "key": "sass/imagetext.scss"
            },
            {
              "id": "86",
              "key": "sass/index.scss"
            },
            {
              "id": "87",
              "key": "sass/pages.scss"
            },
            {
              "id": "88",
              "key": "sass/productDetail.scss"
            },
            {
              "id": "89",
              "key": "sass/publicity.scss"
            },
            {
              "id": "90",
              "key": "sass/text.scss"
            },
            {
              "id": "91",
              "key": "sass/video.scss"
            }
          ]
        },
        {
          "name": "Theme.json",
          "creatable": false,
          "themeAssets": [
            {
              "id": "92",
              "key": "theme.json"
            }
          ]
        }
      ]
    }
  }
}

5、由于模板文件列表,仅需要 key 字段。最后调整后的响应结构。如图5

图5

query{
  onlineStoreTheme(themeId: "vogue"){
    ... ____
  }
}

fragment ____ on OnlineStoreTheme {
  themeAssetList {
    themeId
    name
    key
    creatable
    themeAssetKeys
  }
}

{
  "data": {
    "onlineStoreTheme": {
      "themeAssetList": [
        {
          "themeId": "vogue",
          "name": "Assets",
          "key": "assets",
          "creatable": false,
          "themeAssetKeys": [
            "assets/iconfont/iconfont.css",
            "assets/iconfont/iconfont.js",
            "assets/iconfont/iconfont.json",
            "assets/iconfont/iconfont.woff2"
          ]
        },
        {
          "themeId": "vogue",
          "name": "Auth",
          "key": "auth",
          "creatable": false,
          "themeAssetKeys": [
            "auth/login.blade.php",
            "auth/register.blade.php"
          ]
        },
        {
          "themeId": "vogue",
          "name": "Components",
          "key": "components",
          "creatable": false,
          "themeAssetKeys": [
            "components/carousel.blade.php",
            "components/collections.blade.php",
            "components/combinationRecommendation.blade.php",
            "components/css.blade.php",
            "components/foot.blade.php",
            "components/footInfo.blade.php",
            "components/footMenu.blade.php",
            "components/footSubscribe.blade.php",
            "components/footTextImg.blade.php",
            "components/header.blade.php",
            "components/hotSales.blade.php",
            "components/image.blade.php",
            "components/imageText.blade.php",
            "components/megaMenu.blade.php",
            "components/menuCollapsible.blade.php",
            "components/publicity.blade.php",
            "components/singlecommodity.blade.php",
            "components/text.blade.php",
            "components/video.blade.php"
          ]
        },
        {
          "themeId": "vogue",
          "name": "Config",
          "key": "config",
          "creatable": false,
          "themeAssetKeys": [
            "config/settings_data.json",
            "config/settings_schema.json"
          ]
        },
        {
          "themeId": "vogue",
          "name": "Js",
          "key": "js",
          "creatable": false,
          "themeAssetKeys": [
            "js/address.js",
            "js/app.js",
            "js/cart.js",
            "js/collectionItem.js",
            "js/collections.js",
            "js/common/banner.vue",
            "js/common/cartFreeSpTips.vue",
            "js/common/navbar.vue",
            "js/common/sortselector.vue",
            "js/custom.js",
            "js/error404.js",
            "js/home.js",
            "js/index.js",
            "js/login.js",
            "js/order.js",
            "js/page.js",
            "js/productDetail.js",
            "js/register.js",
            "js/search.js",
            "js/view/account/accountbodyaddress.vue",
            "js/view/account/accountbodyorder.vue",
            "js/view/account/accounttop.vue",
            "js/view/account/addressfrom.vue",
            "js/view/account/index.vue",
            "js/view/cart/index.vue",
            "js/view/collections/card.vue",
            "js/view/collections/index.vue",
            "js/view/product/descriptabs.vue",
            "js/view/product/index.vue",
            "js/view/product/MediaFlat.vue",
            "js/view/product/MediaLeft.vue",
            "js/view/product/scrollSlideVertical.vue",
            "js/view/product/slideVertical.vue",
            "js/view/productlist/index.vue",
            "js/view/search/index.vue"
          ]
        },
        {
          "themeId": "vogue",
          "name": "Layouts",
          "key": "layouts",
          "creatable": false,
          "themeAssetKeys": [
            "layouts/basic.blade.php"
          ]
        },
        {
          "themeId": "vogue",
          "name": "Pages",
          "key": "pages",
          "creatable": false,
          "themeAssetKeys": [
            "pages/address.blade.php",
            "pages/cart.blade.php",
            "pages/collections.blade.php",
            "pages/collectiontitem.blade.php",
            "pages/custom.blade.php",
            "pages/home.blade.php",
            "pages/index.blade.php",
            "pages/order.blade.php",
            "pages/product_detail.blade.php",
            "pages/search.blade.php"
          ]
        },
        {
          "themeId": "vogue",
          "name": "Sass",
          "key": "sass",
          "creatable": false,
          "themeAssetKeys": [
            "sass/app.scss",
            "sass/applications.scss",
            "sass/banner.scss",
            "sass/collectionItems.scss",
            "sass/collections.scss",
            "sass/components.scss",
            "sass/fonts.scss",
            "sass/foot.scss",
            "sass/global.scss",
            "sass/header.scss",
            "sass/hotsales.scss",
            "sass/imagetext.scss",
            "sass/index.scss",
            "sass/pages.scss",
            "sass/productDetail.scss",
            "sass/publicity.scss",
            "sass/text.scss",
            "sass/video.scss"
          ]
        },
        {
          "themeId": "vogue",
          "name": "Theme.json",
          "key": "theme.json",
          "creatable": false,
          "themeAssetKeys": [
            "theme.json"
          ]
        }
      ]
    }
  }
}

 

永夜