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

server-actions-for-next-pages

v1.0.0

Published

Use Next.js server actions in your pages directory

Downloads

199

Readme

This Next.js plugin let you use something like Next.js Server Actions with the /pages directory, letting you call server functions directly from your client components.

WIth Server Actions i mean calling your functions that run in the server directly in your client components, it does not closely follow the Next.js Server Actions behavior.

Differences with Next.js Server Actions

  • Actions can be imported inside pages and app files

  • Actions must be defined in

    • a file inside the /pages/api directory with the "poor man's use server" directive on top
    • a route inside the /app directory with the "poor man's use server" directive on top
  • No closure support, actions can be defined for an entire file(adding "poor man's use server" at the top of the file)

  • Actions can run concurrently

  • Actions can throw errors, on the client these errors will be thrown with the same error message

  • Actions inputs and outputs are serialized with superjson, a superset of JSON

  • Actions do not work inside formAction, you call the function inside onSubmit instead

  • To get headers and cookies you cannot import them directly from next/headers, instead you have to use getContext:

    "poor man's use server";
    import { cookies, headers } from 'server-actions-for-next-pages/headers';
    
    export async function action({}) {
      return { headers: headers(), cookies: cookies() };
    }

Installation

npm i server-actions-for-next-pages

Usage

Add the plugin to your next.config.js file:

// next.config.js
const { withServerActions } = require('server-actions-for-next-pages');

/** @type {import('next').NextConfig} */
const nextConfig = withServerActions()({
  reactStrictMode: false,
});

module.exports = nextConfig;

Create a file for your server actions inside the /pages/api directory with "poor man's use server" at the top:

// pages/api/server-actions.js
"poor man's use server";

export async function serverAction() {
  return { hello: 'world' };
}

Import your actions in your client components:

// pages/index.jsx
import { serverAction } from './api/server-actions';

export default function Page() {
  serverAction().then((data) => console.log(data));

  return <div>...</div>;
}

Usage in edge runtime

This plugin assumes the runtime of your app to be Nodejs unless you explicitly set it to edge for your api page, this means that to support the edge runtime you need to export a config object like export const config = { runtime: 'edge' }; in your api page.

// pages/api/server-actions.js
"poor man's use server";

export const runtime = 'edge';

export async function serverAction() {
  return { hello: 'world' };
}

Accessing the request and response objects

This plugin injects the req and res objects in an AsyncLocalStorage context, so you can access them in your server functions:

Edge function example:

"poor man's use server";

import { cookies, headers } from 'server-actions-for-next-pages/headers';

export const runtime = 'edge';

export async function serverAction({}) {
  const host = headers().get('host');
  return { host };
}

Example in Node.js:

"poor man's use server";
import { cookies, headers } from 'server-actions-for-next-pages/headers';

export async function createUser({ name = '' }) {

  const host = headers().get('host');

  return {
    name,
    host,
  };
}

Adding error logging and handling

You can export a function named wrapMethod to easily wrap all your server actions with error logging or other wrappers

"poor man's use server";

export function wrapMethod(fn) {
  return async (...args) => {
    try {
      const res = await fn(...args);
      return res;
    } catch (error) {
      console.error(error);
      throw error;
    }
  };
}

export async function failingFunction({}) {
  throw new Error('This function fails');
}

How it works

The plugin will replace the content of files inside pages/api with "poor man's use server" at the top to make the exported functions callable from the browser.

When processing the file for the server the plugin creates an API handler that follows the JSON RPC spec.

When processing the file for the client the plugin replaces the exported functions with a fetch calls to the API handler.

This plugin uses Babel to process your page content, it will not slow down compilation time noticeably because it only process files inside the pages/api folder.

Credits

This is a fork of the awesome next-rpc with some changes:

  • It supports the Edge runtime
  • Uses superjson to serialize and deserialize arguments and results
  • It sets status code to 502 when the server function throws an error
  • It uses the top level "poor man's use server" instead of the config.rpc option
  • wrapMethod can be defined with an export instead of config.wrapMethod