React팀의 CRA에 대한 생각 살펴보기

정혜인·2024년 10월 9일
1

딥다이브

목록 보기
4/4

저번에 작성한 블로그 포스팅에서 "npx create-react-app이 어떻게 동작하는지"에 대해 학습하면서, CRA가 어떻게 동작하고, CRA 없이 직접 react 프로젝트를 세팅하는 방법을 작성하였습니다.

CRA에 대해 학습해보면서 이렇게 react 프로젝트가 세팅된다는 것을 처음 알게 되었고, 그럼 과연 초보 개발자들에게 처음부터 CRA로 리액트를 시작하게 하는 것이 옳은 일인지, 개발자의 성장을 위해 처음부터 너무 편리함만을 제공한 것은 아닌지에 대해 고민해보게 되었습니다.

그러다 현재 코드 리뷰를 해주고 계신 멘토님께 이런 제 블로그 포스팅에 대해 피드백을 요청 드렸고, 멘토님께서 관련하여 재미있게 본 PR이 있었다고 공유해주셨습니다.

해당 PR에서는 저와 비슷한 생각을 갖고 있는 개발자들이 많다는 것을 알게 되었고, 많은 개발자들에게도 공감받고 있다는 사실을 확인할 수 있었습니다.

💫 PR에서의 질문

PR 링크는 아래와 같고, 너무 길기에 질문과 답변에 대한 요약을 아래에 작성해보았습니다.

https://github.com/reactjs/react.dev/pull/5487

https://github.com/reactjs/react.dev/pull/5487#issuecomment-1409720741

이 PR은 @t3dotgg라는 분께서 CRA가 개발자에게 좋지 않다고 이야기함으로써 시작됩니다.

Create React App is not a great recommendation to be making, especially for newer developers.

As an educator, I run into countless issues w/ new React devs running into unnecessary issues due to the continued recommendation of CRA. I made a tweet about this and was amazed by the amount of devs who agree

I'm in no way attached to the specific changes I made here, mostly opening this in hopes of a discussion around the technologies recommended in the new Beta docs.

이를 번역해보면 아래와 같습니다.

Create React App은 특히 개발을 처음 하는 사람들에게 좋은 추천이 아닙니다.

CRA의 지속적인 추천 때문에, 교육자로서 저는 신입 React 개발자들이 불필요한 문제에 부딪히는 등과 같은 수많은 문제에 직면하고 있습니다. 저는 이에 대해 트윗을 올렸고, 이에 동의하는 개발자의 수에 놀랐습니다.

여기에 제가 생성한 PR이 변경 사항과는 아무런 관련이 없으며, 주로 새로운 베타 문서에서 권장하는 기술에 대한 논의가 있었으면 하는 바람으로 이 글을 올립니다.

위의 질문에서 t3dotgg는 CRA가 더 이상 좋은 출발점이 아니라고 이야기하고, 실제로 많은 개발자들이 동의하고 있다는 점을 언급하고 있습니다.

저 또한 CRA에 대해 학습해보면서 react를 처음 배우는 사람이 바로 CRA로 시작했을 때 발생하는 문제점에 대해 인지하고 있었기에 굉장히 공감할 수 있었고, 이 질문의 답변이 궁금해졌습니다.

💥 질문에 대한 답변

유명한 meta의 react 개발자인 Dan이 답변해주었고,

답변이 너무 길기 때문에, 가장 아래에 첨부해두었습니다.

결론적으로 이 답변을 정리해보자면,

CRA를 처음 만들게 된 이유 → 시대가 변화하면서 발생한 (드러난) CRA의 문제점 → 초기 CRA의 목표와 현재 변화한 React 생태계에서 발생하는 간극 → 앞으로 CRA가 나아갈 수 있는 여러가지 방향 → 여러가지 옵션 중 현재 CRA 팀에서 나아가고자 하는 방향을 차례대로 제시해줍니다.


그리고 이건 다른 이야기이긴 하지만 개인적으로 이 분… 글을 정말 논리적으로 잘 쓰셨다는 생각이 들었습니다…..

먼저 이 PR에서 개발자들이 제시한 문제가 무엇인지, 이 PR을 통해 얻고 싶었던 것이 무엇인지를 정확히 알고 있다는 점, 그리고 팀에서도 그런 점들을 모두 동의하고 인지하고 있다고 이야기하며 공감을 충분히 하고 있고….

또 그럼에도 불구하고 CRA 팀의 입장에서 이 문제를 당장 개선할 수 없었던 이유를 납득 가능하게 설명하고…….

