Refactor graphql queries

- Remove duplicate queries
- Use smart query in pages/post/_id/_slug/index.vue to avoid multiple db requests for a post and its comments.
We cannot update the apollo cache with asyncData and smart queries have a prefetch policy set to true by default, which
means that they will resolve in a similar timeframe. https://stackoverflow.com/questions/55885337/in-nuxt-should-i-use-asyncdata-or-default-apollo-queries
https://vue-apollo.netlify.com/api/smart-query.html#options
https://vue-apollo.netlify.com/guide/ssr.html#vue-cli-plugin
This commit is contained in:
Matt Rider 2019-08-16 11:25:53 +02:00
parent cd80981130
commit d511d6aa78
8 changed files with 41 additions and 151 deletions

View File

@ -24,10 +24,10 @@
<script>
import gql from 'graphql-tag'
import HcEditor from '~/components/Editor/Editor'
import PostCommentsQuery from '~/graphql/PostCommentsQuery.js'
import CommentMutations from '~/graphql/CommentMutations.js'
import { mapGetters } from 'vuex'
import HcEditor from '~/components/Editor/Editor'
import PostQuery from '~/graphql/PostQuery'
import CommentMutations from '~/graphql/CommentMutations'
export default {
components: {
@ -35,7 +35,6 @@ export default {
},
props: {
post: { type: Object, default: () => {} },
comments: { type: Array, default: () => [] },
},
data() {
return {
@ -77,11 +76,11 @@ export default {
},
update: (store, { data: { CreateComment } }) => {
const data = store.readQuery({
query: PostCommentsQuery(this.$i18n),
query: PostQuery(this.$i18n),
variables: { slug: this.post.slug },
})
data.Post[0].comments.push(CreateComment)
store.writeQuery({ query: PostCommentsQuery(this.$i18n), data })
store.writeQuery({ query: PostQuery(this.$i18n), data })
},
})
.then(res => {
@ -98,14 +97,16 @@ export default {
apollo: {
User: {
query() {
return gql(`{
User(orderBy: slug_asc) {
id
slug
name
avatar
return gql`
{
User(orderBy: slug_asc) {
id
slug
name
avatar
}
}
}`)
`
},
result(result) {
this.users = result.data.User

View File

@ -4,25 +4,25 @@
<span>
<ds-icon name="comments" />
<ds-tag
v-if="comments"
v-if="post.comments"
style="margin-top: -4px; margin-left: -12px; position: absolute;"
color="primary"
size="small"
round
>
{{ comments.length }}
{{ post.comments.length }}
</ds-tag>
&nbsp; Comments
</span>
</h3>
<ds-space margin-bottom="large" />
<div v-if="comments && comments.length" id="comments" class="comments">
<div v-if="post.comments && post.comments.length" id="comments" class="comments">
<comment
v-for="(comment, index) in comments"
v-for="(comment, index) in post.comments"
:key="comment.id"
:comment="comment"
:post="post"
@deleteComment="comments.splice(index, 1)"
@deleteComment="post.comments.splice(index, 1)"
/>
</div>
<hc-empty v-else name="empty" icon="messages" />
@ -31,7 +31,6 @@
<script>
import Comment from '~/components/Comment.vue'
import HcEmpty from '~/components/Empty.vue'
import PostCommentsQuery from '~/graphql/PostCommentsQuery.js'
export default {
components: {
@ -41,29 +40,5 @@ export default {
props: {
post: { type: Object, default: () => {} },
},
data() {
return {
comments: [],
}
},
watch: {
Post(post) {
const [first] = post
this.comments = (first && first.comments) || []
},
},
apollo: {
Post: {
query() {
return PostCommentsQuery(this.$i18n)
},
variables() {
return {
slug: this.post.slug,
}
},
fetchPolicy: 'cache-and-network',
},
},
}
</script>

View File

@ -1,39 +0,0 @@
import gql from 'graphql-tag'
export default i18n => {
const lang = i18n.locale().toUpperCase()
return gql(`
query Post($slug: String!) {
Post(slug: $slug) {
comments(orderBy: createdAt_asc) {
id
contentExcerpt
content
createdAt
disabled
deleted
author {
id
slug
name
avatar
disabled
deleted
shoutedCount
contributionsCount
commentsCount
followedByCount
followedByCurrentUser
location {
name: name${lang}
}
badges {
id
icon
}
}
}
}
}
`)
}

View File

@ -37,9 +37,10 @@ export default i18n => {
name
}
commentsCount
comments(orderBy: createdAt_desc) {
comments(orderBy: createdAt_asc) {
id
contentExcerpt
content
createdAt
disabled
deleted

View File

@ -2,7 +2,7 @@ import gql from 'graphql-tag'
export default i18n => {
const lang = i18n.locale().toUpperCase()
return gql(`
return gql`
query User($id: ID!) {
User(id: $id) {
id
@ -73,5 +73,5 @@ export default i18n => {
}
}
}
`)
`
}

View File

@ -1,38 +0,0 @@
import gql from 'graphql-tag'
export default i18n => {
const lang = i18n.locale().toUpperCase()
return gql(`
query Post($filter: _PostFilter, $first: Int, $offset: Int) {
Post(filter: $filter, first: $first, offset: $offset, orderBy: createdAt_desc) {
id
slug
title
contentExcerpt
shoutedCount
commentsCount
deleted
image
createdAt
disabled
deleted
categories {
id
name
icon
}
author {
id
slug
avatar
name
disabled
deleted
location {
name: name${lang}
}
}
}
}
`)
}

View File

@ -84,7 +84,7 @@ import HcShoutButton from '~/components/ShoutButton.vue'
import HcCommentForm from '~/components/comments/CommentForm'
import HcCommentList from '~/components/comments/CommentList'
import { postMenuModalsData, deletePostMutation } from '~/components/utils/PostHelpers'
import PostQuery from '~/graphql/PostQuery.js'
import PostQuery from '~/graphql/PostQuery'
import HcEmotions from '~/components/Emotions/Emotions'
export default {
@ -122,29 +122,6 @@ export default {
this.title = this.post.title
},
},
async asyncData(context) {
const {
params,
error,
app: { apolloProvider, $i18n },
} = context
const client = apolloProvider.defaultClient
const query = PostQuery($i18n)
const variables = { slug: params.slug }
const {
data: { Post },
} = await client.query({ query, variables })
if (Post.length <= 0) {
// TODO: custom 404 error page with translations
const message = 'This post could not be found'
return error({ statusCode: 404, message })
}
const [post] = Post
return {
post,
title: post.title,
}
},
mounted() {
setTimeout(() => {
// NOTE: quick fix for jumping flexbox implementation
@ -175,6 +152,19 @@ export default {
}
},
},
apollo: {
Post: {
query() {
return PostQuery(this.$i18n)
},
variables() {
return {
slug: this.$route.params.slug,
}
},
fetchPolicy: 'cache-and-network',
},
},
}
</script>
@ -187,7 +177,6 @@ export default {
}
.post-card {
// max-width: 800px;
margin: auto;
.comments {

View File

@ -254,8 +254,9 @@ import HcEmpty from '~/components/Empty.vue'
import ContentMenu from '~/components/ContentMenu'
import HcUpload from '~/components/Upload'
import HcAvatar from '~/components/Avatar/Avatar.vue'
import PostQuery from '~/graphql/UserProfile/Post.js'
import UserQuery from '~/graphql/UserProfile/User.js'
import { filterPosts } from '~/graphql/PostQuery'
// import PostQuery from '~/graphql/UserProfile/Post.js'
import UserQuery from '~/graphql/User'
import { Block, Unblock } from '~/graphql/settings/BlockedUsers.js'
const tabToFilterMapping = ({ tab, id }) => {
@ -401,7 +402,7 @@ export default {
apollo: {
Post: {
query() {
return PostQuery(this.$i18n)
return filterPosts(this.$i18n)
},
variables() {
return {