惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cloudbric
Cloudbric
T
Threat Research - Cisco Blogs
Simon Willison's Weblog
Simon Willison's Weblog
AWS News Blog
AWS News Blog
P
Privacy & Cybersecurity Law Blog
H
Help Net Security
云风的 BLOG
云风的 BLOG
G
GRAHAM CLULEY
Spread Privacy
Spread Privacy
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
A
Arctic Wolf
Project Zero
Project Zero
Engineering at Meta
Engineering at Meta
P
Privacy International News Feed
Blog — PlanetScale
Blog — PlanetScale
Stack Overflow Blog
Stack Overflow Blog
M
MIT News - Artificial intelligence
The Register - Security
The Register - Security
Recorded Future
Recorded Future
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
C
Cisco Blogs
PCI Perspectives
PCI Perspectives
Recent Announcements
Recent Announcements
Martin Fowler
Martin Fowler
A
About on SuperTechFans
W
WeLiveSecurity
GbyAI
GbyAI
V
Vulnerabilities – Threatpost
The GitHub Blog
The GitHub Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
C
Check Point Blog
Y
Y Combinator Blog
月光博客
月光博客
Scott Helme
Scott Helme
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google DeepMind News
Google DeepMind News
F
Fortinet All Blogs
U
Unit 42
G
Google Developers Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Threatpost
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google Online Security Blog
Google Online Security Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Cisco Talos Blog
Cisco Talos Blog
博客园 - 三生石上(FineUI控件)
Hugging Face - Blog
Hugging Face - Blog
MongoDB | Blog
MongoDB | Blog
博客园 - 司徒正美

Maxime Heckel's Blog

On Rendering the Sky, Sunsets, and Planets - The Blog of Maxime Heckel Shades of Halftone - The Blog of Maxime Heckel Field Guide to TSL and WebGPU - The Blog of Maxime Heckel On Shaping Light: Real-Time Volumetric Lighting with Post-Processing and Raymarching for the Web - The Blog of Maxime Heckel Speaking at Figma Config 2025 - The Blog of Maxime Heckel Post-Processing Shaders as a Creative Medium - The Blog of Maxime Heckel On Crafting Painterly Shaders - The Blog of Maxime Heckel The Art of Dithering and Retro Shading for the Web - The Blog of Maxime Heckel Moebius-style post-processing and other stylized shaders - The Blog of Maxime Heckel Shining a light on Caustics with Shaders and React Three Fiber - The Blog of Maxime Heckel Real-time dreamy Cloudscapes with Volumetric Raymarching - The Blog of Maxime Heckel Painting with Math: A Gentle Study of Raymarching - The Blog of Maxime Heckel Building a magical AI-powered semantic search from scratch - The Blog of Maxime Heckel Beautiful and mind-bending effects with WebGL Render Targets - The Blog of Maxime Heckel Refraction, dispersion, and other shader light effects - The Blog of Maxime Heckel The magical world of Particles with React Three Fiber and Shaders - The Blog of Maxime Heckel The Study of Shaders with React Three Fiber - The Blog of Maxime Heckel Building a Design System from scratch - The Blog of Maxime Heckel Everything about Framer Motion layout animations - The Blog of Maxime Heckel Building a Vaporwave scene with Three.js - The Blog of Maxime Heckel Cubic Bézier: from math to motion - The Blog of Maxime Heckel First steps with GPT-3 for frontend developers - The Blog of Maxime Heckel Building the perfect GitHub CI workflow for your frontend team - The Blog of Maxime Heckel Static Tweets with MDX and Next.js - The Blog of Maxime Heckel Advanced animation patterns with Framer Motion - The Blog of Maxime Heckel Scrollspy demystified - The Blog of Maxime Heckel The Power of Composition with CSS Variables - The Blog of Maxime Heckel My first failed SwiftUI project - The Blog of Maxime Heckel Guide to creating animations that spark joy with Framer Motion - The Blog of Maxime Heckel Using Shortcuts and serverless to build a personal Apple Health API - The Blog of Maxime Heckel SEO mistakes I've made and how I fixed them - The Blog of Maxime Heckel Going native: SwiftUI from the perspective of a React developer - The Blog of Maxime Heckel Build your own preview deployment service - The Blog of Maxime Heckel The little guide to CI/CD for frontend developers - The Blog of Maxime Heckel Immigrating to the US - The Blog of Maxime Heckel The physics behind spring animations - The Blog of Maxime Heckel Generate screenshots of your code with a serverless function - The Blog of Maxime Heckel How to use Framer Motion with Emotion styled-components - The Blog of Maxime Heckel Data Fetching with NextJS: What I learned - The Blog of Maxime Heckel Learning in public - The Blog of Maxime Heckel Fixing the dark mode flash issue on server rendered websites - The Blog of Maxime Heckel How to fix NPM link duplicate dependencies issues - The Blog of Maxime Heckel Running scheduled cross-browser end-to-end tests on Github CI - The Blog of Maxime Heckel How I built my first custom ESLint rule - The Blog of Maxime Heckel React Lazy: a take on preloading views - The Blog of Maxime Heckel Automated UI accessibility testing with Cypress - The Blog of Maxime Heckel Building a GraphQL wrapper for the Docker API - The Blog of Maxime Heckel Switching off the lights - Adding dark mode to your React app - The Blog of Maxime Heckel Getting started with Typescript on Gatsby - The Blog of Maxime Heckel Rebuilding Redux with Hooks and Context - The Blog of Maxime Heckel Asynchronous rendering with React - The Blog of Maxime Heckel Using Flow generics to type generic React components - The Blog of Maxime Heckel How to efficiently type your styled-components with Flow - The Blog of Maxime Heckel How I got started with Kubernetes on GKE - The Blog of Maxime Heckel React sub-components Part 3: Whitelisting sub-components with flow - The Blog of Maxime Heckel React sub-components Part 2: Using the new Context API - The Blog of Maxime Heckel React sub-components - The Blog of Maxime Heckel Running Golang tests with Jest - The Blog of Maxime Heckel No title No title
Migrating to Next.js - The Blog of Maxime Heckel
Maxime Heckel · 2021-06-29 · via Maxime Heckel's Blog