마지막에는 팀에서 할 수 있는 해결 방안을 5개로 정리하여 모두 제시하면서, 현재 팀에서 이야기한 내용으로는 5개 중 5번째 선택지의 방향으로 가려고 한다고 주장을 이야기하고, 그렇게 선택한 근거도 명확하게 설명하고…

또 그와 동시에 여러분의 피드백을 듣고 싶고, 앞으로도 최선을 다해 여러분과 논의하고 공유하고 싶다고 마무리합니다……

물론 사과문은 아니지만 이 글을 보면서 느낀 건 .. 연예인들 사과문 올릴 때 보면, 가끔 너무 깔끔하고 똑 부러진다고 칭찬 받는 경우가 있는데, 이 글도 본인의 주장을 납득시키는 글 중 정석이라고 할 수 있지 않을까.. 싶은 생각이 들었습니다.


이런 느낌.......


어쨌든 글을 먼저 요약해보자면, 4가지 단계로 나눌 수 있고, 아래와 같이 정리할 수 있습니다. (이 부분은 Chat GPT의 도움을 받았기 때문에 정확하지 않을 수 있습니다 ㅎ)

CRA의 배경: 2016년 출시 당시, React 앱을 쉽게 시작할 방법이 없었고, 다양한 도구들을 통합하는 과정이 복잡했습니다. CRA는 이 문제를 해결하여, React 프로젝트를 쉽게 시작할 수 있는 표준 도구로 자리 잡았습니다.

CRA의 문제점: 시간이 지나면서 CRA는 성능 문제와 최신 도구 지원 부족 등으로 한계를 드러냈습니다. 특히, 클라이언트 측 렌더링만 지원하기 때문에, 빈 HTML 파일을 로드한 후 모든 스크립트를 다운로드해야 하는 비효율적인 사용자 경험을 초래합니다. 서버사이드 렌더링(SSR)이나 정적 사이트 생성(SSG)이 필요할 때, CRA는 적절한 솔루션을 제공하지 못했습니다.

React 프레임워크의 부상: Next.js, Gatsby, Remix 등과 같은 프레임워크는 CRA가 해결하지 못한 문제들을 해결하며, 컴파일, 렌더링, 라우팅, 데이터 페칭을 통합하여 더 나은 사용자 경험을 제공합니다.

React의 미래: React는 프레임워크와 결합하여 SSR, SSG, 코드 분할, 라우트 기반 데이터 페칭 등의 기능을 지원하는 방향으로 나아갈 것이며, 프레임워크가 React의 최적화 기능을 최대한 활용할 수 있도록 발전할 예정입니다.

💌 논의되는 문제

이 토론(?)에서 이야기한 내용들을 조금 더 구체적으로 살펴보자면,

먼저 CRA의 문제점으로 언급되는 것들은 크게 아래와 같이 정리할 수 있습니다.

  1. 불필요한 의존성: CRA는 불필요하게 많은 패키지와 설정을 포함하고 있어, 프로젝트 규모가 커지면서 관리가 어려워짐
  2. 느린 빌드 시간: CRA는 큰 프로젝트에서 빌드 속도가 느려지기 때문에, 생산성에 영향을 미침
  3. 초보 개발자에게 혼란: CRA는 처음에는 빠르게 시작할 수 있지만, 복잡한 설정이나 확장성 문제로 인해 초보 개발자들에게 오히려 장애물이 될 수 있음

💦 그렇다면 대안은 ?

이러한 문제점들 때문에 react팀에서는 여러 대안을 제시한 것인데, 크게 5가지를 제시한 뒤 이 중 옵션 5를 택하는 방향으로 나아가겠다고 답하였습니다.

옵션 1: 처음부터 새 프레임워크 만들기

Create React App을 데이터 페칭, 라우팅, 번들링, SSG/SSR을 통합하는 프레임워크로 재구성해 볼 수 있습니다. 이러한 우려 사항의 교차점에서 고품질의 새로운 프레임워크를 구축하는 것은 엄청난 작업이며, 많은 전문적인 생태계 전문 지식이 필요하며, 이를 실현하기 위해 다른 프로젝트를 중단하더라도 Create React App 자체처럼 시간이 지남에 따라 정체될 상당한 위험이 있습니다. 또한 실제 사용자가 없음에도 불구하고 공식적으로 권장되는 또 다른 프레임워크로 생태계를 더욱 분열시킬 것입니다. 현재로서는 이 옵션이 실용적이지 않다고 생각합니다.

