Next.jsでYouTube埋め込みを作成する

に公開

Next.jsでブログ兼ポートフォリオサイト的なものを作成しました(チュートリアルを少しいじったもの)。

サイト:https://nemog.net

その際に、markdownファイルにYouTubeの埋め込みができるようにしたので書き残しておきます。

完成系

コードブロックの言語名にYouTubeと指定して、動画のIDを入れます。

以下のように表示されます。

やっていること

ReactMarkdownでmarkdownをHTMLに変換する際、codeの箇所を独自にカスタマイズします。

言語名の部分がYouTubeだったら、react-youtubeというライブラリのコンポーネントに変換する、という処理を行っています。

変換処理部分

[slug].tsx
<ReactMarkdown remarkPlugins={[remarkGfm]} components={{ code: Code }}>
    {post.content}
</ReactMarkdown>

ここでReactMarkdownコンポーネントに{{ code : Code }}を指定することで、codeタグの処理をCodeコンポーネントにゆだねることができます。

https://github.com/nemog9/NextBlog/blob/0e32b591dfdf5e20a97e0a81578c7b18a5c5e549/pages/posts/[slug].tsx#L48-L50

Code.tsx
const Code: CodeComponent = ({ inline, className, children, ...props }) => {
    const match = /language-(\w+)/.exec(className || '');
    const matchFileName = className && className.includes(':') ? className.split(':') : null;
    if (match && match.length > 0 && match[1] === 'youtube') {
        return (
            <div className='youtube-wrap'>
                <YouTube videoId={children[0] as string} />
            </div>
        );
    }

正規表現で言語名部分を取得し、youtubeと書かれていたら、react-youtubeからインポートしたYouTubeコンポーネントに動画のIDを渡します。

そのままだと横幅が指定されており、スマホだと横スクロールできてしまうので、youtube-wrapクラスをつけてはみ出ないようにします。

https://github.com/nemog9/NextBlog/blob/0e32b591dfdf5e20a97e0a81578c7b18a5c5e549/components/Code.tsx#L6-L15

globals.css
.youtube-wrap iframe {
    margin: 1rem 0;
    aspect-ratio: 16 / 9;
    width: 100%;
    max-width: 680px;
    height: auto;
}

youtube-wrap iframeクラスにはaspect-ratioを指定して比率がいい感じになるようにしています。

https://github.com/nemog9/NextBlog/blob/0e32b591dfdf5e20a97e0a81578c7b18a5c5e549/styles/globals.css#L73-L79

一応ソースコードのリンクは貼りましたが、全体的に見たい方はこちらのリポジトリを見て見てください。

https://github.com/nemog9/NextBlog

感想

リンクを貼っただけで自動的に埋め込みにするのはunifiedなどの解析の技術が必要で、そこまで到達するのはすごく大変そうだったので逃げてしまいました。

いつか勉強してみたいです。

が、普通に実用的なものが作れたので満足しています。

多くのサービスがただリンクを貼りつけただけで埋め込みにしてくれますが、改めてすごいことやってるんじゃないかって思いました。

GitHubで編集を提案

Discussion