@curi/static

Installation

The package can be installed through npm (you need to have Node & NPM installed).

npm install @curi/static

About

The @curi/static package is for creating static assets for your server. Its exported functions should be used in a build script, not the source of an application.

API

staticFiles()

The staticFiles() function is used to generate HTML files for a static website and save them to the disk. An HTML file will be created for each page that you provide.

Files will be created as index.html in the directory for their path. For example, the page for the pathname /about would create an /about/index.html file.

import { staticFiles } from '@curi/static';
import { join } from "path";

import routes from "../src/routes";

staticFiles({
  routes,
  pages: [{ name: "Home" }, { name: "About" }],
  outputDir: join(process.cwd(), "public"),
  render: () => {...},
  insert: () => {...}
});

staticFiles() returns a Promise that resolve with an array of results. Each entry in the results array contains the pathname of the result, a success boolean, and, if success is false, the error that occurred.

It can be useful to log the results to easily see what pages were successfully built and which had issues.

staticFiles({...})
  .then(results => {
    const resultString = results
      .map(result => {
        return result.success
          ? `✔ ${result.pathname}`
          : `✖ ${result.pathname} (${result.error.message})`;
      })
      .join("\n");
    console.log(resultString);
  });

Arguments

routes

The array of route descriptors that is passed to a router.

routes = prepareRoutes([
  {
    name: "Home",
    path: "",
  },
  {
    name: "User",
    path: "u/:id"
  }
]);


staticFiles({
  // ...
  routes
});
pages

An array of page descriptors. A page descriptor is an object with a name property defining which route to generate a page for. If the route (or any of its ancestors) has any params, they should be passed as an object with the params property.

const pages = [
  { name: "Home" },
  { name: "User", params: { id: 1 }},
  { name: "User", params: { id: 2 }},
];


staticFiles({
  // ...
  pages
});
render()

A function that takes the emitted response, navigation, and router for a location and returns the content that should be inserted into the page's HTML.

render()s behavior will depend on what type of application is being built. For a React application, this would call the renderToString() method from react-dom/server. A Vue application would use vue-server-renderer.

render() can return anything you want it to. This may be a string for simple rendering, or an object with multiple properties for more complex rendering (e.g. title/style properties for the <head> and rendered markup to insert in the <body>).

// for a React application
import { renderToString } from "react-dom";
import { curiProvider } from "@curi/react-dom";

function render(emitted) {
  const { router } = emitted;
  const Router = curiProvider(router);
  return renderToString(
    <Router>
      {({ response }) => {...}}
    </Router>
  )
}

staticFiles({
  // ...
  render
});
insert()

A function that takes the value returned by the render() function and inserts it into the full HTML for a page.

function insert(markup) {
  return `<!doctype html>
<html>
  <head>
    <title>${markup.title}</title>
  </head>
  <body>
    <div id="root">${markup.html}</div>
    <script src="/static/js/bundle.js"></script>
  </body>
</html>`;
}

// where the markup comes from the render() function:
function render() {
  return { title: "Yo!", html: "<div>Hey!</div>" };
}

staticFiles({
  // ...
  insert
});
outputDir

The folder where the generated HTML files should be saved.

outputRedirects

If a route automatically redirects, you probably do not need to create an HTML file for it. If you set outputRedirects to true, HTML files will be generated for redirect pages.

Your server should be configured to return a fallback page when there is no content for a route, so you should not need to create HTML files for redirected pages.

Note: If you do create HTML files for redirects, be sure that your application knows how to render redirect responses. If you are using emitRedirects = false in your client side code, your application probably doesn't know how to render redirects.
getRouterOptions()

The getRouterOptions() function returns the options for a router.

When you call staticFiles(), a number of routers will be created behind the scenes. staticFiles() creates its own history instances, and gets its routes from the routes options, but the router may also need to be provided with other options, like route interactions.

Note: This is a function so that each router has its own instances of route interactions in order to avoid any possible issues with routers resetting other router's interactions.
import active from "@curi/active";
const getRouterOptions = () => ({
  routes: [active()]
});

staticFiles({
  // ...
  getRouterOptions
});

pathnames()

The pathnames() function is used to generate pathnames from an array of provided page descriptors. This can be useful for generating a sitemap.

Arguments

routes

The array of route descriptors that is passed to a router.

routes = prepareRoutes([
  {
    name: "Home",
    path: "",
  },
  {
    name: "User",
    path: "u/:id"
  }
]);


const paths = pathnames({
  // ...
  routes
});
pages

An array of page descriptors. A page descriptor is an object with a name property defining which route to generate a page for. If the route (or any of its ancestors) has any params, they should be passed as an object with the params property.

const pages = [
  { name: "Home" },
  { name: "User", params: { id: 1 }},
  { name: "User", params: { id: 2 }},
];


const paths = pathnames({
  // ...
  pages
});
routerOptions

The options for a router, predominantly useful for passing any route interactions the application may need while rendering.

import active from "@curi/active";
const routerOptions = {
  routes: [active()]
};

const paths = pathnames({
  // ...
  routerOptions
});