옵션 2: Create React App 사용 중단, Vite 템플릿 유지

Create React App을 폐기하고 대신 우리만의 Vite 템플릿을 유지할 수도 있습니다. 명시된 목표를 달성하려면 이 템플릿이 매우 정교해야 합니다. 사실, React 프레임워크만큼 정교해야 하며 라우팅, 데이터 페칭 등에 대한 의견을 부과해야 합니다. 그러면 같은 문제가 발생합니다. 사실상 또 다른 프레임워크를 만드는 셈이 됩니다.

옵션 3: Create React App 사용 중단, React 프레임워크 제안

Create React App을 도구로서 덜 강조하거나 더 이상 사용하지 않고 React 프레임워크를 더 적극적으로 강조할 수 있습니다. 이는 React와 함께 프레임워크를 사용해야 한다는 것을 의미하지는 않지만, 대부분 앱에 프레임워크 중 하나를 사용하는 것이 좋습니다 . 단점은 React 앱을 만드는 데 중립적인 브랜드의 CLI "게이트웨이"가 더 이상 없다는 것입니다. 해당 프레임워크의 문서에서 올바른 게이트웨이를 찾아야 합니다. 완전히 사용하지 않는 것도 방해가 됩니다. 명령을 오랫동안 작동 상태로 유지해야 하며, 이는 브랜딩 관점에서 혼란스럽습니다("React 앱을 만드는 것이 더 이상 사용되지 않는 이유는 무엇입니까?").

옵션 4: Create React App이 단일 프레임워크를 사용하도록 만들기

지정된 프레임워크 하나를 선택하고 Create React App을 변경하여 기본적으로 해당 프레임워크로 앱을 만들 수 있습니다. 이 접근 방식의 주요 문제는 다른 솔루션이 경쟁하기 매우 어렵다는 것입니다. 특히 약간 다른 장단점이 있지만 인기, 기능 세트 및 품질이 거의 동일한 경우 더욱 그렇습니다. 이러한 동작의 변화는 모든 이전 튜토리얼이 명확하지 않은 방식으로 중단되기 때문에 매우 파괴적이어야 합니다.

옵션 5: Create React App을 런처로 전환

Create React App을 명령으로 유지하지만 런처로 바꿀 수 있습니다. 추천 프레임워크 목록을 제안한 다음, 마지막 옵션인 "클래식" 프레임워크 없는 접근 방식을 제안합니다. 마지막 "클래식" 접근 방식은 CRA가 지금 하는 것처럼 클라이언트 전용 앱을 생성하지만(튜토리얼을 깨지 않도록 하기 위해), 결국 후드 아래에서 Vite로 이동할 수 있습니다.

큐레이트된 프레임워크 목록에 올라가려면 React 프레임워크가 특정 기준을 충족해야 합니다. 이는 사실상 이 문서 페이지 에서 발생하는 것과 유사합니다. 커뮤니티에서의 인기와 채택(목록을 짧게 유지하기 위해), 기능 세트, 성능 특성, 웹 플랫폼과 React 자체를 최대한 활용할 수 있는 능력, 적극적으로 유지 관리되는지 여부, 다양한 호스팅 서비스 및 환경에서 호스팅하는 방법이 명확한지 여부(공급업체에 종속되는 것을 피하기 위해)를 고려해야 합니다. 각 프레임워크의 시작 템플릿은 React 팀에서 유지 관리하여 일관된 디자인과 브랜딩을 유지하고, 상업 서비스에 링크하지 않으며, 유사한 구조를 갖도록 합니다. 선택에 도달한 방식에 대해 커뮤니티에 명확하게 전달해야 하며, 주기적으로 재평가해야 합니다.

우리의 제안

현재 우리는 옵션 5("Create React App을 런처로 전환")에 기울고 있습니다. Create React App의 원래 목표는 대부분의 React 사용자에게 새로운 React 웹 앱을 시작하는 가장 좋은 방법을 제공하는 것이었습니다. 우리는 그것을 런처로 재활용하는 것이 대부분의 새로운 웹 앱에 가장 좋다고 생각하는 것의 변화를 명확하게 전달하는 반면, 동시에 이전 워크플로에 대한 탈출구를 남겨두는 것을 좋아합니다. 옵션 3과 달리, 그것은 "React 앱 만들기"가 어떻게든 더 이상 사용되지 않는다는 인식을 피합니다. 그것은 약간의 선택이 필요하다는 현실을 인정하지만, 지금은 선택할 수 있는 정말 좋은 옵션이 있습니다.

