Kapeel Kokane Coder by day, content creator by night, learner at heart!

Stackblitz WebContainers: Run Next.js inside the browser

5 min read 1556

Stackblitz is a popular online IDE for creating and sharing projects that is used by companies like Google and GitHub. Stackblitz, which is powered by VS Code, provides its users with the capability to spin up and share fullstack applications that use frameworks and libraries like React, Vue, and Angular. Because Stackblitz projects are online immediately, you can share your project with just a single click!

Recently, Stackblitz introduced WebContainers, which allow users to run entire Node.js processes inside of the browser, offering benefits for security, speed, and performance.
As a result, users can also run Next.js projects in the browser!

In this article, we’ll explore this functionality in depth. Let’s get started!

Node.js primitives

Before we can understand how Stackblitz works, we have to understand the functionality behind Node.js. Node.js, a JavaScript runtime, is built on top of the Chrome V8 engine, which converts JavaScript code written by developers into something that a computer can understand.

Node.js made it possible for developers to run their JavaScript code in native environments like the operating system without the need for a browser. I/O primitives, which are part of the standard library, allow Node.js to perform operations like accessing a database, making a network request, and reading from the file system.

Node.js offers both blocking and non-blocking implementations of I/O primitives. However, we prefer non-blocking primitives, which are executed on a single thread. Node.js depends on its own unique event-based system that prevents concurrency issues that arise due to multi-threading when running operations in parallel.

Nodejs Primitives Operating System Diagram

Node.js in the browser

You can install Node.js on macOS, Windows, and Linux machines. Although currently still in beta, thanks to WASM and the capabilities API, it’s also possible to run Node.js in the browser!

In Stackblitz WebContainers, the WASM layer successfully abstracts the OS layer away, causing the Node.js process running inside of the browser tab to actually function as if it were running inside of a full-fledged operating system!

Nodejs Primitives Webassembly Diagram

We made a custom demo for .
No really. Click here to check it out.

Setting up a Node.js WebContainer

Now, let’s try it out! Let’s head over to Stackblitz and try running some of our own code. To start a new project, visit the homepage and click on Node.js. Within seconds, a new project will be created for us, which includes the file system for our project on the left, a code editor for making changes in the center, and a terminal at the bottom.

To add our code, run the code snippet below in the terminal:

node index.js

The version of Node.js we’re currently using will be printed to the console via the code.

Let’s write some code that works with our file system. Create a file called tmp.txt in the same project and add the following text:

Hello World

Next, we’ll add the following code snippet, which reads the file and truncates it to just five characters:

const { open } = require('fs/promises');
async function readAndTruncate() {
  let filehandle = null;
  try {
    filehandle = await open('tmp.txt', 'r+');
    await filehandle.truncate(5);
  } finally {
    await filehandle?.close();
  }
}
readAndTruncate();

Upon running this code and checking tmp.txt, we see that our initial input has been modified to read Hello, meaning our Node.js primitive for reading from and writing to a file has worked!

Next.js in the browser

Now that we’ve run the Node.js WebContainer successfully, let’s set up a Next.js project. First, let’s understand the functionality behind Next.js and Stackblitz. Keep in mind that Next.js is a React-based framework that offers static rendering, server-side rendering, and image optimization out of the box.

Let’s briefly consider the differences between accessing a React application and accessing a Next.js application.

Accessing a React application

To access a React application, we enter the application URL in the browser. The browser will fetch the HTML, CSS, and JavaScript bundles. The JavaScript is then compiled on the browser while the React code is converted to the corresponding HTML and CSS, generating the page. The page is then inserted into a div inside of the fetched HTML, pulling up the UI.

Accessing a Next.js application

To access a Next.js application, we enter the URL in the browser. At build time, there are several pages marked as static. If the requested page is static, it is served as is. If the page is not static, the browser checks if it is a server-side rendered page. If so, the necessary API calls are performed, and the final generated HTML and CSS are sent to the browser to display directly.

If the page is neither static nor server-side rendered, you can access it in a way that is very similar to a React application! However, the final HTML and CSS will be delivered directly to the browser instead of being created when you unpack the JavaScript bundle.