Last year, I gave myself the objective of learning Next.js as it was getting more and more popular among the people I followed on Twitter and was adopted by many companies as their main frontend framework. The focus of the Next.js team on Developer eXperience (DX) and simplicity was striking the first time I tried it, especially compared to Gatsby which, back then, powered this blog and started to feel very cumbersome at times.

Thus in January, I told myself I'd migrate over my entire blog and its content over to Next.js and see if I could leverage its simplicity to make the experience of maintaining and expanding this blog easier and less time-consuming.

As this migration is now a success 🎉 I wanted to dedicate this blog post to go through some of the thoughts I gathered throughout this process, and also the experience I had with both frameworks, to maybe help you choose what's best for your own setup.

Farewell Gatsby

After over a year and a half of building this site with Gatsby, it was time to say goodbye. However, this doesn't mean I don't appreciate Gatsby any more, far from that. I feel Gatsby was a great way to enter the "technical blog-sphere" and gave me all the tools to build a successful and compelling blog:

  • I had no idea what I was doing when I started this blog 🐶 (still the case but a bit less now).

  • I didn't know anything about SEO, and the plugin system was a gold mine that helped me follow best practices without any knowledge required.

  • It introduced me to MDX which is now an essential part of my stack and gave me the ability to build interactive components into my blog posts. The setup for MDX on Gatsby was incredibly easy!

So, "what drove you off Maxime?" you may ask. Well here are a couple of points that started to become more and more obvious as my time with Gatsby went by.

Over-engineered

Something that originally caught my attention with Gatsby was its use of GraphQL. It became more of a curiosity over time honestly. While I'm sure it makes sense for many sites at scale (e-commerce, bigger and more complex publications), at least to me the GraphQL felt like an extra level of complexity that felt unnecessary.

The more I iterated on my blog, the more the technical choice of GraphQL felt unjustified (for my use-case at least), building data sources felt way more complicated than it should have been:

Excerpt of my gatsby-config.js and gatsby-node files

4