우리는 이러한 요점을 구체화하는 더 자세한 RFC 제안을 작업할 것입니다. 그동안 이러한 요점에 대한 여러분의 피드백을 듣고 싶습니다. 긴 댓글이었지만, 전체적인 사고 과정을 보여주고 이 기회를 이용하여 React와 프레임워크 간의 관계를 명확히 하고 싶었습니다. 여기에서 후속 질문에 최선을 다해 답변해 보겠습니다.

❣ 결론

결국 react 팀이 앞으로 나아가려는 방향은, Create React App(CRA)를 기존의 방식에서 벗어나 런처(launcher)로 변환하는 것이었습니다. 이는 CRA를 통해 새로운 React 앱을 시작하는 방법을 그대로 유지하되, 여러 가지 선택지를 제시하는 도구로 활용하려는 계획입니다.

기존의 CRA는 React 웹 애플리케이션을 단순히 시작하는 용도로 사용되었는데, 이번에 react팀에서 선택한 옵션은 CRA를 다양한 프레임워크 중에서 가장 적합한 프레임워크를 선택할 수 있는 플랫폼으로 확장하자는 것입니다. 여기서 중요한 점은 React 팀이 커뮤니티에서 인기가 있고, 기능과 성능 면에서도 뛰어난 추천 프레임워크 목록을 제공해서 사용자가 선택할 수 있게 한다는 것입니다.

사용자는 이 목록에서 자신에게 맞는 프레임워크를 고를 수 있고, 당연히 기존의 CRA 방식의 앱도 선택할 수 있습니다. 이때, 이 classic 방식은 Vite 같은 새로운 툴을 활용하여 더 빠르고 효율적인 빌드 시스템으로도 전환될 수 있습니다.

결론적으로 react 팀이 선택한 방식은 프레임워크 선택을 폭넓게 제공하되, 기존 CRA의 단순함을 유지하려는 의도인 것입니다.

저는 사실 어떤 게 정답이라 의견을 말하기엔 너무 잘 모르는 감자이지만, 개인적으로 react팀에서 선택한 CRA를 launcher로 변환하는 것이 현재 최선의 방법이라는 것에 동의합니다.

이 PR에서 여러 사람들이 Dan의 글에 대해 많은 의견과 답변을 남겨준 것 또한 확인할 수 있었는데, 여러 의견 중 nickserv가 남긴 각 옵션별 본인의 생각을 정리한 것이 인상 깊어서 공유해보려 합니다.

옵션 1: 처음부터 새 프레임워크 만들기

SSR을 이미 지원하는 것(예: Vite/Astro)을 기반으로 하지 않는 한 너무 복잡합니다.

옵션 2: Create React App 사용 중단, Vite 템플릿 유지

제가 가장 좋아하는 옵션은 SSR 지원을 템플릿 추가 옵션으로 추가할 수 있다는 점입니다.

옵션 3: Create React App 사용 중단, React 프레임워크 제안

초보자에게 클라이언트 측에서 React를 효과적으로 사용하는 방법을 가르쳐주지 않으며 React 커뮤니티가 실제로 하는 일과 문서에서 권장하는 것(예: 문서 베타 이전에 hooks가 출시된 방식)이 분리될 위험이 있습니다. 또한 React를 Vercel에서 가장 잘 실행되는 Next와 같은 것에 임의로 결합하는 것에 대해서도 우려하고 있습니다. React와 Vercel은 Next 사용자가 다른 프레임워크를 사용할 수 없고 Vercel 외의 다른 곳에 배포하지 않도록 하는 데 이점이 있다는 것을 알고 있지만, 이는 오픈 소스 소프트웨어에 이상적인 경로가 아닙니다. React가 프레임워크만 지원하는 것에 대해 너무 고집을 부리면 더 유연한 대체 프레임워크로 더 많은 사용자를 잃을 위험이 있습니다.

옵션 4: Create React App이 단일 프레임워크를 사용하도록 만들기

아마도 너무 고집이 센 것 같습니다. 모듈식 Vite/Astro 등의 템플릿이 아니라면요.

옵션 5: Create React App을 런처로 전환

저는 이것이 유지 관리 측면에서 현재 상황보다 개선될 것이라고 생각하지만, 장기적으로는 교육에 잘못된 선택이라고 생각합니다. 우리는 의사 결정을 최소화하고 점진적인 학습을 허용해야지, 누군가가 기술을 배우기도 전에 기술에 대한 의사 결정을 이해하도록 강요해서는 안 됩니다.

