2.0.0 • Published 3 years ago

inertia-node v2.0.0

Weekly downloads
57
License
MIT
Repository
github
Last release
3 years ago

inertia-node V2

inertia-node is a simple Node.js adapter/middleware for Inertia.js that uses standard Node.js APIs. It can be used with any middleware based web framework that exposes the standard Node.js request and response objects such as Express.js or Polka.

Install

To install inertia-node inside your Node.js project simply run:

npm install inertia-node

Note: All code samples use Polka but you can use whatever web framework you like.

Example

const polka = require("polka");
const inertia = require("inertia-node");

const ASSET_VERSION = "1";
const { PORT = 3000 } = process.env;

const html = (pageString, viewData) => `
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />

    <!-- Custom data -->
    <title>${viewData.title}</title>

    <!-- Your React, Vue or Svelte SPA -->
    <link rel="stylesheet" href="/build/bundle.css" />
    <script defer type="module" src="/build/main.js"></script>
  </head>

  <!-- The Inertia page object -->
  <body id="app" data-page='${pageString}'></body>
</html>
`;

polka()
  .use(inertia(html, ASSET_VERSION))
  .get("/", (req, res) => {
    req.Inertia.setViewData({ title: "Inertia Page" }).render({
      component: "Index",
      props: { username: "ironman" },
    });
  })
  .listen(PORT, (err) => {
    if (err) throw err;
    console.log(`> Running on localhost:${PORT}`);
  });

Usage

inertia-node expects two arguments:

  1. html: a function that recieves pageString - a correctly encoded string of the Inertia page object - and an optional viewData object that you can populate with additional data. The function should return an HTML string.
  2. version (optional): your current asset version

It will return a standard Node.js middleware that you can use with Express.js, Polka etc. Functions can be accessed from the Inertia object that will be added to the request. You can chain functions together but you can't call another function after calling render or redirect.

Note: In your HTML view function make sure to always include the page string in the data-page attribute of the HTML node you want to render your JavaScript app in. Version 1 of inertia-node did not stringify and encode the page object for you so that the data could be used in the HTML. But since you are expected to use the viewData object to pass any additional data to your HTML, version 2 now stringifies and correctly encodes the page object for you. For more information on how Inertia works read the protocol on the Inertia website.

API

setViewData(data)

  1. data, Object - An Object of additional data you want to pass to your HTML view function

setViewData can be used to pass additional data to your HTML view function such as the page's title or other meta data.

app.use(({ Inertia }, _, next) => {
  Inertia.setViewData({
    title: "Todo App",
    description:"A Web App to Create and Manage Todos"
  })

  next();
});

// ...

const html = (pageString, viewData) => `
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />

    <meta name="description" content="${viewData.description}">
    <title>${viewData.title}</title>

    <link rel="stylesheet" href="/build/bundle.css" />
    <script defer type="module" src="/build/main.js"></script>
  </head>

  <body id="app" data-page='${pageString}'></body>
</html>
`;

If you call setViewData multiple times during a single request, the data of all calls will be merged to a single object and be available to your HTML template.

shareProps(props)

  1. props, Object - An object of props you want to include with every render call

Shared props are props that will be combined with the props you pass to the render function. When you call shareProps more than once, props shared from previous calls will be merged with props from any subsequent calls.

app.use(({ Inertia }, _, next) => {
  Inertia.shareProps({ username: "ironman" })
  next();
});

app.get("/todos", ({ Inertia }) => {
  Inertia.render({
    component: "Todos",
    props: {
      todos: [
        { text: "Study Korean", done: false },
        { text: "Cook Arabic food", done: false },
      ]
    }
    // JavaScript component on the client will receive
    // {
    //   username: "ironman",
    //   todos: [
    //     { "Study Korean", done: false },
    //     { "Cook Arabic food", done: false },
    //   ]
    // }
  });
});

setHeaders(headers)

  1. headers, Object - An Object of custom headers you want to include in your response

Add custom headers to your response.

Note: Headers that are required by Inertia take precedence and cannot be overwritten.

app.get("/", ({ Inertia }) => {
  Inertia
    .setHeaders({
      token: "7pTgHCv0JgeAyyBRDpUi"
    })
    .render({
      component: "Index",
      props: { username: "ironman" }
    });
});

setStatusCode(statusCode)

  1. statusCode, number - The response's status code

Change the status code when sending a response. Useful for e.g. when you want to render an error. Headers set from previous calls will be merged with headers set from any subsequent calls.

app.get("/", ({ Inertia }) => {
  Inertia.render({
    component: "Index",
    props: { username: "ironman" }
  });
});

app.use(({ Inertia }) => {
  Inertia
    .setStatusCode(404)
    .render({
      component: "Error",
      props: { message: "Page not found" },
    });
});

render(page)

  1. page, Object - the Inertia page object

This function will send your response as either a HTML or JSON string to the client depending on wether the client is requesting your page for the first time or is making a subsequent Inertia request.

The Inertia page object consists of the following properties:

  1. component, string - The name of the JavaScript component to render on the client
  2. props, Object - The page props (data)
  3. url, string - The URL of the route. This will be automatically added by the middleware.
  4. version, string - The asset version. This will be automatically added by the middleware.
app.get("/todos", ({ Inertia }) => {
  Inertia.render({
    component: "Todos",
    props: {
      todos: [
        { text: "Study Korean", done: false },
        { text: "Cook Arabic food", done: false },
      ]
    },
  });
});

On Partial Reloads only props requested by the client will be sent. To improve performance on the server you can wrap each prop inside a function so that they will only be evaluated when necessary.

app.get("/todos", ({ Inertia }) => {
  const todos = async () => await database.getTodos();
  const bookmarks = async () => await database.getBookmarks();

  Inertia.render({
    component: "Todos",
    props: {
      todos,
      bookmarks
    },
  });
});

Now when the client only requests todos the middleware will hit the database only once and not call bookmarks.

redirect(url)

  1. url, string - The URL to redirect to

Redirect the client to a different URL.

app.post("/todos", (req, res) => {
  database.createTodo(req.body);
  req.Inertia.redirect("/todos");
});

Since redirects to the same URL are very common with Inertia, inertia-node provides a shortcut for this.

Calling the following code:

req.Inertia.redirect(req.headers["referer"]);

is equivalent to just:

req.Inertia.redirect();

Note: Inertia requires you to use a 303 status code when redirecting upon a PUT, PATCH or DELETE request and a 302 status code otherwise. The redirect function will automatically take care of this for you. If you handle redirects yourself make sure to select the correct status code.

Note: Calling setStatusCode before redirect has no effect.

2.0.0

3 years ago

1.1.2

4 years ago

1.1.1

4 years ago

1.1.0

4 years ago

1.0.0

4 years ago