Skip to content

Latest commit

 

History

History
155 lines (103 loc) · 5.94 KB

File metadata and controls

155 lines (103 loc) · 5.94 KB

import { Callout } from 'nextra/components';

Next.js

This guide covers how to integrate React Cosmos with Next.js 13.4+. It includes support for React Server Components. The Cosmos Renderer switches seamlessly between Server and Client components in the same project.

Also check out react-cosmos/nextjs-example, which features both Server and Client fixtures of the glorious react-tweet component.

Getting Started

Create a new Next.js project or open an existing one.

Install the required packages:

npm i -D react-cosmos react-cosmos-next

Create cosmos.config.json and point rendererUrl to your renderer (we'll get to it in a moment):

{
  "rendererUrl": {
    "dev": "http://localhost:3000/cosmos/<fixture>",
    "export": "/cosmos/<fixture>.html"
  }
}

Add cosmos and cosmos-export scripts to package.json:

"scripts": {
  "cosmos": "cosmos --expose-imports",
  "cosmos-export": "cosmos-export --expose-imports"
}

Create a basic fixture at src/Hello.fixture.jsx:

export default <h1>Hello World!</h1>;
If you're using TypeScript replace `.jsx` file extensions with `.tsx`.

Create a Next.js page at src/app/cosmos/[fixture]/page.tsx:

import { nextCosmosPage, nextCosmosStaticParams } from 'react-cosmos-next';
import * as cosmosImports from '../../../../cosmos.imports';

export const generateStaticParams = nextCosmosStaticParams(cosmosImports);

export default nextCosmosPage(cosmosImports);

This is your Cosmos Renderer.

By default, `nextCosmosPage` does not access `searchParams` to keep routes eligible for static rendering. If your fixtures need search params, opt in with `readSearchParams`:
export default nextCosmosPage({ ...cosmosImports, readSearchParams: true });

This opts the route into dynamic rendering.

Start Next.js:

npm run dev

Start React Cosmos (in a 2nd terminal):

npm run cosmos
You'll notice `cosmos.imports.js` was generated. This module is a dependency of the Cosmos Renderer. The Cosmos Server updates this file automatically. You can add it to .gitignore.

🚀 Open localhost:5000 in your browser.

That's it. You're now running Server fixtures in React Cosmos!

You can import both Server and Client components in your fixtures, which run on the server by default. You can also add the 'use client' directive to a fixture module (or decorator) if you want use Hooks inside it.

Limitations

  • Only Component Fixtures fixtures can be exported from a fixture module with the 'use client' descriptor. That's because Client fixture modules are passed as is to the Server render tree and their exports are expected to be components by design. While Node Fixtures and Multi-Fixtures cannot be used in Client fixtures, all Cosmos fixture formats are supported in Server fixtures.

Static Export

The cosmos-export command creates a static export of the Cosmos UI shell, which expects a corresponding static Renderer to connect with. Generating the complete export requires stringing a few simple commands together:

# Build Cosmos
npm run cosmos-export
# Build Next.js
npm run build
# Copy Next.js build into Cosmos export
cp -R ./out/_next ./cosmos-export
cp -R ./out/cosmos ./cosmos-export

At this point your static export is ready to be served:

npx http-server ./cosmos-export

👀 Live demo

Further Integration

Separate React Cosmos from Next.js app

One approach for building Cosmos independently in a Next.js app is to organize the Cosmos component library as a separate project within a dedicated cosmos subfolder. Cosmos files will have access to the main app through the parent folder and it will only import necessary components.

You can take it a step further and deploy your app and Cosmos separately to two different vercel projects from the same codebase.

Check this repo for more information and an example of this setup: https://github.com/scorado-ltd/scorado-examples-nextjs-cosmos/tree/main

On making a plugin (Next.js insider help needed)

Running Server Components in Cosmos is awesome but a plugin could take this integration to the next level (no pun intended).

Similar to the Vite and Webpack plugins, a Next.js plugin would:

  • Remove the need to wire up the Cosmos Renderer (the /cosmos page).
  • Hide the user module mappings (the cosmos.imports file generated with the --expose-imports flag).
  • Set the renderer URL automatically with no Cosmos config needed.
  • Support static exports out of the box with the cosmos-export command.

Making a Cosmos plugin is easy-peasy. Plugging into Next.js is the missing link for a seamless integration.

Ideally we would call the dev and build Next.js commands programatically. But I don't know if Next.js supports this at the moment. There is a Custom Server API but I'm not sure if it works with the App Router architecture and the build part is missing.

In the meantime we can remove the /cosmos page from the out dir when deploying our app. Another option is a monorepo with a main Next.js app and a Cosmos Next.js app.

If you or someone you know has Next.js expertise please don't be shy and reach out. Help is appreciated!