이 분은 거의 각 옵션에 대해 발생할 수 있는 문제점을 중심으로 작성해주셨는데, 이 또한 충분히 생각해볼 문제라고 판단해서 이렇게 가져와봤습니다.

개인적으로 CRA를 launcher로 전환하는 것이 괜찮은 방법이라고 생각하긴 했지만, nickserv의 댓글 덕분에 오히려 ‘react를 처음 다뤄보는 사람들에게 너무 많은 의사 결정을 내리도록 한다면 react 프레임워크에 대한 접근성이 떨어질 수도 있겠구나’하는 생각도 할 수 있었습니다.

어쨌든 저는 이런 논의가 일어났었다는 것이 너무 재밌었고, 그냥 앞으로의 React 생태계가 어떻게 변할지가 너무 기대되고 궁금하다는 정도로 글을 마무리하겠습니다.

💨 react 팀의 답변 전문

Hi everyone.

We know this has been a pain point for a while, and we are working on a proposal to address it. Since this pull request was intended to start a discussion, this sounds like a good time to provide some background on our thinking about the future of Create React App. We want to be clear about our reasoning and the tradeoffs we're considering, so this is going to be a long comment with several sections. If you're feeling impatient, scroll to the last section for our proposed way forward.

Why Create React App exists

To provide the historical context for this discussion, I'd like to revisit the story of Create React App and retrace its evolution.

When we released Create React App in 2016, the tooling landscape was fragmented and not integrated. If you were adding React to an existing app, you'd add a <script> tag or an import from npm, and then adjust your existing build tooling configuration. But if you were creating a new app that's built just with React from scratch, there was no clear way to do it.

Before Create React App, you had to install a bunch of tools and wire them up together, provide the right presets to use JSX, configure them differently for development and production environments, provide the right settings for asset caching, configure the linter, and so on. This was very tricky to do correctly. People coped with this by creating and sharing "boilerplate" repositories that you could clone. However, that created a different problem: once you cloned the boilerplate and adjusted it for your project, it was hard to pull updates. Your project setup would get stale, and you'd either give up on updating or spend a lot of effort getting all tools to work together again. In a fast-moving ecosystem, this was very difficult.

Create React App solved this by combining several tools under one package, choosing a reasonable default configuration, and then papering over all the little incompatibilities between the tools. Now, if you wanted to start a new project with React, there was a single clear recommended way to do that! Then, every once in a while, you'd update this package, and get all the underlying tooling updates "for free". This model became so popular that there's an entire category of tools working this way today. Vite is indeed one of the best tools out there that share a similar vision—and, in some ways, takes it further.

The goal of Create React App was to provide the best way to start a new React web app for the majority of React users. It supported a curated set of features that work together. Over time, the "baseline" of what it offers out of the box would expand as we figure out the right tradeoffs. For example, we've added an overlay for runtime errors. We've added support for different styling options. We've added Fast Refresh by default, which allowed you to save your component's code and see the changes without losing the state. This was a huge milestone for the default React developer experience. In general, since Create React App had full control over the compilation pipeline, adding compilation-related features for everyone was easy.

Having a curated setup like this remains valuable to the ecosystem. When React Hooks came out, we added the React Hooks lint rules to the default setup. In addition to being an easy way to start a project, Create React App also allowed the React team to deploy non-trivial tooling changes (Fast Refresh support, React Hooks lint rules) to the broadest possible audience. It would be difficult to roll out these tooling changes so widely if there was no popular template curated by the React team.

The problems with Create React App

As the years passed, Create React App has stagnated. Many pointed out in this thread that it is slower than the alternatives, and doesn't support some popular tools that people want to use today. In principle, we could fix these issues. For example, we could update the internals of Create React App to use a faster bundler, or even to use Vite internally. Or we could suggest people to migrate from Create React App to something like Vite. However, there is a much deeper issue we want to address.

By design, Create React App produces a purely client-side app. This means that every app created with it contains an empty HTML file and a <script> tag with React and your application bundle. When the empty HTML file loads, the browser waits for the React code and your entire application bundle to download. This might take a while on low-bandwidth connections, and the user does not see anything on the screen at all while this is happening. Then, your application code loads. Now the browser needs to run all of it, which may be slow on underpowered devices. At last, at this point the user sees something on the screen — but often you'll also need to load some data. So your code sends a request to load some data, and the user is waiting for it to come back. Finally, the data loads, the components re-render with the data, and the user sees the final result.

