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

推荐订阅源

P
Privacy & Cybersecurity Law Blog
Engineering at Meta
Engineering at Meta
Forbes - Security
Forbes - Security
MongoDB | Blog
MongoDB | Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
A
About on SuperTechFans
量子位
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
雷峰网
雷峰网
腾讯CDC
P
Proofpoint News Feed
S
Schneier on Security
S
Secure Thoughts
V
Visual Studio Blog
Help Net Security
Help Net Security
The Hacker News
The Hacker News
C
Cyber Attacks, Cyber Crime and Cyber Security
P
Privacy International News Feed
SecWiki News
SecWiki News
S
SegmentFault 最新的问题
T
Threatpost
小众软件
小众软件
MyScale Blog
MyScale Blog
F
Fortinet All Blogs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
P
Proofpoint News Feed
T
Tailwind CSS Blog
I
Intezer
C
CERT Recently Published Vulnerability Notes
U
Unit 42
V
V2EX
Cyberwarzone
Cyberwarzone
Recorded Future
Recorded Future
O
OpenAI News
Project Zero
Project Zero
有赞技术团队
有赞技术团队
Google DeepMind News
Google DeepMind News
Last Week in AI
Last Week in AI
Hugging Face - Blog
Hugging Face - Blog
Know Your Adversary
Know Your Adversary
C
Cybersecurity and Infrastructure Security Agency CISA
Scott Helme
Scott Helme
V2EX - 技术
V2EX - 技术
博客园 - 叶小钗
S
Securelist
A
Arctic Wolf
The Cloudflare Blog
W
WeLiveSecurity
T
Threat Research - Cisco Blogs
博客园 - Franky

Graphite blog

Introducing Code Tours: a new way to review Introducing Cursor Cloud Agents in Graphite Building the future of software development with Cursor Reimagining the PR Page: Designing for speed and focus Graphite changelog [11-20-2025] Graphite changelog [11-04-2025] Graphite changelog [10-16-2025] The future of engineering is collaborative (and already here) Meet Graphite Agent: the next evolution of AI code review Introducing frozen branches: A safer way to build on your teammates’ work Graphite changelog [09-17-2025] How we sped up code search for Graphite Chat Introducing Graphite Chat AI is writing code—here's why it also needs to review that code How I got Claude to write code I could actually ship How we built the first stack-aware merge queue (and why it matters) How we organize our monorepo to ship fast Graphite brings stacking to Tower Code review tooling: Should you build or buy? Making AI code review available to everyone Introducing: The new Graphite + Linear integration Graphite raises $52M and launches Diamond to reimagine code review for the age of AI Why AI will never replace human code review How stacked PRs unblock distributed development teams Graphite is going to Developer Week 2025 Beating the end of year code freeze How Graphite’s eng team ships code remarkably fast Why we chose Anthropic's Claude to power Graphite Reviewer AI code generation will remain fragmented How we redesigned Graphite's landing page in-house Introducing Graphite Reviewer: your AI code review companion How AI code review reduces review cycles to improve developer productivity What if you could get instant feedback on your code? The new developer toolchain Not Rocket Science - How Bors and Google’s TAP inspired modern merge queues Graphite's State of code review 2024 How Google migrated billions of lines of code from Perforce to Piper Going from 0 to 1: How to write better unit tests when there are none Speed up your merges: Parallel CI is now generally available for teams using Graphite’s merge queue Down for less than four minutes a month: how AWS deploys code BitKeeper, Linux, and licensing disputes: How Linus wrote Git in 14 days Graphite is now free for startups and open source projects Launch week wrap-up (May 2024) Reduce CI costs for Buildkite and GitHub Actions Cheaper CI & faster merging with batching How Google does code review The technical learning curve at a startup is gentler than you might think Graphite will now automatically rebase your partially-merged stacks Multiple engineers can now seamlessly collaborate on the same stack of PRs Do you ever outgrow GitHub? From the 80's to 2024 - how CI tests were invented and optimized Graphite changelog [4/10/2024] 🎺 Graphite changelog [4/25/2024] 🐸 How Stack Overflow replaced Experts Exchange How GitHub monopolized code hosting Graphite changelog [3/27/2024] 🤝 The core principles of building a good AI feature Onboarding roulette: deleting our employee accounts daily Graphite changelog [3/13/2024] 🚁 Why Facebook doesn’t use Git How to recreate the Phabricator code review workflow Types of code reviews: Improve performance, velocity, and quality What's the best GitHub pull request merge strategy? Phabricator vs GitHub vs Graphite: How do they stack up? Improving team velocity through better pull request practices Moving fast breaks things: the importance of a staging environment Building trust as a software engineer Keeping code simple: moving fast by avoiding over-engineering What's better than GitHub pull request filters? The Graphite pull request inbox 7 Best Phabricator alternatives for PR stacking + code review [2024] Accurate eng estimations: predicting and negotiating the future Tracking and understanding GitHub PR stats: A step-by-step guide 8 pull request best practices for optimal engineering What’s next for Graphite Graphite Q1 Launch week: Stacking with the tools you love Graphite Q1 Launch week: Making stacking seamless Accelerating code review The Mom Test How to use stacked PRs to unblock your entire team Graphite Q1 launch week 2024 The practical and philosophical problems with AI code review Empirically sup code review best practices Call site attribution: how to pinpoint rogue SQL queries throttling your performance Every engineer should understand git reflog Post mortem: we took 124 seconds from you, here's 378 back Your GitHub pull request workflow is slowing everyone down Optimizing CI/CD workflows for trunk-based development Why we use AWS instead of Vercel to host our Next.js app How large pull requests slow down development 3 key lessons in application server optimization Trunk-based development: why you should stop using feature branches Git was built in 5 days Why large companies and fast-moving startups are banning merge commits How long should your CI take? Experimenting with AI code review Graphite Changelog [10/18/2023] The comprehensive guide to writing the best PR title of all time How 10,000 Developers All Contribute to the same Repo
CRA to AppRouter in 5 Steps: A case study with Graphite
Kenneth DuMe · 2023-10-24 · via Graphite blog

