자신의 사이트에 블로그 카드를 설치하였다

블로그 등을 작성해 다음과 같은 느낌으로 링크를 카드로 표시했다.단순한 링크보다는 링크의 정보를 미리 볼 수 있어 좋다.zen 등도 이런 링크를 실현하여 좋은 사용자 체험을 제공할 수 있을 것이라고 생각합니다.
画像1
다른 사이트나 SNS에 자신의 사이트를 소개할 때 언어와 이미지를 어떻게 설정하는지에 관한 기사를 종종 볼 수 있다.예를 들어zen에서도 자동으로ogp 이미지를 생성하는 글을 볼 수 있다.
https://zenn.dev/tdkn/articles/c52a0cc7bea561
https://zenn.dev/ryo_kawamata/articles/introduction-socialify
https://zenn.dev/makiart/articles/78d53694e70105
https://zenn.dev/mkmk4423/articles/13e913c0a5543781639f
그러나 자신의 사이트에 다른 사이트의 정보를 얻었는지에 대한 기사가 적혀 있는 것은 드물다.Zen에도 여러 개 있어요. 참고할게요.
https://zenn.dev/littleforest/articles/scrape-og-tags
https://zenn.dev/junki555/articles/a4902e7f66547c91d812
wordpress 등 사이트에서 플러그인을 제공한 것 같습니다. 방법을 소개하는 글은 바로 찾을 수 있습니다. 예를 들어 저처럼next입니다.js를 사용한 상황 등의 보도는 완전히 그렇다고 할 수 있다.그래서 이번엔 넥스트야.js를 사용한 저의 실현 방법을 소개합니다.나는 이것이 좋은 방법인지 모르겠지만, 나는 당신이 참고할 수 있기를 바랍니다.그리고 조언이 있으면 말씀해 주세요.

구조


우선 블로그 카드는 기본적으로'제목','설명','URL','이미지'로 구성되어 있다.

그러면 이 정보를 어디서 얻었는지 말하자면 저는'html 파일 헤드'에 있는 메타 탭에 기재된 정보를 얻었습니다.

따라서 링크된 URL 중 카드를 표시하려는 URL의 사이트를 방문하면 메타 태그 정보를 얻는 메커니즘을 구축하면 된다는 것을 대략적으로 설명한다.

이루어지다