This is quite inefficient, though it's hard to do better if you run React on the client only. Compare this to a server framework like Rails: a server would start the data fetch immediately, and then generate the page with all the data. Or take a static build-time framework like Jekyll that does the same, but during the build, and produces an HTML+JS+CSS bundle you can deploy to a static hosting. In both cases, the user would see the HTML file with all the information instead of a blank file waiting for the scripts to load. HTML is the cornerstone of the web — so why does creating a "React app" produce an empty HTML file? Why are we not taking advantage of the most basic feature of the web—the ability to see content quickly before all the interactive code loads? Why do we wait to start loading the data until after all the client-side code has finished loading?

Create React App solved only one side of the problem. It provided a good (at the time!) development experience, but it didn't impose enough structure to help you leverage the strong sides of the web for a good user experience. You could try to solve these problems yourself, but that would involve "ejecting" and significantly customizing your setup, which defeated the point of Create React App. Every truly efficient React setup was custom, different, and unachievable with Create React App.

These user experience problems are not specific to Create React App. They are not even specific to React. For example, apps created from the Vite homepage templates for Preact, Vue, Lit, and Svelte suffer from all of the same problems. These problems are inherent to purely client-side apps with no static site generation (SSG) or server-side rendering (SSR).

Although the Facebook.com rewrite from Hack/XHP rendering to React could not have shipped without SSR (which ended up being critical for performance), the problems described above don't uniquely affect large apps like Facebook. Quite the opposite! If you think about many apps developed fully in React, you'll find all kinds of content-oriented apps that would benefit from SSG or SSR. Portfolios, blogs, newspapers, e-commerce shops — it simply doesn't make sense for them to serve empty HTML files. This is why we always suggested to use SSG-capable React frameworks for content-oriented sites.

The rise of React frameworks

Some people might prefer to not build fully in React, and that's a valid option. For example, you could generate HTML pages on the server or during the build with a different tool like Jekyll or Astro. This solves the problem of empty HTML files, but you have to mix two rendering technologies (e.g. Jekyll templates for the "outer" part of the page and React components for the "inner" part). The more interactivity you want to add with time, the more noticeable this technological split becomes.

This split does not only hurt the developer experience — the user experiences suffers too. With tools that are truly HTML-centered and don't take full advantage of React, every page navigation becomes a full page reload, blowing away all the client-side state. Today, many users expect smooth in-app navigation (assuming it's done in a correct and accessible way) rather than '90s style full page reloads. Similarly, many developers prefer to build their app using a single rendering model instead of mixing two different ones. People want to build their entire apps with React. And we want to enable them to.

If you build entire apps with React, being able to use SSG/SSR is important. The lack of support for them in Create React App is glaring. But it's not the only area where Create React App is behind. After years of innovation in the ecosystem, many other problems now have mature solutions for React. For example, let's look at network waterfalls and bundle size.

Even if your app doesn't benefit from SSG or SSR as much as content-oriented sites do, it likely suffers from network waterfalls. If you fetch "on mount", your first data fetch doesn't even start until all the code has loaded and your components have rendered. That's a waterfall — it could be done in parallel if your app "knew" how to start fetching while the code is still loading. On navigation, if a parent and a child component both need to fetch something, that creates even worse waterfalls. When we talk about React performance, there's no escaping the fact that for so many apps, waterfalls are the performance bottleneck. To solve these waterfalls, you need to integrate data fetching with routing, which Create React App doesn't do.

Unlike React, which has a fixed bundle size, your application code keeps growing with every new feature and extra dependency you add. If you deploy often, your app can become very slow to load on every usage because it'll always have to load all code. There are a few ways you can solve this problem. You could say "no" to features, but this doesn't always work. You could move some code to run on the server or during the build (if your tooling allows that). Ideally, you would also split code by route: if a dashboard page needs to render a chart, there is no need to load that chart's entire implementation on the account billing page. However, if you try to do code splitting manually, you'll often make performance worse. For example, if you lazily load the chart, but the chart loads its data "on mount", you have just introduced yet another network waterfall. Solving this well requires integrating data fetching with routing and bundling, which Create React App doesn't do.

React itself is only a library. It does not dictate how to do routing or data fetching. Neither does Create React App. Unfortunately, this means that neither React alone nor Create React App, as originally designed, can solve these problems. As you can see, this isn't about a single missing feature. These features — server-side rendering and static generation, data fetching, bundling, and routing — are interconnected. When Create React App came out, React was very new, and there was still a lot left to figure out about each of these features should work in isolation, let alone how to best put them together.