At Graphite, we believe Next.js is the future. For anyone developing scalable, high-performance web applications, you need to migrate away from Create React App (CRA) and instead move to the Next.js framework.

Now, you may read this and think that sounds challenging. So did we, at first! Our codebase is structured in a sprawling, typescript monorepo, that dozens of developers collaborate on simultaneously. This made things a little more complicated, and our first attempts at migration were incredibly long, expensive, and failed partway through. However, after talking to members of the Vercel team, and using the new App Router, we condensed the entire migration into 5 simple PRs.

Before we tackle that though, let’s look at the difference between Next.js and CRA, and why we would even want to migrate in the first place.

What’s the difference between Next.js and a single-page application (SPA)?

There are two main differences between Next.js and single-page applications, such as those created by Create React App:

1. Rendering and data fetching:

Next.js supports multiple rendering strategies including server-side rendering (SSR), static site generation (SSG), incremental static regeneration (ISR), and client-side rendering (CSR). Depending on the specific page's needs, developers can choose whether to render at compile time, on the server, or in the browser.

On the other hand, Single-page applications built with Create React App are entirely client-side rendered: the application's content is rendered in the browser using JavaScript. The server sends a nearly empty HTML file, and JavaScript running in the browser fetches data and populates the page. This can increase latency and hurt page responsiveness as the JavaScript is downloaded, parsed, and executed.

2. Routing:

Because of this, the two also differ in how they handle routing. Next.js uses a file-system-based router built on App Router. By simply adding files to the 'pages' directory, routes are automatically available (and rendered by the selected strategy). Dynamic routing is also supported by creating files or folders with square bracket notation, e.g., pages/posts/[id].js.

Create React App on the other hand does not provide built-in routing. Instead, developers often integrate libraries like react-router to handle SPA-style navigation, where route changes do not trigger full page reloads but dynamically change page-contents based on the URL.

These two differences allow Next.js to optimize performance and improve developer experience in ways that just aren’t possible in a traditional single-page application model.

The benefits of Next.js over SPAs:

1. Bundle-splitting:

This is one of the biggest advantages with Next.js. Traditional single-page applications tend to send a large JavaScript bundle containing the entire application to the browser upon initial request. This can be inefficient, especially for large applications which need to parse and execute this code before first paint. Next.js however, automatically splits your codebase into smaller JavaScript bundles for each page, meaning that users only load the JavaScript necessary for the current page, greatly improving load times and overall performance.

2. Performance improvements:

Along with bundle-splitting, Next.js’s out-of-the-box optimizations like automatic image optimization, and smart prefetching, contribute to faster load times and overall user experience. Since Next.js supports both server-side rendering(SSR) and static site generation(SSG), it can deliver fully-rendered pages to the client, which can significantly improve perceived performance, especially on slower networks.

3. SEO and crawling:

