npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

next-server-actions-parallel

v1.2.1

Published

Run Next.js server actions in parallel. Like tRPC, but without the boilerplate.

Downloads

906

Readme

Parallel Next.js Server Actions

NPM version License Sponsor the author

Run multiple Next.js server actions in parallel.

The missing ingredient to build tRPC-like workflows, but without the boilerplate.

TL;DR

Install:

pnpm i next-server-actions-parallel

Define your server actions like so:

app/page.actions.ts:

'use server';

import { createParallelAction } from 'next-server-actions-parallel';

export const listUsers = createParallelAction(async () => { // 👈 don't forget the `async` keyword!!
  return prisma.user.findMany(); // 👈 let's assume this takes 3 seconds
});

export const listProducts = createParallelAction(async (categoryId: string) => {
  return prisma.product.findMany({ where: { categoryId } }); // 👈 let's assume this also takes 3 seconds
});

Call them like so:

app/page.tsx:

'use client';

import { runParallelAction } from 'next-server-actions-parallel';
import { listUsers, listProducts } from './page.actions';

export default async function Page() {
  // 👇 this may take slightly more than 3 seconds, but a lot less than 6.
  const [users, products] = await Promise.all([
    runParallelAction(listUsers()),
    runParallelAction(listProducts('82b2ab20-ec1e-4539-85a2-ea6737555250')),
  ]);

  return (
    <div>
      <ul>
        {users.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
      <ul>
        {products.map((product) => (
          <li key={product.id}>{product.name}</li>
        ))}
      </ul>
    </div>
  );
}

How does it perform?

In a nutshell: a lot faster than default Next.js server actions, not as fast as REST API routes.
Check it in your specific deployment environment and decide if it makes sense for your project.

Show gratitude

If you find my open-source work useful, please consider sponsing me on GitHub Sponsors.

Background story

When Vercel added support for server actions in Next.js, a lot of developers - myself included - were hyper-excited about it and saw it as a boilerplate-free alternative to tRPC.io to Telefunc.

Many were however disappointed to find that Next.js server actions were only executed in series, contrary to what one would expect when triggering them in parallel with Promise.all.
It probably worked like that because they were intended to be used for mutations, because "data should be fetched in server components or using REST API endpoints".
Plus, since server actions are implemented with POST requests, some purists are reluctant to the idea of using them for fetching data, though POST requests can and usually do return data.

However, there are many reasons why projects like tRPC.io, Telefunc and other *RPCs were built and have no problem using POST requests to fetch data. If you're building real, data-rich applications, including something like tRPC.io in your stack gives you type-safety and spares you the effort of building and maintainings maybe hundreds of API endpoints just to populate dynamic UI components (such as autocompletes and selects).

tRPC.io is the "batteries-included" choice; I'm a big fan and former contributor to the ecosystem - see tRPC-SvelteKit, but I always found the amount of boilerplate to be a bit discouraging for new developers and/or small projects. Telefunc looks like a nice alternative, but it doesn't (yet, as of November 2024) have an obvious way of integrating with the Next.js app router.

It would be nice to use server actions for RPC without the current limitation of being unable to call multiple functions in parallel.
Here's a non-exhaustive list of issues and discussions where the subject was mentioned:

Well, that's what next-server-actions-parallel is for.

How does it work?

It's actually quite simple:

  • The createParallelAction is wrapping the promise your server action returns in an array (a single-ellement tuple, to be more precise - see note below) and returning that array instead of the result of the promise.
  • The runParallelAction client-side utility function will await the promise and return the result.

This repository contains a light Next.js app that demonstrates it in action and benchmaks it against REST API routes and default server actions, so you can check it out in different environments and decide if it makes sense for your project.

Check it on StackBlitz ⚡️
Deploy with Vercel

Note:
Wrapping the promise in an object would also work, but I've chosen to use an array for data-transfer efficiency.

Do I actually need to use this library?

Not necessarily. The two functions that are exported by the library are small enough to be easily copied and pasted into your own project, see source code here.
But since this is a common pain point for many developers, I've decided to provide a simple and easy-to-use wrapper... And maybe hope that if you find it useful you won't hesitate to show your eternal gratitude by throwing a few greenbacks my way , at least for discovering the trick... 😜

License

The MIT License.