Knowledge Updates

Observations while developing web applications and creating great software.

  • The Man in the Arena ↗

    Teddy Roosevelt’s speech in Paris, France on April 23, 1910:

    It is not the critic who counts; not the man who points out how the strong man stumbles, or where the doer of deeds could have done them better. The credit belongs to the man who is actually in the arena, whose face is marred by dust and sweat and blood; who strives valiantly; who errs, who comes short again and again, because there is no effort without error and shortcoming; but who does actually strive to do the deeds; who knows great enthusiasms, the great devotions; who spends himself in a worthy cause; who at the best knows in the end the triumph of high achievement, and who at the worst, if he fails, at least fails while daring greatly, so that his place shall never be with those cold and timid souls who neither know victory nor defeat.

    The last few months have been full of family life and hard work. The last few days were marked by grief at the assassination of Charlie Kirk while he was in the arena. I have prioritized meeting with important people in my life to encourage them. This is a time for courage (Job 32, Revelation 21:8) and to silence evil with good works (Proverbs 14:23).

    The question must not be merely, Is there to be peace or war? The question must be, Is it right to prevail? Are the great laws of righteousness once more to be fulfilled? And the answer from a strong and virile people must be ‘Yes,’ whatever the cost.

    See you in the arena.

  • On Stepping Back ↗

    Russell Power provides software engineering examples and advice for the exploration-explotation dilemma:

    How much energy should we invest into getting “just this next bug fixed and working” versus taking a sip of tea and then you should change your approach or change your job?

  • The Full Picture ↗

    Mayor Matt Mahan wants to end homelessness in San Jose neighborhood by neighborhood.

    When it comes to my proposal that we use a brief, targeted interaction with the criminal justice system to compel those who repeatedly refuse private shelter to instead engage with treatment, we’ve been talking a lot lately about the moment of accountability. The moment where things get so bad that we need to take action to help those suffering and the broader community. But we don’t talk a lot about the many moments that come before and the many moments that will come after because of our action at this critical juncture.

    So let’s start from the beginning.

    Matt Mahan is leading the way. Others need to step up. The County of Santa Clara has a responsibility to build out treatment beds. Judges need to make wise judgements. I hope this policy will free people from addiction and suffering. Go read the Mayor’s plan. Let’s make it our reality together.

  • JSX Over The Wire ↗

    Dan Abramov:

    Your components don’t call your API.

    Instead, your API returns your components.

    Why would you ever want to do that?

    Great long read which pairs nicely with today’s React Router RSC Preview.

    RSC is mindbending, I won’t lie. Sometimes you have to think inside-out. But personally, I think RSC is awesome. The tooling is still evolving but I’m excited for its future. I hope to see more technologies thoughtfully blending the boundaries.

  • React Router RSC Preview ↗

    Ryan Florence introduces Jacob Ebey’s latest work to bring RSC to React Router.

    We’re leveraging Parcel’s RSC support to help us figure out what React Router looks like when RSC is a first-class bundler feature. You’ll note in the preview template there’s a little Parcel plugin for routes.ts to button it all up and it’s pretty small. The effort to port to other RSC-native bundlers in the future should be equally minimal.

    By targeting RSC-native bundlers like Parcel, we’re also helping to guide the direction of Vite’s official RSC support. Hiroshi Ogawa is currently working publicly on Vite RSC support and using React Router’s RSC APIs in Vite to validate their approach. By sharing our early RSC work publicly, we can help ensure that we’ll be ready once Vite RSC support finally lands.

    This is very exciting for us: both React’s and React Router’s full feature sets will soon be usable with very little effort with any bundler, any JavaScript runtime, and any server!

    Here’s the example repo and the little Parcel plugin which makes it possible.

    The post introduces the concept of RSC from server loaders:

    export async function loader({ params }) {
      let { contentBlocks, ...product } = await getProduct(params.productId);
      return {
        product,
        content: (
          <div>
            {contentBlocks.map((block) => {
              switch (block.type) {
                case "image":
                  return <ImageBlock {...block} />;
                case "gallery":
                  return <GalleryBlock {...block} />;
                case "video":
                  return <VideoBlock {...block} />;
                case "text":
                  return <TextBlock {...block} />;
                case "markdown":
                  return <MarkdownBlock {...block} />;
                default:
                  throw new Error(`Unknown block type: ${block.type}`);
              }
            })}
          </div>
        ),
      };
    }
    
    export default function Article({ loaderData }) {
      return (
        <ProductLayout product={loaderData.product}>
          {loaderData.content}
        </ProductLayout>
      );
    }

    There’s also a great section on batching and caching:

    A couple major concerns with the RSC architecture are N+1 queries and over-fetching. Both are very easy to do when components can fetch their own data. We saw it happen in many Hydrogen v1 apps and it tanked performance to unacceptable levels.

    If you’re not familiar, the first version of Hydrogen used RSC before abandoning it. Ryan proposes a new generic concept for solving this problem using batch-loader:

    import { batch } from "@ryanflorence/batch-loader";
    
    // Async context to load data from anywhere in the app
    let context = new AsyncLocalStorage<ReturnType<typeof createLoaders>>();
    
    // React Router middleware to provide the context to the app
    export const dataMiddleware: MiddlewareFunction<Response> = async (_, next) => {
      // create batchFunctions for just this request
      let batchFunctions = {
        movie: batch(batchMovies),
        actor: batch(batchActors),
      };
    
      return new Promise((resolve) => {
        context.run(batchFunctions, () => {
          resolve(next());
        });
      });
    };
    
    // load function to be used anywhere, especially in components
    export function load() {
      return context.getStore() as ReturnType<typeof createLoaders>;
    }

    Ryan is looking to bring this kind of concept into React Router.