We’re not the only ones who favor Next.js. Search engines also have an opinion. One historical downside of SPAs is the potential for SEO challenges, since not all search engine crawlers execute JavaScript effectively. With Next.js's server rendering capabilities, you deliver fully-rendered HTML content to crawlers, ensuring optimal indexing.

4. It's where web development is moving:

The web development landscape is rapidly evolving and new tools and frameworks are constantly emerging. Next.js is the latest in that category, offering increased flexibility, scalability, and performance improvements without adding much overhead. Backed by Vercel, Next.js has plenty of development resources behind it while at the same time enjoying the benefits of a strong community and ecosystem. It also seamlessly integrates with the JAMstack architecture, which is becoming the go-to for modern web development due to its scalability and performance benefits. More and more developers are moving to Next.js.

A journey in 5 pull requests

Knowing the differences between the two, let’s take a look at the 5 pull requests that made our migration possible.

1. HTTPS in local development:

The first problem we had was an API difference between react-scripts (the library CRA uses to power npm start) and Next.js. React-scripts has the flag HTTPS=true to serve content using HTTPS in local development. Unfortunately Next.js doesn’t have anything analogous, expecting you to use a third-party tool for that.

Following a stack overflow post, we adopted local SSL proxy. This allowed us to serve local host through  HTTPS, ensuring that our local development would remain unchanged.

2. SVG imports:

Create React App has a lot of built-in magic to allow you to import SVGs in JSX. Honestly it magically supports the import of all sorts of files, but the main one we cared about was SVGs. This was achieved using a specific configuration of the SVGr library which takes SVGs and converts them into react components. Unfortunately, Next.js doesn’t have this same support out of the box.

As a solution, in this PR, we imported SVGr and updated to its latest, recommended syntax that supports export as both a name component and as a default component. This entailed refactoring a handful of library imports but overall was a pretty small change.

3. Refactoring folder structure:

So this one is probably specific to us. As we mentioned above, Next.js has this awesome built-in routing functionality. Unfortunately, to support that functionality , Next interprets files in the “pages” directory as routes and assumes that they have specific exports.. While we did have a “pages” directory, they were not Next routes and did not have the required exports.

This PR renamed the directory “pages” to “router-pages”.

4. Integrating Next.js:

This next pull request (pun intended) is where the bulk of the migration took place; this is where the magic happens.

This pull request included a couple of different changes that I’m going to break out into a few steps.

Making Next work

First thing we had to do was introduce the next.config.js file to configure Next.

We didn’t do anything special with the configuration other than disabling static images. We did this because moving to Next’s image serving right now would require a pretty big amount of lift. We realized though we could split this out into an upstream PR later. So for now we turned this off.

The next thing we did was tweak our Webpack configuration; all we did here was update webpack to use the right SVGr version.

Furthermore, two new files, layout.tsx and page.tsx, were introduced. While layout.tsx replicated the layout previously defined in an index.html in CRA, page.tsx effectively took over what used to be in the app.js.

Development mode

Then because we’re coming from a single-page application, in the next.js config, we inject a rewrite, which says “hey for any page loaded, let’s just put you right at the index.” This allowed us to maintain our client-side routing pattern for the time being.

Git updates

So here we just updated out gitignore to ignore the .next folder, something we didn’t have to think about before

Tests

And finally we had to create a bunch of test mocks to handle file imports. You gotta have your tests

These changes enabled us to drop in Next.js; the package.json was updated to replace references of CRA (or in our case, Create React App rewired) with Next commands.

5. Handling server-side rendering (SSR):

The final PR was to handle server-side rendering or SSR. SSR introduces complexities when accessing objects like window and document. We added conditional checks before accessing objects exclusive to the browser environment. This prevented errors during server-side rendering (where JS might try to access window and run into window is undefined). 

Additionally, Next renders content on the server (for initial render) and on the client (for updates), and reconciles them through a process called hydration. If these two do’nt match, Next throws an error. Because React Router does not work on the server, we implemented an initial empty render for both server and client. This was a temporary solution to avoid hydration mismatches that we can remove after we migrate to Next’s routing.

Beyond these primary steps, we  also updated our Content Security Policy (CSP). Next.js injects inline scripts, which are disallowed under our CSP. We resolved this by adding a build step to hash all inline scripts.

We hope our little expedition showed you that migration to Next doesn’t have to be scary, and is well worth it. As we continue our development journey, we plan on fully integrating all the rest of what Next.js has to offer.