Rendering your page directly in the browser improves overall page load time and increases compatibility with SEO crawler bots, causing an overall performance boost! With Stackblitz web containers, you can gain these benefits without having to leave the browser.

Creating our Next.js project in Stackblitz

Nextjs Stackblitz Browser Cycle

You might have noticed that the server plays a larger role in the lifecycle of a Next.js app than the lifecycle of a normal React application.

The Next.js server is based on Node.js, so, historically, the Next.js server could run on any system that could support running Node.js. Now, Node.js can run completely inside of the browser with WebContainers, meaning we can also run a Next.js app in the browser!

To start a new Next.js project, go to the Stackblitz home screen and click on Next.js. Alternately, you can open any browser, type Next.new in the address bar, and press enter. A new Next.js project will be set up for us!

We can also create a new project based on the examples in the Next.js GitHub! We just need to append the project name in front of Next.new. For example, if I wanted to start a new project with the blog-starter example, I could run the following code in the browser:

next.new/blog-starter

Integrating an API

Following the steps above generates a project that has two files, index.js and about.js. These files cater to two routes that the Next.js starter template provides for you, / and /about. Let’s integrate an API into our project and modify the UI rendered at the / route.

For this demo, we’ll use the NASA Events API, which returns a summary of all of the climate events currently occurring on earth. We’ll use components from the React Bootstrap library to design our UI. Install the library by running the following command in the terminal:

npm install --save [email protected] bootstrap

We are installing these dependencies inside the Node.js environment created inside the browser. Next, let’s import Bootstrap CSS inside the index.js file:

import 'bootstrap/dist/css/bootstrap.css';

Server-side rendering

To retrieve the data for our project, we’ll use the getServerSideProps function in Next.js. We’ll make the call on the server side, then use the result inside IndexPage, our React component. Doing so instructs Next.js to make the call on the server side whenever any request is made from the browser for this particular component:

export async function getServerSideProps(context) {
  const res = await fetch('https://eonet.sci.gsfc.nasa.gov/api/v2.1/events');
  const events = await res.json();
  return {
    props: { nasaEvents: events } // will be passed to the page component as props
  };
}

UI rendering

Next, we’ll return the events that were fetched inside of a props key, which Next.js will pass to the React component as props. Then, we’ll use the Bootstrap components to display the events as a list:

export default function IndexPage({ nasaEvents }) {
  return (
    <div style={{ padding: 10 }}>
      <h2>Nasa Events</h2>
      <div>
        {nasaEvents.events.map(event => (
          <Item event={event} />
        ))}
      </div>
    </div>
  );
}

Next, we’ll abstract the UI that needs to be rendered for each event into another UI component that we name Item:

Helper component
function Item({ event }) {
  return (
    <Card style={{ width: '90%', marginBottom: 10 }}>
      <Card.Body>
        <Card.Title>{event?.categories[0]?.title}</Card.Title>
        <Card.Text>{event.title}</Card.Text>
        <a href={event?.sources[0]?.url}>
          <Button>visit</Button>
        </a>
      </Card.Body>
    </Card>
  );
}

Now, our code is complete! Upon refresh, we’ll see that we are able to get a list of climate events taking place around the globe:

Final Next Stackblitz Project

Conclusion

In this tutorial, we learned how to run a Next.js project entirely in the browser using Stackblitz WebContainers. We set up a Node.js container, then accessed a Next.js project through it, integrating an API with server-side and UI rendering.

Our project includes a project URL, which helps collaboration on the development, and a deployment URL, which lets the user preview the end result. To share this project, I can simply share the project URL. I hope you enjoyed this tutorial!

LogRocket: Full visibility into production Next.js apps

Debugging Next applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your Next app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your Next.js apps — .

Kapeel Kokane Coder by day, content creator by night, learner at heart!

Testing accessibility with Storybook

One big challenge when building a component library is prioritizing accessibility. Accessibility is usually seen as one of those “nice-to-have” features, and unfortunately, we’re...
Laura Carballo
4 min read

Leave a Reply