그렇긴 하지만 쉽게 시행할 수 없는 문제도 있다.CORS(Cross-Origin Resource Sharing: 올리브 리소스 공유)의 문제입니다.
오리온자리는 쉽게 호스트 이름으로, 코르스와는 서로 다른 호스트 사이에서 자원을 공유하기 위한 메커니즘이다.(자세한 내용은 아래와 같다)
https://developer.mozilla.org/ja/docs/Web/HTTP/CORS
https://developer.mozilla.org/en-US/docs/Glossary/Origin
대부분의 사이트에서 이 설정을 했기 때문에 브라우저로 자원을 얻을 수 있지만 클라이언트는javaScript 등을 사용하는 자원을 얻을 수 없습니다.따라서 서버에서 정보를 얻고 블로그 카드를 만들어야 한다.

  • 클라이언트의 조작을 통해 블로그 카드를 동적으로 만들려면'aax로 만든 URL을 서버 측에 보내고 서버 측에서 정보를 얻고 보여주며 클라이언트에게 되돌려주고 싶다'는 방법을 고려할 수 있다.

  • next.만약 js의 SSG처럼 미리 재현할 수 있다면, 'SSG 시 URL에서 정보를 얻고 재현할 수 있습니다.'
  • SSG 처리


    이번에는 표기 파일인 SSG에서 기사를 생성하기 때문에 2번 방법을 소개한다.
    절차로 삼다
  • 글의 데이터를 문자열로 가져오기
  • 카드로 변환할 링크의 URL을 정렬로 가져오기
  • URL에서 text/html 데이터 가져오기
  • 얻은 text/html 데이터에서 상응하는 메타 라벨
  • 타이틀, description,imge에 해당하는 정보를 추출 배열로 저장
  • 어레이를 어셈블리로 반환합니다.
  • 네.서버 측 JS에는 DOM 작업에 대한 API가 없으므로 JSDOM 라이브러리를 사용하여 DOM 작업을 수행합니다.
    또한 구성 요소에 데이터를 전송할 때undefined와 같은 대상, 예를 들어 JSON이 전달하는 대상을 배제해야 한다.
    const jsdom = require("jsdom");
    const { JSDOM } = jsdom;
    
    export const getStaticProps: GetStaticProps = async({ params }) => {
        // 1. 記事のデータを文字列として取得 ========================================
        const article = getArticle(); // 記事のデータを文字列として取得
    
        // 2. カードに変換したいリンクのURLを配列として取得 ===========================
        // 行ごとに配列にする
        const lines = article.split("\n");
        const links = [];
        // URLの取得
        lines.map(line => {
            if (line.indexOf("http://") === 0) links.push(line);
            if (line.indexOf("https://") === 0) links.push(line);
        });
    
        let cardDatas = [];
        const temps = await Promise.all(links.map(async(link) => {
            const metas = await fetch(link)
            // 3. URLからtext/htmlデータを取得 ====================================
            .then(res => res.text())
            .then(text => {
                const metaData = {
                    url: link,
                    title: "",
                    description: "",
                    image: "",
                };
                // 4. 取得したtext/htmlデータから該当するmetaタグを取得 ==============
                const doms = new JSDOM(text);
                const metas = doms.window.document.getElementsByTagName('meta');
    
                // 5. title, description, imageにあたる情報を取り出し配列として格納 ==
                for (let i = 0; i < metas.length; i++) {
                    let pro = metas[i].getAttribute("property");
                    if (typeof pro == "string") {
                        if (pro.match("title"))       metaData.title = metas[i].getAttribute("content");
                        if (pro.match("description")) metaData.description = metas[i].getAttribute("content");
                        if (pro.match("image"))       metaData.image = metas[i].getAttribute("content");
                    }
                    pro = metas[i].getAttribute("name");
                    if (typeof pro == "string") {
                        if (pro.match("title"))       metaData.title = metas[i].getAttribute("content");
                        if (pro.match("description")) metaData.description = metas[i].getAttribute("content");
                        if (pro.match("image"))       metaData.image = metas[i].getAttribute("content");
                    }
                }
                return metaData;
            })
            .catch(e => {console.log(e);});
            return metas;
        }));
        // 配列の整形 ※コンポーネントに渡す際はjson情報に変換するようなので
        // undefinedのようなオブジェクトは除外する。
        cardDatas = temps.filter(temp => temp !== undefined);
    
        // 6. 配列をコンポーネントに返す。 ==========================================
        return {
            props: {
                data,
                cardDatas,
            }
        }
    }
    
    우선 블로그 카드는 기본적으로'제목','설명','URL','이미지'로 구성되어 있다.그러나 여기서는 그렇게 할 필요가 없다5. title, description, imageにあたる情報を取り出し配列として格納. 임의의 라벨에서 정보를 얻으면 자신이 좋아하는 블로그 카드가 될 수 있다.
    타이틀, description, 이미지 등 메타 라벨을 꼭 준비해야 하는 것은 아니지만, 튼튼한 블로그 카드를 만들려면 description을 찾지 못하면 본문에서 받아야 한다.

    어셈블리 처리


    비록 당신은 구성 요소의 처리를 좋아하지만, 나는 먼저 나의 설치를 위에 놓을 것이다.여기는 ReactMarkdown 사용 시 처리입니다.renderers 링크로 판단되는 부분은 블로그 카드 링크카드 구성 요소에 맡깁니다.
    <ReactMarkdown 
        source={ article }
        // LinkCardコンポーネントがブログカード
        renderers={{ code: CodeBlock, link: LinkCard }}
    />
    
    블로그 카드 정보를 서문으로 전달하는 방법을 모르기 때문에 전역 상태에서 배열로 얻은 모든 블로그 카드 정보를 저장하고 링크카드 구성 요소의 URL을 통해
    귀하와 일치하는 블로그 카드 정보가 있으면 블로그 카드로 하고 그렇지 않으면 a탭으로만 표시합니다.
    import React ,{ useContext } from "react";
    import { SiteContext } from "../pages/_app";
    
    interface P {
        href: string,
        children: any,
    }
    
    const LinkCard: React.FC<P> = ({ href, children }) => {
        // @ts-ignore
        const { state } = useContext(SiteContext);
        const target = state.metas.find(meta => meta.url == href);
    
        if (target) {
            return (
                <a href={ href } target="_brank" className="grid grid-cols-5 bg-white rounded-md p-3">
                    <div className="col-span-1 flex justify-start items-center">
                        <img src={ target.image ? target.image : "/noImage.svg" } alt={target.title} width="100px" className="object-contain"/>
                    </div>
                    <div className="col-span-4 flex flex-col justify-start">
                        <div className="text-xl font-bold text-black">{ target.title }</div>
                        <div className="text-gray-400 text-xs">{ target.description }</div>
                    </div>
                </a>
            );
        }
        return (
            <a href={ href } target="_brank">{ children }</a>
        )
    }
    
    export { LinkCard }
    
    더 신뢰할 수 있는 설치 방법은zen이 일대을 보는 것이 좋다.

    좋은 웹페이지 즐겨찾기