diff --git a/README.md b/README.md index 71c459e..97fc15e 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ SEO, 웹접근성 - [SEO, 웹 접근성](https://github.com/kimyouknow/kimyouknow.github.io/pull/15) - [Slack에 메타 태그가 적용되지 않는 버그 수정](https://github.com/kimyouknow/kimyouknow.github.io/pull/27) +- [SEO 컴포넌트 리팩토링 및 og:image 에러 수정](https://github.com/kimyouknow/kimyouknow.github.io/pull/31) 기타 @@ -113,13 +114,15 @@ Github에서 아래와 같이 세팅 후 원하는 main브랜치에 push하면 ```js { + lang: "", // ko title: ``, //Yunho.blog author: '', // Yunho(kimyouknow) description: ``, // 안녕하세요. 프론트엔드 개발자 김윤호입니다. 고민과 문제 해결 과정을 공유하고 있습니다. siteUrl: '', // https://kimyouknow.github.io/ - image: ``, // static 경로에 원하는 사진을 넣어주시면 프로필 이미지로 반영됩니다. ex) ./static/profile-image.png + profileImage: ``, // static 경로에 있는 사진 파일을 입력하면 프로필 이미지로 반영됩니다. ex) profile-image.png + mainOgImage :"", // static 경로에 원하는 사진 파일을 입력하면 메인페이지의 og-image 태그로 반영됩니다. keywords: [], // 원하는 키워드를 적어주시면 keywords meta태그에 반영됩니다. ex) '개발블로그', '문제해결', 'gatsby' - favicon: '', // static 경로에 원하는 사진을 넣어주시면 favicon 이미지로 반영됩니다. ex) ./static/pencil.png + favicon: '', // static 경로에 원하는 사진을 넣어주시면 favicon 이미지로 반영됩니다. ex) /static/pencil.png social: { email: '', // kimyouknow@naver.com github: ``, //https://github.com/kimyouknow diff --git a/blog-config.js b/blog-config.js index c83677d..118ed65 100644 --- a/blog-config.js +++ b/blog-config.js @@ -3,11 +3,13 @@ require('dotenv').config({ }) module.exports = { + lang: 'ko', siteName: `Yunho.blog`, author: 'Yunho(kimyouknow)', description: `안녕하세요. 프론트엔드 개발자 김윤호입니다. 고민과 문제 해결 과정을 공유하고 있습니다.`, siteUrl: 'https://kimyouknow.github.io', - image: `static/profile-image.png`, + profileImage: `profile-image.png`, + mainOgImage: 'main-og-image.png', keywords: ['개발블로그', '문제해결', 'gatsby'], favicon: 'static/pencil.png', social: { diff --git a/src/components/Common/Image/index.tsx b/src/components/Common/Image/index.tsx index b10e12f..e3e9560 100644 --- a/src/components/Common/Image/index.tsx +++ b/src/components/Common/Image/index.tsx @@ -1,9 +1,7 @@ import styled from '@emotion/styled' -import { graphql, useStaticQuery } from 'gatsby' import { GatsbyImage, IGatsbyImageData } from 'gatsby-plugin-image' -import { useMemo } from 'react' -import { GatsbyImageDataType } from '@/types/gatsby.type' +import useStaticImage from '@/hooks/useStaticImage' const ImageSizeMap = { s: 'var(--icon-medium)', @@ -19,36 +17,14 @@ interface ImageProps { isCircle?: boolean } -interface ImageNode { - node: { - relativePath: string - extension: string - publicURL: string - childImageSharp: { - gatsbyImageData: IGatsbyImageData - } - } -} - -interface AssetsImageType { - images: { - edges: ImageNode[] - } -} - interface GatsbyImgProps extends Omit { - image: GatsbyImageDataType + image: IGatsbyImageData alt: string className?: string } const Image = ({ src, size = 'm', isCircle = false, ...rest }: ImageProps) => { - const assetImages = useStaticQuery(imageQuery) - - const target = useMemo( - () => assetImages.images.edges.find(({ node }) => src === node.relativePath), - [assetImages, src], - ) + const target = useStaticImage({ src }) if (!target) return null @@ -70,20 +46,3 @@ const SImage = styled(({ isCircle, ...rest }: GatsbyImgProps) => { diff --git a/src/components/PostDetail/index.tsx b/src/components/PostDetail/index.tsx index 461d31f..f2b7749 100644 --- a/src/components/PostDetail/index.tsx +++ b/src/components/PostDetail/index.tsx @@ -1,6 +1,5 @@ import PostFooter from '@/components/PostDetail/PostFooter' import SEO from '@/components/SEO' -import useBlogConfig from '@/hooks/useBlogConfig' import Layout from '@/Layout' import { PostPageItemType } from '@/types/PostItem.types' @@ -9,11 +8,10 @@ import PostHeader from './PostHeader' interface PostPageInfoProps { postPageInfo: PostPageItemType - href: string + pathname: string } -const PostDetail = ({ postPageInfo, href }: PostPageInfoProps) => { - const { author, favicon, seo, siteName } = useBlogConfig() +const PostDetail = ({ postPageInfo, pathname }: PostPageInfoProps) => { const { node: { tableOfContents, @@ -34,15 +32,11 @@ const PostDetail = ({ postPageInfo, href }: PostPageInfoProps) => { return ( { - const absoluteImagePath = `${siteUrl}/${image}` + const { + lang, + author, + siteName, + favicon, + seo, + siteUrl, + mainOgImage, + description: mainDesc, + keywords: mainKeywords, + } = useBlogConfig() + const target = useStaticImage({ src: mainOgImage }) + const mainOgImagePath = target?.node.publicURL || '' + // params가 없으면 기본 config type을 사용하기 + const pageUrl = `${siteUrl}${pathname || ``}` + keywords = keywords || mainKeywords + description = description || mainDesc + image = image ? `${siteUrl}${image}` : `${siteUrl}/${mainOgImagePath}` + title = title || siteName return ( {title} @@ -31,16 +47,16 @@ const SEO = ({ - - + + {/* twitter cards tags additive with th og: tags */} - + - + diff --git a/src/hooks/useBlogConfig.ts b/src/hooks/useBlogConfig.ts index da1d178..349a72d 100644 --- a/src/hooks/useBlogConfig.ts +++ b/src/hooks/useBlogConfig.ts @@ -18,7 +18,8 @@ const useBlogConfig = () => { siteName description siteUrl - image + profileImage + mainOgImage keywords favicon social { diff --git a/src/hooks/useStaticImage.ts b/src/hooks/useStaticImage.ts new file mode 100644 index 0000000..68a3c3b --- /dev/null +++ b/src/hooks/useStaticImage.ts @@ -0,0 +1,54 @@ +import { graphql, useStaticQuery } from 'gatsby' +import { IGatsbyImageData } from 'gatsby-plugin-image' +import { useMemo } from 'react' + +interface ImageNode { + node: { + relativePath: string + extension: string + publicURL: string + childImageSharp: { + gatsbyImageData: IGatsbyImageData + } + } +} + +interface AssetsImageType { + images: { + edges: ImageNode[] + } +} + +export interface useStaticImageProps { + src: string +} + +const useStaticImage = ({ src }: useStaticImageProps) => { + const assetImages = useStaticQuery(imageQuery) + + const target = useMemo( + () => assetImages.images.edges.find(({ node }) => src === node.relativePath), + [assetImages, src], + ) + + return target +} + +export default useStaticImage + +const imageQuery = graphql` + query { + images: allFile(filter: { sourceInstanceName: { eq: "static" } }) { + edges { + node { + relativePath + extension + publicURL + childImageSharp { + gatsbyImageData(layout: CONSTRAINED) + } + } + } + } + } +` diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 697e1c0..50fde90 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -6,7 +6,6 @@ import MainHeader from '@/components/CategoryHeader' import { CategoryListProps } from '@/components/CategoryHeader/CategoryList' import PostList from '@/components/PostList' import SEO from '@/components/SEO' -import useBlogConfig from '@/hooks/useBlogConfig' import Layout from '@/Layout' import { PostListItemType, PostType } from '@/types/PostItem.types' @@ -27,7 +26,6 @@ const IndexPage = ({ allMarkdownRemark: { edges }, }, }: IndexPageProps) => { - const { author, siteName, siteUrl, description, image, keywords, favicon, seo } = useBlogConfig() const parsed: ParsedQuery = queryString.parse(hash) const selectedCategory = typeof parsed.category !== 'string' || !parsed.category ? 'All' : parsed.category // category 프로퍼티 값이 문자열 형태가 아니거나 존재하지 않는 경우에는 기본적으로 카테고리 값을 All로 지정하고, 그러지 않은 경우에는 파싱한 값을 지정 @@ -57,16 +55,7 @@ const IndexPage = ({ ) return ( - + diff --git a/src/templates/post.template.tsx b/src/templates/post.template.tsx index 352c4dd..a0fb9a2 100644 --- a/src/templates/post.template.tsx +++ b/src/templates/post.template.tsx @@ -11,7 +11,7 @@ interface PostTemplateProps { } } location: { - href: string + pathname: string } } @@ -19,9 +19,9 @@ const PostTemplate = ({ data: { allMarkdownRemark: { edges }, }, - location: { href }, + location: { pathname }, }: PostTemplateProps) => { - return + return } export default PostTemplate diff --git a/src/types/PostItem.types.ts b/src/types/PostItem.types.ts index 1b847ba..55a3bff 100644 --- a/src/types/PostItem.types.ts +++ b/src/types/PostItem.types.ts @@ -1,4 +1,4 @@ -import { GatsbyImageDataType } from './gatsby.type' +import { IGatsbyImageData } from 'gatsby-plugin-image' export interface PostFrontmatterType { title: string @@ -7,7 +7,7 @@ export interface PostFrontmatterType { summary: string thumbnail: { childImageSharp: { - gatsbyImageData: GatsbyImageDataType + gatsbyImageData: IGatsbyImageData } publicURL: string } diff --git a/src/types/gatsby.type.ts b/src/types/gatsby.type.ts index abe9be0..3d45658 100644 --- a/src/types/gatsby.type.ts +++ b/src/types/gatsby.type.ts @@ -1,36 +1,42 @@ import { IGatsbyImageData } from 'gatsby-plugin-image' -export type GatsbyImageDataType = IGatsbyImageData - export interface GatsbyImgProps { - image: GatsbyImageDataType + image: IGatsbyImageData alt: string className?: string } export interface SEOConfigType { - lang?: string + title?: string + pathname?: string + description?: string + image?: string + keywords?: string[] + readingTime?: string +} + +/** + * blog-config.js의 정보 타입 + */ +export interface ConfigType { + lang: 'ko' | 'en' author: string siteName: string - siteUrl: string - title?: string description: string - image: string + siteUrl: string + profileImage: string + mainOgImage: string keywords: string[] favicon: string - seo: { - google: string - naver: string - } - readingTime?: string -} - -export interface ConfigType extends SEOConfigType { social: { email: string github: string til: string } + seo: { + google: string + naver: string + } utterances: { src: string repo: string diff --git a/static/main-og-image.png b/static/main-og-image.png new file mode 100644 index 0000000..d623f58 Binary files /dev/null and b/static/main-og-image.png differ