React 앱의 링크를 바삭 바삭한 Twitter로 매료
트위터에 매료 란 무엇입니까?
이런 녀석! 이름은 Twitter Card.
링크가 Twitter에서 어떻게 표시되는지는 Card Validator | Twitter Developers 에서 확인할 수 있다.
이것을 React 앱 링크로 표시하고 싶습니다! 라는 이야기.
최근 처음 React를 만져 막상 Twitter Card 대응하려고 조사했을 때, SPA에 있어서의 OGP 대응의 고민을 알았습니다.
대응 방법은 여러 가지 하지만 이번에는 필자가 실제로 시도한 두 가지 방법을 간단히 쓰고 싶습니다.
실제로 채택한 "Static Site Generator 방법"과 "Cloud Functions에서 meta 태그를 바꾸는 방법"의 두 가지입니다.
방법 1: SSG
Server Side Rendering (SSR)과 비교하여 Static Site Generator (SSG)라고합니다.
사전에 JS 를 실행해 각 페이지의 HTML 를 생성해 그것을 전달하는 기법.
저자는 소규모 개인 앱에 대해이 방법으로 OGP를 지원했습니다.
구체적으로는 react-snap + react-helmet로 HTML을 생성하고 Firebase Hosting에서 전달합니다. 1
react-snap
로컬에서 크롤링하여 HTML을 생성하는 라이브러리.
(이름에 react라고 들어 있지만, 별도로 react 전용 라이브러리가 아니라 Vue에서도 사용할 수 있습니다!)
package.json 의 scripts 에 "postbuild": "react-snap"
를 더하는 것만으로 잘 해 준다!
package.json"scripts": {
"start": "react-scripts-ts start",
"build": "react-scripts-ts build",
"postbuild": "react-snap",
"test": "react-scripts-ts test --env=jsdom",
"eject": "react-scripts-ts eject"
}
이것을 사용해 수중에서 사전에 렌더링한 결과를 HTML 로서 가질 수가 있습니다.
다만, 이것만으로는 어느 페이지도 동일한 meta 태그 (루트의 index.html에 쓴 것)가 되어 버립니다.
따라서 react-helmet를 도입하여 페이지별로 meta 태그를 설정합니다.
react-helmet
hello.tsximport { RouteComponentProps } from 'react-router-dom'
import { Helmet } from "react-helmet";
export const Hello: React.SFC<RouteComponentProps<{}>> = props => (
<div>
<Helmet
title={'Hello World'}
meta={[
{ name: 'twitter:card', content: 'summary' },
{ property: 'og:image', content: 'path/to/og_image' },
{ property: 'og:title', content: 'Helloページ' },
{ property: 'og:description', 'サンプルページです' },
{ property: 'og:url', content: `hoge_domain${props.path}` }
]}
/>
<div> Hello! </div>
</div>
)
이런 식으로 Helmet 컴포넌트를 꽂아 meta 정보를 지정할 수 있다.
이 helemt 를 도입한 다음에 yarn build
그러면, 생성되는 HTML 의 meta 태그는 확실히 동적으로 생성할 수 있다.
build/컴포넌트명/index.html 를 보면 이런 느낌이 되어 기쁘다!
build/Hello/index.html<meta content="Helloページ" data-react-helmet="true" property="og:title">
Firebase에 배포
매우 정상적인 설정으로 배포하기만 하면 됩니다.
firebase.json{
"hosting": {
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
이런 느낌으로 바삭하게 버렸습니다!
방법 2: Cloud Functions로 meta 태그 교체
이쪽에 대해서는 많은 기사가 있으므로 간단하게.
처음에는 이 방법으로 만들었습니다만, 소규모의 개인 개발이고 심플한 일 밖에 없는 앱이었기 때문에, 방법 1이 더 적합하다고 생각 전환했습니다.
Cloud Functions를 통한 동적 콘텐츠 배포 에도 써있듯이, meta 태그를 바꿔 OGP 대응할 수 있습니다.
SEO를 향상시키는 단일 페이지 앱을 미리 렌더링합니다. 이렇게 하면 서로 다른 소셜 네트워크 간에 공유할 수 있는 동적 meta 태그를 만들 수 있습니다.
Cloud Functions에 TypeScript 사용 을 참고로 설정하고 이런 식으로 meta 태그를 바꿉니다.
functions/index.tsximport * as functions from 'firebase-functions'
import * as fs from 'fs'
export const PreRender = functions.region('asia-northeast1').https.onRequest((req, res) => {
res.set('Cache-Control', 'public, max-age=300, s-maxage=600')
fs.readFile('./index.html', 'utf8', (e, html) => {
const responseHtml = html.replace('トップページ', 'Helloページ') // meta タグの中身を置換する処理を書く
res.status(200).send(responseHtml)
})
})
그런 다음 Firebase Hosting 리라이트을 사용하여 요청을 Cloud Functions에 전달합니다.
firebase.json{
"hosting": {
"rewrites": [
{
"source": "hello/*",
"function": "PreRender"
},
{
"source": "**",
"destination": "/index.html"
}
]
}
}
결론
상당히 썼습니다만, 참고가 되면 다행입니다.
참고
공식 문서
Server Side Rendering (SSR)과 비교하여 Static Site Generator (SSG)라고합니다.
사전에 JS 를 실행해 각 페이지의 HTML 를 생성해 그것을 전달하는 기법.
저자는 소규모 개인 앱에 대해이 방법으로 OGP를 지원했습니다.
구체적으로는 react-snap + react-helmet로 HTML을 생성하고 Firebase Hosting에서 전달합니다. 1
react-snap
로컬에서 크롤링하여 HTML을 생성하는 라이브러리.
(이름에 react라고 들어 있지만, 별도로 react 전용 라이브러리가 아니라 Vue에서도 사용할 수 있습니다!)
package.json 의 scripts 에
"postbuild": "react-snap"
를 더하는 것만으로 잘 해 준다!package.json
"scripts": {
"start": "react-scripts-ts start",
"build": "react-scripts-ts build",
"postbuild": "react-snap",
"test": "react-scripts-ts test --env=jsdom",
"eject": "react-scripts-ts eject"
}
이것을 사용해 수중에서 사전에 렌더링한 결과를 HTML 로서 가질 수가 있습니다.
다만, 이것만으로는 어느 페이지도 동일한 meta 태그 (루트의 index.html에 쓴 것)가 되어 버립니다.
따라서 react-helmet를 도입하여 페이지별로 meta 태그를 설정합니다.
react-helmet
hello.tsx
import { RouteComponentProps } from 'react-router-dom'
import { Helmet } from "react-helmet";
export const Hello: React.SFC<RouteComponentProps<{}>> = props => (
<div>
<Helmet
title={'Hello World'}
meta={[
{ name: 'twitter:card', content: 'summary' },
{ property: 'og:image', content: 'path/to/og_image' },
{ property: 'og:title', content: 'Helloページ' },
{ property: 'og:description', 'サンプルページです' },
{ property: 'og:url', content: `hoge_domain${props.path}` }
]}
/>
<div> Hello! </div>
</div>
)
이런 식으로 Helmet 컴포넌트를 꽂아 meta 정보를 지정할 수 있다.
이 helemt 를 도입한 다음에
yarn build
그러면, 생성되는 HTML 의 meta 태그는 확실히 동적으로 생성할 수 있다.build/컴포넌트명/index.html 를 보면 이런 느낌이 되어 기쁘다!
build/Hello/index.html
<meta content="Helloページ" data-react-helmet="true" property="og:title">
Firebase에 배포
매우 정상적인 설정으로 배포하기만 하면 됩니다.
firebase.json
{
"hosting": {
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
이런 느낌으로 바삭하게 버렸습니다!
방법 2: Cloud Functions로 meta 태그 교체
이쪽에 대해서는 많은 기사가 있으므로 간단하게.
처음에는 이 방법으로 만들었습니다만, 소규모의 개인 개발이고 심플한 일 밖에 없는 앱이었기 때문에, 방법 1이 더 적합하다고 생각 전환했습니다.
Cloud Functions를 통한 동적 콘텐츠 배포 에도 써있듯이, meta 태그를 바꿔 OGP 대응할 수 있습니다.
SEO를 향상시키는 단일 페이지 앱을 미리 렌더링합니다. 이렇게 하면 서로 다른 소셜 네트워크 간에 공유할 수 있는 동적 meta 태그를 만들 수 있습니다.
Cloud Functions에 TypeScript 사용 을 참고로 설정하고 이런 식으로 meta 태그를 바꿉니다.
functions/index.tsximport * as functions from 'firebase-functions'
import * as fs from 'fs'
export const PreRender = functions.region('asia-northeast1').https.onRequest((req, res) => {
res.set('Cache-Control', 'public, max-age=300, s-maxage=600')
fs.readFile('./index.html', 'utf8', (e, html) => {
const responseHtml = html.replace('トップページ', 'Helloページ') // meta タグの中身を置換する処理を書く
res.status(200).send(responseHtml)
})
})
그런 다음 Firebase Hosting 리라이트을 사용하여 요청을 Cloud Functions에 전달합니다.
firebase.json{
"hosting": {
"rewrites": [
{
"source": "hello/*",
"function": "PreRender"
},
{
"source": "**",
"destination": "/index.html"
}
]
}
}
결론
상당히 썼습니다만, 참고가 되면 다행입니다.
참고
공식 문서
import * as functions from 'firebase-functions'
import * as fs from 'fs'
export const PreRender = functions.region('asia-northeast1').https.onRequest((req, res) => {
res.set('Cache-Control', 'public, max-age=300, s-maxage=600')
fs.readFile('./index.html', 'utf8', (e, html) => {
const responseHtml = html.replace('トップページ', 'Helloページ') // meta タグの中身を置換する処理を書く
res.status(200).send(responseHtml)
})
})
{
"hosting": {
"rewrites": [
{
"source": "hello/*",
"function": "PreRender"
},
{
"source": "**",
"destination": "/index.html"
}
]
}
}
상당히 썼습니다만, 참고가 되면 다행입니다.
참고
공식 문서
블로그 등
【기사판】State of SEO for SPA 2018 : 매우 알기 쉬운 정리 기사! 조사하면서 다양한 고전하기 전에이 기사를 만나고 싶었습니다 ...
SSR없이 React 앱을 OGP에 대응 (자력 prerendering 편) : 본 기사와 같이 로컬로 Pre Rendering 하는 기법.
React + TypeScript + Firebase Hosting 구성
Reference
이 문제에 관하여(React 앱의 링크를 바삭 바삭한 Twitter로 매료), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/sensuikan1973/items/70a8d954f24e89156d15텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)