어떻게 분류 페이지를 격자와 건전성을 가지게 합니까?io

분류 페이지는 인용 표시나 분류를 통해 사이트 내용을 그룹화하는 좋은 방법이다.나의 개인 사이트에 대해 나는 줄곧 Gridsome, 정적 사이트 생성기와 Sanity를 사용하여 나의 구조화된 내용에 사용하고 있다.지금까지 이 두 가지 도구를 사용하는 것은 좋은 체험이다. 나는 나의 사이트를 위해 분류 페이지를 실현하고 싶다.깊이 연구한 결과 Gridsome은 서로 다른 내용 노드와 belongsTo 노드를 인용하여 서로 다른 내용 유형을 인용함으로써 이 상자를 열면 바로 사용할 수 있는 기능을 지원했다.좋아, 다행이야!보아하니 이것은 매우 직접적인 것 같다.

문제


gridsome 문서에 따라 이 기능을 개발하기 시작했을 때, 클래스 페이지에 Category.vue 템플릿을 만들었습니다. 이 템플릿은 관련 클래스가 있는 모든 유형의 목록을 포함하지만, belongsTo 노드를 사용하여 내용을 조회할 때나는 belongsTo 노드와 sanity-source-gridsome 플러그인과 관련된 문제를 발견했다. 이 플러그인은 나의 건전한 graphql 모드를 가져와 정확한 맵 형식을 얻으며, 하나의 API 요청을 통해 나의 모든 내용을 Gridsome 사이트에서 사용할 수 있도록 한다.문제는 belongsTo 노드에 인용이 있어도!현재 개방적github issue이 있는데 Sanity팀은 이를 더욱 연구할 것이라고 밝혔지만 지금까지 이 기능은 예상대로 작동하지 않고 격자 안에서 분류 페이지를 만들 수 없어서 큰일났다!
그러나 깊이 있는 연구를 한 후에 저는 잠시 저에게 적용되는 해결 방안을 발견했습니다. 즉, Gatsby와 Sanity를 사용하여 분류 페이지를 만드는 Sanity Team 솔루션에서 페이지를 꺼내는 것입니다!Gridsome의 행운은 Vue를 이용한 정적 사이트 생성기임에도 불구하고 Gridsome 팀은 프레임워크를 만들 때 Gatsby로부터 많은 영감을 얻었고, Gatsby와 함께 일하는 많은 것들이 Gridsome에서 많든 적든 같은 방식으로 일할 수 있다는 점이다.그래서 저는 Sanity의 개발자 관계 담당자인 Knut Melvær로부터 CSS 기술에 관한 blog post을 찾았습니다. Gatsby와 Sanity로 분류 페이지를 만드는 것에 관한 것입니다. 과연 비슷한 해결 방안이 Gridsome에도 적용됩니다!따라서 Gridsome의 예상 사용 방식은 아니지만 공식 Sanity 플러그인을 복구하기 전까지는 일시적인 해결 방법이다.

솔루션


따라서 해결 방안은 Gridsome 데이터 저장 API의 일부 기능을 이용하여 인용된 내용을 기존의 데이터 형식에 삽입하고 각 종류를 바탕으로 페이지를 만드는 것이다.거기서, 우리는 Gridsome 모드 API를 사용하여 인용된 내용을 기존의 데이터 형식으로 해석할 수 있으며, 이렇게 하면 우리가 필요로 하는 데이터는 우리의graphql 모드에서 템플릿 페이지에서 조회할 수 있다.

범주 Slug 페이지 만들기


클래스 템플릿 페이지 조회에서 사용할 수 있는 belongsTo 기능을 사용할 수 없기 때문에, 구축할 때 모델의 클래스 세그먼트에서 /categories/vue 페이지와 같은 단일 클래스 페이지를 만들어야 합니다.클래스 형식이 건전한 모드에서 격자 모드로 정확하게 비치고 있음을 알고 있기 때문에, 클래스 형식을 조회하여 createPages 갈고리의 클래스slug와 id를 되돌려주고,slug 루트와 Category.vue 템플릿을 바탕으로 프로그래밍 방식으로 페이지를 만들 수 있습니다.이것은 모든 종류에 대해 정적 페이지를 구축할 것이다.
//gridsome.server.js
module.exports = function(api) {
    api.createPages(async ({ createPage, graphql }) => {
        const { data } = await graphql(`
          {
            allSanityCategory {
              edges {
                node {
                  slug {
                    current
                  }
                  id
                }
              }
            }
          }
        `)
        // If there are any errors in the query, cancel the build and tell us
        if (data.errors) throw data.errors

        // Let‘s gracefully handle if allSanityCategory is null
        const categoryEdges = (data.allSanityCategory || {}).edges || []

        categoryEdges
          // Loop through the category nodes, but don't return anything
          .forEach(({ node }) => {
            // Destructure the id and slug fields for each category
            // const id = node.id
            // const slug = node.slug
            const { id, slug = {} } = node
            // If there isn't a slug, we want to do nothing
            if (!slug) return

            // Create the page using the URL path and the template file, and pass down the id
            // that we can use to query for the right category in the template file
            createPage({
              path: `/categories/${slug.current}`,
              component: './src/templates/Category.vue',
              context: { id }
            })
        })
    })  
}

