DEV Community

anasrin
anasrin

Posted on • Originally published at anasrar.github.io

Contentlayer: Optimize getStaticProps on Next.js

TL:DR

Remove unnecessary data that doesn't render on getStaticProps.

Why?

When you pass Contentlayer data to getStaticProps on Next.js, by default will include the raw markdown, which is redundant and bad for load speed.

import { allPosts, Post } from 'contentlayer/generated';

export async function getStaticProps() {
  const posts: Post[] = allPosts;
  return {
    props: {
      posts,
    }
  };
}
Enter fullscreen mode Exit fullscreen mode

HTML result.

<script id="__NEXT_DATA__" type="application/json">
  {
    "props": {
      "pageProps": {
        "posts": [
          {
            "title": "Change me!",
            "date": "2022-03-11T00:00:00.000Z",
            "body": {
              "raw": "\nWhen you change a source file, Contentlayer automatically updates the content cache, which prompts Next.js to reload the content on screen.\n",
              "html": "<p>When you change a source file, Contentlayer automatically updates the content cache, which prompts Next.js to reload the content on screen.</p>"
            },
            "_id": "change-me.md",
            "_raw": {
              "sourceFilePath": "change-me.md",
              "sourceFileName": "change-me.md",
              "sourceFileDir": ".",
              "contentType": "markdown",
              "flattenedPath": "change-me"
            },
            "type": "Post",
            "url": "/posts/change-me"
          },
          {
            "title": "Click me!",
            "date": "2022-02-28T00:00:00.000Z",
            "body": {
              "raw": "\nBlog posts have their own pages. The content source is a markdown file, parsed to HTML by Contentlayer.\n",
              "html": "<p>Blog posts have their own pages. The content source is a markdown file, parsed to HTML by Contentlayer.</p>"
            },
            "_id": "click-me.md",
            "_raw": {
              "sourceFilePath": "click-me.md",
              "sourceFileName": "click-me.md",
              "sourceFileDir": ".",
              "contentType": "markdown",
              "flattenedPath": "click-me"
            },
            "type": "Post",
            "url": "/posts/click-me"
          },
          {
            "title": "What is Contentlayer?",
            "date": "2022-02-22T00:00:00.000Z",
            "body": {
              "raw": "\n**Contentlayer makes working with content easy.** It is a content preprocessor that validates and transforms your content into type-safe JSON you can easily import into your application.\n",
              "html": "<p><strong>Contentlayer makes working with content easy.</strong> It is a content preprocessor that validates and transforms your content into type-safe JSON you can easily import into your application.</p>"
            },
            "_id": "what-is-contentlayer.md",
            "_raw": {
              "sourceFilePath": "what-is-contentlayer.md",
              "sourceFileName": "what-is-contentlayer.md",
              "sourceFileDir": ".",
              "contentType": "markdown",
              "flattenedPath": "what-is-contentlayer"
            },
            "type": "Post",
            "url": "/posts/what-is-contentlayer"
          }
        ]
      },
      "__N_SSG": true
    },
    "page": "/",
    "query": {},
    "buildId": "lJqgQzHmHoKqCJDQ-Nldm",
    "isFallback": false,
    "gsp": true,
    "scriptLoader": []
  }
</script>
Enter fullscreen mode Exit fullscreen mode

Optimizing

Clone data1 and remove unnecessary things.

import { allPosts, Post } from 'contentlayer/generated';

export async function getStaticProps() {
  const posts: Post[] = allPosts.map((post) => {
    const copy = structuredClone(post);
    copy.body.raw = "";
    copy._raw.sourceFilePath = "";
    copy._raw.sourceFileName = "";
    copy._raw.sourceFileDir = "";
    copy._raw.flattenedPath = "";
    return copy;
  });
  return {
    props: {
      posts,
    }
  };
}
Enter fullscreen mode Exit fullscreen mode

Why Clone?

Contentlayer use single source of truth JSON, modifying data might causing race condition when you need one data on two place or more.

single source of truth diagram

HTML result.

<script id="__NEXT_DATA__" type="application/json">
  {
    "props": {
      "pageProps": {
        "posts": [
          {
            "title": "Change me!",
            "date": "2022-03-11T00:00:00.000Z",
            "body": {
              "raw": "",
              "html": "<p>When you change a source file, Contentlayer automatically updates the content cache, which prompts Next.js to reload the content on screen.</p>"
            },
            "_id": "change-me.md",
            "_raw": {
              "sourceFilePath": "",
              "sourceFileName": "",
              "sourceFileDir": "",
              "contentType": "markdown",
              "flattenedPath": ""
            },
            "type": "Post",
            "url": "/posts/change-me"
          },
          {
            "title": "Click me!",
            "date": "2022-02-28T00:00:00.000Z",
            "body": {
              "raw": "",
              "html": "<p>Blog posts have their own pages. The content source is a markdown file, parsed to HTML by Contentlayer.</p>"
            },
            "_id": "click-me.md",
            "_raw": {
              "sourceFilePath": "",
              "sourceFileName": "",
              "sourceFileDir": "",
              "contentType": "markdown",
              "flattenedPath": ""
            },
            "type": "Post",
            "url": "/posts/click-me"
          },
          {
            "title": "What is Contentlayer?",
            "date": "2022-02-22T00:00:00.000Z",
            "body": {
              "raw": "",
              "html": "<p><strong>Contentlayer makes working with content easy.</strong> It is a content preprocessor that validates and transforms your content into type-safe JSON you can easily import into your application.</p>"
            },
            "_id": "what-is-contentlayer.md",
            "_raw": {
              "sourceFilePath": "",
              "sourceFileName": "",
              "sourceFileDir": "",
              "contentType": "markdown",
              "flattenedPath": ""
            },
            "type": "Post",
            "url": "/posts/what-is-contentlayer"
          }
        ]
      },
      "__N_SSG": true
    },
    "page": "/",
    "query": {},
    "buildId": "toHJpUjQDJpnE6IPRFO4s",
    "isFallback": false,
    "gsp": true,
    "scriptLoader": []
  }
</script>
Enter fullscreen mode Exit fullscreen mode

  1. structuredClone() - Web APIs | MDN

Top comments (0)