Times changed. Now it's getting increasingly difficult to recommend a solution where you are locked into not having these features. Even if you don't use all of them immediately, they should be available for you when you need them. You shouldn't have to migrate to a different template and restructure all of your code to take advantage of them. Similarly, not all data fetching or code splitting needs to be route-based. But it's a good default that should be available to most React apps.

Although you could integrate all these pieces yourself, it is hard to do well. Just like when Create React App itself integrated several concerns related to compilation, tools like Next.js, Gatsby, and Remix went further — and integrated compilation with rendering, routing, and data fetching. This category of tools that integrates compilation, rendering, routing and data fetching is known as "frameworks". (Or, if you prefer to call React itself a framework, you might call them "metaframeworks"). These frameworks impose some opinions about structuring your app in order to provide a much better user experience. Many developers also find it ergonomic to have recommended scalable built-in solutions for routing and data fetching.

React as an architecture

We like the flexibility of React. You can use React to build a single button, or you can use it to build an entire app. You can use it to build an internal dashboard inside a twenty-year old Perl website, or you can make a hybrid SSG/SSR e-commerce website using React for the entire thing. This flexibility is essential, and we know our users love it too. It isn't going away.

However, we also want to encourage the best possible defaults we can for new apps fully built with React. It would be nice if the default suggested way to create React apps supported features like SSG and SSR, automatic code splitting, no client-server waterfalls, route prefetching, navigation preserving client UI state, and other features that enable a great user experience. At the very least, the default suggested way to create React apps should not be totally locked out of these features due to an inherently client-only architecture that doesn't integrate the right concerns to enable them.

This is an opportunity. For frameworks, the challenge is to integrate these concerns with great performance and ergonomics. However, there was also a challenge there for React, too. We realized that the best way we can help React frameworks to deliver great user experiences is by focusing on the underlying primitives in React itself. There are unique things that React itself can do at the rendering layer which supercharge what frameworks can do at all other layers. For example, as with <Suspense>, a single React API can unlock a whole range of framework optimizations for a framework behind the scenes.

This is why we find it helpful to think of React as two things.

React is a library. This library provides some APIs that let you define and compose components together. React is also an architecture. It provides the building blocks that let the framework authors take full advantage of its rendering model. You can use React without a framework. But we want to make sure that if you use it with a framework, the framework is able to take the best advantage of React itself. Many of the features we've been building for the past few years (<Suspense>useTransition, streaming APIs like renderToPipeableStream, and experimental Server Components) are framework-oriented. They let frameworks take full advantage of React by integrating bundling, routing, and data fetching with it.

You can already see some of these features being adopted in Next 13Gatsby 5, and Remix 1.11. There is still a lot to do, and some of this work is in the process of graduating out of the experimental stage (so documentation is still sparse). Still, we're excited to see our multi-year efforts pay off and empower React frameworks (and their users) to ship faster apps by default.

Which brings us to the next point.

One library, many frameworks

There's more than a single React framework. And that's good.

Despite concerns about the churn, the React ecosystem is better for having many players. There are multiple competing data fetching solutions and routing solutions. The options get better with every year. It shouldn't be surprising that there are also multiple solutions that integrate routing, data fetching, rendering and compilation — i.e., multiple React frameworks.

We would like to keep it that way. However, we would also like to encourage convergence where it is possible and benefits the React ecosystem. For example, different frameworks may use different mechanisms to load data. However, if they all adopt <Suspense> for loading indicators, our higher-level features on top of <Suspense> will work with all frameworks. We are still working to finalize and document APIs for frameworks, but we want to empower them to take the best from React.

Some projects will never fit into any popular framework's mold, and that's okay. Maybe you're developing an internal dashboard that needs to integrate with a PHP site, and none of the frameworks let you do that very easily. That's a great use case for a lower-level tool like Parcel or purely client-side Vite templates. Maybe your app is a drawing editor, you have no routes, and you want to opt out even from SSG. We always supported, and will support that. It's valid to continue to use React as a library rather than as a framework architecture. We only argue it's not the right default for most new web apps.

If the best way for most React apps is to start with a framework, which framework should we suggest? Should we pick one? How do we decide which one to pick? What if it gets stagnant over time? There is also a more sensitive question of incentives. Popular and well-maintained frameworks often have some kind of commercial offerings related to them — either directly or indirectly. These offerings may fund the development of those frameworks, but we'd like to avoid pushing people towards a product that, for example, only works with a particular hosting platform.

This brings us to the question in this thread.