구조에 인용 형식 추가


다음 단계는 Gridsome 모드 API를 이용하여 새로운 모드 유형을 만드는 것입니다. 이 유형들은 구축할 때 Gridsome GraphQL 모드에 추가됩니다. 이것은 바로 우리가 새로운 ReferencedPostReferencedProject 유형을 만드는 데 사용할 내용입니다. 제 투자 조합에 있어서 이 두 가지 데이터 유형은 현재 두 가지 데이터 유형PostProject으로 분류 집합에 대한 인용을 포함합니다.이 방법은 인용할 형식의 수량에 사용할 수 있으며, 필요에 따라 호출할 수 있습니다.나는 그것들을 인용 유형이라고 부른다. 이 유형들이 그들이 바탕으로 하는 원시 유형과 어떻게 다른지, 그리고 어떻게 나의 사이트에서 그것들을 사용하는지 상하문을 제공한다.이러한 유형은 임의의 수량의 속성이나 속성 유형이 있을 수 있기 때문에 만약에 Sanity의 post 중 3-4개의 속성만 필요하다면 그에 상응하여 비추어 낼 수 있습니다.
일부 건전한 유형은 Gridsome에 비치는 패턴 유형과 일일이 대응하지 않았다는 것을 발견했다.이것은 일부 유형을 건전한 모드에서 격자 모드로 수동으로 비추어야 한다는 것을 의미합니다.이것은 항상 그렇지는 않을 수도 있습니다. 어떤 유형은 이미지 형식과 같은 다른 맵에 확실히 비칩니다.특히 Sanity의 블록 내용 유형은 Gridsome에서 "uraw"내용으로 비치기 때문에 GROQ 응답에서 보듯이 Sanity가 되돌아오는 블록 내용은 접두사 "uraw"가 없습니다.또한 주의해야 할 것은 이 새로운 유형들은 Node 인터페이스를 실현해야 하며, Gridsome은 @infer 명령을 사용하지 않는 한 사용자 정의 필드의 필드 형식을 추정하지 않는다는 것이다.
지금 너는 왜 내가 기존의 유형을 사용할 수 없느냐고 물어볼 수도 있다.이 질문에 대답하기 위해서, 당신은 모델에 이미 존재하는 기존의 건전한 유형을 완전히 사용할 수 있습니다.그러나 GROQ 쿼리 응답의 모든 값을 수동으로 매핑해야 합니다. GROQ 쿼리 응답은 Sanity에서 Gridsome까지의 일대일 매핑이 아니며 유형에 따라 분류 페이지에 많은 데이터가 필요하지 않을 수도 있습니다.이것이 바로 내가 이 목적을 위해 새로운 모델을 만들기로 결정한 이유다.분류 페이지가 postproject 형식 중 어떤 값을 필요로 하는지 알고 있기 때문에 이 해결 방안을 위해 새로운 형식을 만들었습니다.인용 유형을 처리하는 방법을 선택할 수 있지만, 두 가지 선택 모두 가능합니다.
//gridsome.server.js
module.exports = function(api) {
...

api.loadSource(({ addSchemaTypes }) => {
    addSchemaTypes(`
        type ReferencedPost implements Node @infer {
            id: ID!
            title: String
            publishedAt: Date
            mainImage: SanityMainImage
            _rawBody: JSON
            _rawExcerpt: JSON
            path: String
            slug: SanitySlug
            categories: [JSON]
        }
        type ReferencedProject implements Node @infer {
            id: ID!
            title: String
            publishedAt: Date
            mainImage: SanityMainImage
            _rawExcerpt: JSON
            path: String
            slug: SanitySlug
            categories: [JSON]
        }
    `)
    })
...
}

Sanity 참조 조회 및 schemaResolvers 추가