module.exports = () => {

8

resolve: 'gatsby-plugin-mdx',

10

extensions: ['.mdx', '.md'],

12

default: require.resolve('./src/templates/BlogPost.tsx'),

17

resolve: `gatsby-source-filesystem`,

20

path: `${__dirname}/content/`,

29

exports.createPages = ({ graphql, actions }) => {

30

const { createPage } = actions;

31

return new Promise((resolve, reject) => {

61

result.data.allMdx.edges.forEach(({ node }) => {

63

path: `/posts/${node.frontmatter.slug}`,

64

component: node.parent.absolutePath,

66

timeToRead: node.timeToRead,

67

cover: node.frontmatter.cover,

68

tableOfContents: node.tableOfContents,

Another example that felt weird is that it was suggest that something as simple as my website config (a simple JS object) needed to be queried via GraphQL:

Excerpt of my site config and its corresponding query

6

export const pageQuery = graphql`

That feeling grew stronger when I wanted to add some simple functionalities, like generating a sitemap. The only way to have those working within the Gatsby Build pipeline was to leverage that GraphQL layer which I barely understood the inner workings of it. This made my entire setup rely on plugins to let me iterate fast on this website.

On top of that, it seems that the company behind Gatsby keeps releasing abstraction layers to address the plugin issues, and then new abstraction layers on top of that to solve the problems created by the previous one. During my short time using Gatsby, it went from promoting plugins to themes to recipes which was overwhelming.

This thread from @tesseralis illustrates well how I feel about some of the technical choices that were made.

The plugin ecosystem is a double edge sword

As helpful as it seemed at the beginning, it became clear over time that delegating some of the core functionalities of my blog to plugins was not such a good idea after all:

  • A lot of plugins depended on each other, like gatsby-plugin-sharp, gatsby-image, or any related plugins I was using for image optimization/processing. They needed to be updated altogether, and many times I found myself spending lots of time trying to find the right combination of versions to avoid breaking my setup.

  • I was relying on a lot of plugins for canonical URLs and SEO in general. These would often break or change their behavior after an update without any warning, or collide with one another. All my meta tags were erased one time because I added a plugin to my list in the wrong order without noticing it. Twitter Cards, Opengrah Images, ... all gone for several days 😱 not ideal when you try to build a proper SEO strategy.

  • More plugins meant more node_modules which meant also longer install and build time. Over time it added up to quite a bit

Moreover, as the community grew, so did the number of plugins! This is a positive thing, don't get me wrong. But just try to search for RSS in the Gatsby Plugins website. There are 22 plugins (as I'm writing these words) doing more or less the same thing but each of them in a slightly different way. One would need to do a lot of digging to find which one is the "official"/"recommended" one to use which is not ideal. I'm pretty sure a little bit of curation in the plugin section would go a long way.

As a result, I was pouring hours of personal time maintaining, fixing, and expanding this site. Over time I grew tired of working with Gatsby's technical choices and started spending a lot of time working around them, thus making using Gatsby itself less and less justifiable.

The migration

This migration to Next.js was the opportunity for me to accomplish the following:

  • Learn a bit more about Next.js on a more complex project.

  • Strive for simplicity! No GraphQL or over-engineered tech, it's just a blog. No theme, few plugins, a minimum amount of dependencies.

  • Focus on performance. Address any pitfalls and make sure my blog was ready for the rollout of Core Web Vitals

The process

I like to treat my blog like a product, so I wanted to conduct this migration as seriously as possible, without negatively impacting the reading experience or my traffic. Thus I established a little process to ensure that this effort would be successful:

  1. Reimplement my pages and the "MDX article pipeline", i.e. getting my article and their custom widgets/components to render, generate sitemap, OpenGraph images, and RSS feed.

  2. Migrating over all my React components from my Gatsby Theme onto the repository of the blog.

  3. Cleaning up my dependencies. Some pieces relied on packages that seemed a bit overkill, like Scrollspy, table of content, etc...

  4. Test, test, and test, especially anything related to SEO!

Thankfully, I built a sturdy automated CI/CD pipeline in the past that assisted me along the way making sure I was not breaking anything unknowingly. (Thank you Maxime from 2020 🙏)

Once a satisfying result was achieved, I started a slow rollout of the blog throughout a week. For that, I used Netlify's "split branch" feature. I deployed 2 branches (main for the Gatsby version, next for the Next.js version) under the same project, and slowly redirected the traffic to the new version, or falling back to the old one if issues were to occur.

Screenshot of the Netlify Split Test feature used here while releasing the new Next.js version of my blog

Screenshot of the Netlify Split Test feature used here while releasing the new Next.js version of my blog

This gave me great peace of mind, knowing that whatever would happen, I'd always have the "legacy" version available if I ever needed to roll back my blog in the short term. It was while executing this process that I was able to see Next.js shine, but also noticed some of its caveats, specifically for certain aspects of my use case.

Where it shined

Next.js is incredibly fast and easy to iterate with. I have never worked this fast on my blog:

  • Adding new data sources felt incredibly easy compared to Gatsby as I could pretty much load my MDX documents the way that fit my use-case.

  • The configuration required is light, well documented, and compatible with any package I was familiar with for basic React projects.

While Gatsby felt like building a blog with pre-build LEGO pieces, Next.js on the other hand was the total opposite. The framework is very unopinionated and there are very few "plugins" per se as most of the community seems to implement their own pieces/scripts that fit exactly their setup.

Want to generate your sitemap at build time? You need to build your own script. What about generating OpenGraph images? Same, build your own!

This can seem like a huge trade-off, but I actually like this aspect of Next.js:

  • I write these scripts for myself now. They don't need to be perfect or fit some specific requirements from the framework, i.e. no need for GraphQL for such an easy use case, which felt liberating. On top of that, it's a lot of fun! (at least to me 😛)

  • I can use any library I want to assist me. No need to build or add an unnecessary plugins with additional dependencies to get the desired output.

The most important take here is that I finally feel in control of my blog. No more black boxes! 🙌

Caveats

As liberating as it may feel at first, there were still some caveats about not having all these pre-built tools that I was used to with my previous setup.

Gatsby has a better MDX support, at least as I'm writing these words. I struggled to find the right library to get a similar MDX experience on Next.js as the official next/mdx library was lacking a few things I needed. This was a bit worrying at first as MDX is at the core of my blog and I wanted to continue using it the way I was accustomed to.

I opted for next-mdx-remote, however, it came with one particular tradeoff:

  • it required me to put all my MDX components in context of all MDX files. This means this article technically knows about the widgets I wrote in my Framer Motion blog posts for instance. Before I could have discrete import statements in my MDX files, this is not an option anymore.

  • this increased the bundle size of my blog posts, at scale in the long run this might be a problem. However, it looks like lazy loading those component is a good workaround to this issue.

Lazy Loading MDX components with Next.js and next-mdx-remote

1

import dynamic from 'next/dynamic';

3

const FramerMotionPropagation = dynamic(() =>

4

import('./custom/Widgets/FramerMotionPropagation')

6

const FramerMotionAnimationLayout = dynamic(() =>

7

import('./custom/Widgets/FramerMotionAnimationLayout')

9

const FramerMotionAnimatePresence = dynamic(() =>

10

import('./custom/Widgets/FramerMotionAnimatePresence')

13

const MDXComponents = {

14

FramerMotionPropagation,

15

FramerMotionAnimationLayout,

16

FramerMotionAnimatePresence,

19

const Article = ({ post }) => {

22

<MDXRemote {...post.mdxSource} components={MDXComponents} />

Image optimization also slowed me down. Vercel released next/image not long before I started the migration, but the way it worked was opposite from what I was used to with Gatsby: Gatsby would optimize images at build time, while Next optimizes images on the fly. This meant 3 things:

  1. I would get faster build time on Next.js 🚀

  2. I had to hardcode the height and width of all my images 😅.

  3. I needed to either use a 3rd party image service to host my images or host my blog on Vercel as at the time, Netlify did not support next/image.

I did not want to risk doing both a framework migration AND a platform migration at the same time. I stayed on Netlify and patiently waited for a couple of weeks, but the resulting next/image support was not entirely satisfying to me.

Thus I ended up opting for Cloudinary to host my images. Below you'll find the Image component I use in my MDX file to lazy load my images:

My next/image loader and component

1

import NextImage from 'next/image';

3

const loader = ({ src, width, quality }) => {

4

return `https://res.cloudinary.com/abcdefg123/image/upload/f_auto,w_${width},q_${

9

const Image = (props) => {

12

<NextImage {...props} loader={loader} quality={50} />

13

<figcaption>{props.alt}</figcaption>

How I use my next/image powered Image MDX component

2

src="blog/netlify-split-test.jpg"

3

alt="Screenshot of the Netlify Split Test feature used here while releasing the new Next.js version of my blog"

This made me realize that there could be potential risks of using Next.js the way I do in the future:

  • By not hosting on Vercel, I may have to wait to get some core features that I need

  • The resulting support of these features might not be as good as they might be on Vercel and might force me to find workarounds.

This is not a big deal right now, or even the case, but, it's something that is a possibility and that I need to keep in mind.

What's next?

Overall, I'm glad I made the jump to Next.js, learned a lot, and feel that my blog has improved quite a bit, especially performance-wise. Now that the migration of my blog is over I can finally focus on some of the plans I have for it:

  • A dedicated Learning In Public section where you can track what I'm currently learning, and also find all the resources I'm using

  • A Newsletter section where you can read all the past issues of my newsletter

  • Focus on performance improvements. I'm striving to get perfect Core Web Vitals scores ✅ ✅ ✅

On top of that, I'm currently migrating my portfolio to Next.js as well, so there will probably be a few new things I'll experiment with there as well (mini-projects/experiences, updated case studies, ...).

TLDR

  • To me, Gatsby is a choice if you're getting started with building your blog for the first time without prior knowledge.

  • Plugins are a great way to abstract away some of the complexity but be wary of relying on them too much especially if you want some custom behavior over time.

  • By using a lot of plugins, keep in mind that this will increase install and build time. You will end up with lots of node_modules

  • Some of Gatsby's technology choices may feel over-engineered, especially if you're not a fan of GraphQL.

  • Next.js is simpler, unopinionated, and most importantly blasting fast!

  • You'll feel more in control of a Next.js project compared to a Gatsby project.

  • You'll have to build a lot of things from scratch to make your blog work, this can be both a good or a bad thing depending on what you want to achieve.

  • Once you figure out some of the little caveats I mentioned, you will have a great time with Next.js!