What should we do with Create React App?

Create React App's original goals were:

  • Provide an easy way to start a new React project without configuration.
  • Integrate compilation-related dependencies to be easily upgradable.
  • Let the React team deploy tooling updates as broadly as possible (e.g. Fast Refresh support, Hooks lint rules).

However, it doesn't meet the original goal of being the best way to create a React app anymore. By raising the bar and integrating compilation with rendering, routing, and data fetching, frameworks let their users create React apps that:

  • Take full advantage of web APIs to deliver fast apps and sites by default, whether small or large.
  • Take full advantage of React itself and its framework-level features.
  • Provide routing and data fetching that let the developers fall into the "pit of success".

The React ecosystem deserves a default recommended approach that can take full advantage of the web and of React itself. This doesn't even mean necessarily depending on a Node.js server. Many popular frameworks don't require a server and can work in SSG mode, so they can address the "fully static" use cases too. The advantage of a framework is that if you later need SSR, you don't need to migrate. It's available, as are other things (e.g. Remix offers a mutation API out of the box).

How do we achieve this vision? We see a few options.

Option 1: Create a new framework from scratch

We could try to rearchitect Create React App as a framework that integrates data fetching, routing, bundling, and SSG/SSR. Building a high-quality new framework at the intersection of these concerns is a huge undertaking, requires a lot of specialized ecosystem expertise, and even if we stopped other projects to pull this off, there is a significant risk it would become stagnant over time like Create React App itself did. It would also further fragment the ecosystem with yet another framework that is officially recommended despite having no real users. We don't think this option is practical at this time.

Option 2: Deprecate Create React App, maintain a Vite template

We could deprecate Create React App and instead maintain our own Vite template. To achieve the stated goals, this template would have to be very sophisticated. In fact, it would have to be as sophisticated as a React framework — and impose opinions about routing, data fetching, etc. That leads to the same issue: we'd effectively be creating another framework.

Option 3: Deprecate Create React App, suggest React frameworks

We could deemphasize or deprecate Create React App as a tool, and emphasize React frameworks more actively. This doesn't mean you would have to use a framework with React, but that we would suggest using one of them for most apps. The downside is we'd no longer have a neutrally branded CLI "gateway" to creating a React app: you'd have to find the right one in the corresponding framework's docs. Outright deprecating is also disruptive. We'd need to keep the command working for a long while — which is confusing from the branding perspective ("why is creating a React app deprecated?")

Option 4: Make Create React App use a single framework

We could pick a single designated framework, and change Create React App to create apps with that framework by default. The main problem with this approach is that it makes it very difficult for other solutions to compete — especially if they have slightly different tradeoffs but are roughly the same in popularity, feature set and quality. Such a change in behavior would also have to be pretty disruptive since all the old tutorials would break in a non-obvious way.

Option 5: Turn Create React App into a launcher

We could keep Create React App as a command, but turn it into a launcher. It would suggest a list of recommended frameworks, followed by the "classic" framework-less approach being the last option. That last "classic" approach would produce a client-only app like CRA does now (to avoid breaking tutorials), but could eventually move to Vite under the hood.

To get on the curated frameworks list, a React framework would have to meet certain criteria — similar to what de facto happens with this documentation page. We would need to consider popularity and adoption in the community (to keep the list short), feature set, performance characteristics, ability to take full advantage of the web platform and React itself, whether it's actively maintained, and whether it is clear how to host it on a variety of hosting services and environments (to avoid any vendor lock-in). The starter template for each framework would be maintained by the React team to ensure they have consistent design and branding, don't link to commercial services, and are similarly structured. We would need to clearly communicate to the community about how we arrived at our choices, and we would periodically reevaluate them.

Our proposal

We are currently leaning towards Option 5 ("Turn Create React App into a launcher"). The original goal of Create React App was to provide the best way to start a new React web app for the majority of React users. We like that repurposing it as a launcher explicitly communicates a shift in what we think is best for most new web apps, while at the same time leaving an escape hatch for the older workflows. Unlike Option 3, it avoids the perception that "creating a React app" is somehow deprecated. It acknowledges the reality that a bit of choice is needed, but there are now really great options to choose from.

We'll be working on a more detailed RFC proposal fleshing out these points. In the meantime, we'd love to hear your feedback on these points. I know this was a long comment, but I wanted to show the whole thought process, and to use this opportunity to clarify the relationship between React and frameworks. I'll try my best to respond to follow-up questions here.

Thank you for reading!

0개의 댓글

관련 채용 정보