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

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more