현재 우리는 인용 유형을 정의했습니다. 인용해야 할 모든 유형의 건전성을 조회하고 응답을 새로운 정의 유형에 비추어야 합니다.우리가 이곳에서 Sanity와 함께 사용할 수 있는 멋진 특징 중 하나는 GROQ 이다. 이것은 Sanity의 조회 언어이다.GROQ를 사용하면 사용 가능한 모든 범주의 범주 유형을 조회하고 응답에 유형과 속성을 연결할 수 있습니다.따라서 posts에서 모든 인용projectscategory의 용례를 얻기를 희망하는 경우 GROQ 조회를 작성하여 categorycategoryID를 기반으로 한 모든 게시물을 되돌려 받았습니다. 그 중에서 postcategoryID를 인용했습니다.엽서로 표시된 ui 구성 요소와 일치하도록 post 의 다른 종류 목록도 되돌려줍니다.나는 나의 projects 유형에 대해서도 유사한 조회를 사용했다.
const categoriesQuery = `*[_type == "category" && _id == $categoryID] {
    "posts": *[_type == "post" && references($categoryID)] {
        ..., categories[]->{_id, title, slug}
    }
}`
이 조회를 통해 다음과 같은 JSON 데이터 구조의 출력을 얻었습니다ReferencedPost.
[
    {
        "posts": [
            {
                "_createdAt":"2020-04-28T18:02:39Z"
                "_id":"0f6bb0e4-7009-4b12-9c92-0c3b28f6f1dd"
                "_rev":"0Ox5zGUPjTF8jIyPAfinDK"
                "_type":"post"
                "_updatedAt":"2020-07-11T05:46:12Z"
                "authors":[...]
                "body":
                    [0 - 50]
                    [50 - 100]
                    [100 - 135]
                "categories":[...]
                "excerpt":[...]
                "mainImage":{...}
                "publishedAt":"2020-04-28T06:00:00.000Z"
                "slug":{...}
                "title":"Jamstack Denver Meetup Livestreaming and Recording Setup"
            }   
        ]
    }
]
이것이 바로 우리가 조회의 출력을 우리의 새로운 인용 유형에 비추기 위해 새로운 schemaResolver 을 만들어야 하는 곳이다.우리는 이러한 새로운 모델 유형의 집합을 추가함으로써 이 점을 실현한다. 나는 postsprojects라고 부른다. 그들은 각각ReferencedPostReferencedProject유형의 수조이다.그리고 이 집합을 기존 SanityCategory 형식에 추가하거나 분류 형식에 추가하십시오. 이 종류는 Gridsome에서 이미 매핑된 데이터 구조입니다.이것은 우리가 posts 템플릿에서 projects 조회할 때 allSanityCategoryCategory.vue 집합에 접근할 수 있도록 합니다.
또한 Sanity 프로젝트와 상호 작용하고 필요한 GROQ 조회를 할 수 있도록 @sanity/client 모듈을 가져오는 것이 필요합니다.우리는 건전성 gridsome.server.jsprojectId 으로 그것을 초기화해야 합니다. 이것은 당신이 조회하고자 하는 데이터 집합의 이름입니다.이 값은 당신의 건전한 프로젝트에 유일한 것입니다. 만약 프로젝트 id가 없다면, 건전한 관리 계기판에서 볼 수 있습니다.나는 현재 하나의 단독 프로필에 나의 설정을 설정했지만, 이것도 환경 변수를 통해 완성할 수 있다.여기서 모드 해석기를 생성하여 GROQ 조회를 하고 데이터를 컬렉션 유형에 매핑할 수 있습니다.
//gridsome.server.js
const clientConfig = require('./client-config')
const sanityClient = require('@sanity/client')
const client = sanityClient({
  projectId: clientConfig.sanity.projectId,
  dataset: clientConfig.sanity.dataset,
  useCdn: true // `false` if you want to ensure fresh data
})

