This is going to a different type of post than I usually do. I want to share my learning experience getting started with Next.js. My hope is that some of this might be useful for you those of you interested in learning Next.js, but also to hopefully learn from those of you who already know Next.js.
So up front, let me be frank. I am a total React noob. Somehow, despite its ubiquity in today's frontend development ecosystem, I've managed to avoid it. Partly this was because I was never in a position to have to use it and partly this was because I found the React ecosystem a bit overwhelming and intimidating.
However, I've been really interested in checking out Next.js. From what I'd read and seen, it seemed to make React approachable. And, even more interesting for me, it even allows for statically generating assets, making it an option for JAMstack development.
Where to Learn Next.js?
Next.js has a nicely done learn guide that tries to help motivate you by awarding your points for completing tasks and answering quiz questions. It does a pretty nice job of covering the basics. That being said, I didn't feel ready to jump in and build something at this point. I was looking for something that would dive a little deeper - preferably a video training of some sort.
After doing some research I stumbled on this training by Remy Sharp. It appears to be a number of versions behind on Next.js, so some aspects of it seem to be outdated, but most of the basics it covers in the first modules are still relevant. Overall, it gave me what I was looking for even if it could use some updating.
Creating a Learning Project
The next step was to actually start trying to build something with Next.js. Since my goal was to explore it's usage for JAMstack, I decided to look into how to rebuild my current blog that was built using Jekyll. While it isn't a complex site, there's enough there to force me to learn a lot about Next.js.
The goal was to recreate the blog, including generating content assets that are currently written in Markdown with YAML front Matter. Next.js doesn't appear to natively support this at this time. There is an official MDX loader plugin but my posts were not written using MDX and I was not looking to convert all of them.
Thankfully, Kendall Strautman wrote a great post on building a Markdown blog with Next.js and an associated sample project repository. This provided enough detail to get me going.
I have some of the basics working in my repo including a dynamic route [slug].js
that handles any post URL and loads the appropriate content.
import * as React from 'react'
import matter from "gray-matter";
import ReactMarkdown from "react-markdown";
import Layout from '../../components/layout'
export default function BlogTemplate(props) {
function reformatDate(fullDate) {
const date = new Date(fullDate)
return date.toDateString().slice(4);
}
const markdownBody = props.content
const frontmatter = props.data
return (
<Layout config={props.config}>
<div>
<h1>{frontmatter.title}</h1>
<h2>
{frontmatter.description}
</h2>
<h3>{reformatDate(frontmatter.date)}</h3>
</div>
<div>
<ReactMarkdown source={markdownBody} />
</div>
</Layout>
)
}
BlogTemplate.getInitialProps = async function(ctx) {
const { slug } = ctx.query
const content = await import(`../../posts/${slug}.md`)
const config = await import(`../../data/config.json`)
const data = matter(content.default);
return {
...data,config
}
}
One issue right now is that the slug is based upon the file name, which Jekyll requires formatting with the date string. So instead of using /blog/joining-stackbit
, I currently need to use /blog/2019-10-09-joining-stackbit
. Whether this is a problem fixable by code or simply by renaming all the files, I do not know yet.
Passing Down Config Properties
Next.js has a special method called getInitialProps()
, which is a useful way to load any needed data the page needs. One of the things I wanted to do was to load site-wide configuration data similar to how it is done with Jekyll. What I quickly learned was that this method isn't available in components (at least not without some tweaking), just regular pages.
In the end, I opted to load the data in the page and then pass it down to the layout. This ends up being a bit redundant rather than automatic. Maybe I'm doing this wrong but do I need to load this on each page or is there a way to centralize loading it just once? This way I then need to pass it down from the layout component to each component that makes up the layout. I am not sure if this is considered a best-practice or antipattern for React.
Home.getInitialProps = async function() {
const configData = await import(`../data/config.json`)
return {
...configData
}
}
<Layout config={props}>
</Layout>
I am not sharing this as how it should be done...more as "Am I doing this right?"
Next Steps
That's my status right now. I can load posts, but the layout is awful. Next steps will be:
- Improving the layout (adding a design)
- Handling sub-pages or data (I have content generated from YAML files in my current blog)
- Figure out how to handle categories that are in the front matter and allow for filtering as I do here in my current blog
- Reimplement the site search that is currently built with Lunr
- Finally, I will need to configure the whole thing to statically generate the output files to deploy to Netlify.
I welcome any Next.js advice! 🙏🏻
Top comments (6)
You’re layout config setup code looks good. But it got me thinking, you’re re-rendering the layout every time you switch pages. This probably is harder to notice for smaller apps, but you’ll probably want to avoid it if possible. Here’s an article I found with some good solutions: adamwathan.me/2019/10/17/persisten...
Thanks Shane. Great advice.
Do you have any tip to use MDX instead of MD?
Unfortunately, no. I may be a bit of an outlier (or call me a curmudgeon), but I don't like MDX. Markdown has a ton of limitations, but the reason the format works and the reason we accept those limitations is because it is easy to learn and easy to write. It emphasizes simplicity over functionality. One of these limitations was that anything you couldn't do in Markdown you had to learn how to do in HTML. Sill, it was generally easy for anyone, even without much web dev experience, to look at the file and make sense of the content. In my view, MDX keeps many of the issues of Markdown but throws on a layer of additional complexity. I get why it seems necessary when dealing with React, I just feel like it's a step in the wrong direction.
Ok. Thanks for the answer. The reason why I asked: I don't know how should I organize and handle images for the blog posts. I don't know the practical way.
Images shouldn't be too difficult. For my sites that I manually maintain, I just keep them in the static images folder. Most CMS will help manage this for you - even free ones like Netlify CMS.