Refactor blog into Node.js. Session 1
Why?
I have the blog, for which I rarely write, and no I do not need to reskin in with something new. On twitter folks do it every year and it is a trend.
After watching Next.js conf 2021 I was sold to try it out. Like I do not need to worry compressing images. Ever? Automatic removal of not used CSS? I'm sold!
Just to mention, I do not care that much, that it is done with React.js, for me it is opportunity to level up my knowlesdge of what is possible good tooling in 2021.
Let's go!
Useful links
Official tutorials is great place to start
After tutorials, the grate place to start is on Next.js GitHub - use their generator.
Like this:
Execute create-next-app with npm or Yarn to bootstrap the example:
npx create-next-app --example blog-starter blog-starter-app
or
yarn create next-app --example blog-starter blog-starter-app
Changes I done straight away
And the start looks good so far. Love the folder and components structure, and there is no insane depth there. Good job to folks who created this example.
And this is a great start.
Things I started to change straight away.
Images from Markdown to Nextjs
I have some images in mardown context and I need that to display as NextJs Image component, I followed this blogpost originally:
Using NextJS and Next/Image with MDX Markdown Processing by George Michael
And I ended up with custom solution, which is probably worth short blogpost.
import ReactMarkdown from "react-markdown" import remarkGfm from 'remark-gfm' import Image from "next/image" import markdownStyles from "./markdown-styles.module.css" const renderers = { image: image => { return <Image src={image.src} alt={image.alt} height="200" width="355" /> }, paragraph: (paragraph) => { const { node } = paragraph; if (node.children[0].type === "image") { const image = node.children[0]; return <Image src={image.url} alt={image.alt} height="200" width="355" />; } return <p>{paragraph.children}</p>; }, } export default function PostBody({ content }) { return ( <div className="max-w-2xl mx-auto"> <ReactMarkdown className={markdownStyles["markdown"]} children={content} renderers={renderers} remarkPlugins={[remarkGfm]} /> </div> ) }
React-markdown component started to recommend to use components instead: https://github.com/remarkjs/react-markdown/blob/main/changelog.md#change-renderers-to-components
Keep in mind NextJs Image component needs width and height. So to parse custom mardown like this:
![Next.js tutorial page](/assets/blog/blog-nextjs-day1/Screenshot%202021-11-16%20at%2018.00.17.png "1007x990")
code is following:
import ReactMarkdown from "react-markdown" import Image from "next/image" import markdownStyles from "./markdown-styles.module.css" const components = { img: image => { const defaultSize = [4, 3] const [width, height] = typeof image.title === "string" && /^\d*x\d*$/.test(image.title) ? image.title.split("x").map((n) => parseInt(n)) : defaultSize; return <Image src={image.src} alt={image.alt} width={width} height={height} /> }, } export default function PostBody({ content }) { return ( <div className="max-w-2xl mx-auto"> <ReactMarkdown className={markdownStyles["markdown"]} children={content} components={components} /> </div> ) }
Relation with slugs
In this generated example, slug must match file name. I dissagree, and I will try to change it. Please share if you have already something.
Things I loved and enjoy a lot
- RSS Generator
- It is easy to extend current example
- Again - Next.js Image compression is awesome!
- I start to value Next.js docs more and more. Easy to read, fast to find info - great tool.
- Folder and components structure, and there is no insane depth there. Good job to folks who created this example.
Todos for the other sessions
- Code Color formatting
- Using Link component
- Add today I learned section