module.exports = function(api) {
    api.loadSource(({ addSchemaResolvers }) => {
        addSchemaResolvers({
            SanityCategory: {
                posts: {
                  type: ['ReferencedPost'],
                  async resolve(obj) {
                    const posts = []
                    const categoriesQuery =
                      '*[_type == "category" && _id == $categoryID] {"posts": *[_type == "post" && references($categoryID)]{..., categories[]->{_id, title, slug}}}'
                    const categoriesParams = { categoryID: obj._id }
                    await client.fetch(categoriesQuery, categoriesParams).then(category => {
                      category.forEach(categoryPosts => {
                        categoryPosts.posts.forEach(post => {
                          //Dynamically set the variables that are mapped by gridsome
                          post['id'] = post._id
                          post['_rawBody'] = post.body
                          post['_rawExcerpt'] = post.excerpt
                          post['categories'] = post.categories.map(category => ({
                            id: category._id,
                            title: category.title,
                            slug: category.slug
                          }))
                          post['path'] = `/blog/${post.slug.current}`
                          posts.push(post)
                        })
                      })
                    })
                    return posts
                  }
                },
                projects: {
                  type: ['ReferencedProject'],
                  async resolve(obj) {
                    const projects = []
                    const categoriesQuery =
                      '*[_type == "category" && _id == $categoryID] {"projects": *[_type == "project" && references($categoryID)]{..., categories[]->{_id, title, slug}}}'
                    const categoriesParams = { categoryID: obj._id }
                    await client.fetch(categoriesQuery, categoriesParams).then(category => {
                      category.forEach(categoryProjects => {
                        categoryProjects.projects.forEach(project => {
                          //Dynamically set the variables that are mapped by gridsome
                          project['id'] = project._id
                          project['_rawExcerpt'] = project.excerpt
                          project['categories'] = project.categories.map(category => ({
                            id: category._id,
                            title: category.title,
                            slug: category.slug
                          }))
                          project['path'] = `/projects/${project.slug.current}`
                          projects.push(project)
                        })
                      })
                    })
                    return projects
                  }
                }
            }
        })
    })
}

위의 코드에서 16줄과 43줄, 우리가 유형을 해석할 때, 우리는 dataset 파라미터를 전달했다는 것을 알 수 있습니다.obj 값은 obj 대상이며, SanityCategory 구축 기간에 기본적으로 모든 기존schemaResolvers을 통해 SanityCategoryposts 집합을 사용하여 분석할 수 있도록 순환한다.이런 상황에서resolve 함수도 비동기적이어야 한다. 왜냐하면 모든 함수projects는 전달된 GROQ 조회를 사용하여 우리의 Sanity 데이터 집합에 가져오기 요청을 하기 때문이다.SanityCategory 또한 정의된 매개변수가 있는 객체로서, 이 매개변수는 categoriesParams 속성을 통해 GROQ 질의에 전달됩니다.

질의 템플릿에서 참조되는 유형


모드가 구축되면, 우리는 현재 클래스의 인용 내용 집합에 접근할 수 있으며, $ 템플릿에서graphql를 사용하여 템플릿에 나타나는 다른 데이터를 조회할 수 있습니다.내 사이트에서, 나는 집합을 Category.vuePostCard.vue 구성 요소의 도구로 사용하지만, 당신은 집합을 사용하여 그것들을 나타낼 수 있습니다.
//templates/Category.vue

<template>
...
</template>

<script>
...
</script>

<page-query>
query Category ($id: ID!) {
  metadata {
    sanityOptions {
      projectId
      dataset
    }
  }
  category: sanityCategory(id: $id) {
    id
    title
    posts {
      id
      title
      path
      publishedAt(format: "MMMM D YYYY")
      _rawExcerpt
      _rawBody
      categories
      mainImage {
        asset {
          _id
          url
        }
        caption
        alt
        hotspot {
          x
          y
          height
          width
        }
        crop {
          top
          bottom
          left
          right
        }
      }
    }
    projects {
      id
      title
      path
      publishedAt(format: "MMMM D YYYY")
      _rawExcerpt
      categories
      mainImage {
        asset {
          _id
          url
        }
        caption
        alt
        hotspot {
          x
          y
          height
          width
        }
        crop {
          top
          bottom
          left
          right
        }
      }
    }
  }
}
</page-query>

<style>
...
</style>
이것은 내가 ProjectCard.vue 페이지에 들어갔을 때 얻은 결과이다.이 예에서 트위터 종류는 인용된 블로그 게시물만 있고 항목이 없다는 것을 주의해야 한다.

결론


그렇습니다!Gridsome과 Sanity를 동시에 사용하고 분류 페이지를 만들려면 임시 해결 방법을 찾을 수 있습니다.장기적으로 보면 이것은 이상적인 해결 방안이 아니다. 왜냐하면 Gridsome은 이미 이 점을 실현하기 위해 내장된 방식을 가지고 있기 때문이다. 그러나 /categories/twitch 플러그인 문제가 해결되기 전에 비슷한 결과를 얻을 것이다.나는 반드시 늦게 이 문장을 갱신할 것이다. 그것이 해결된 정확한 해결 방안이 사용될 때, 최종적으로 이것은 여전히 기술적인 해결 방법이기 때문이다.이 해결 방안을 마음대로 수정하십시오. 다른 융통성 있는 방법이나 해결 방안이 있을 수도 있고 같은 결과를 얻을 수도 있습니다.
즐거운 인코딩!

좋은 웹페이지 즐겨찾기