Static Site Generation

SSG (Static Site Generation) is a solution based on data and templates that renders complete static web pages during the build process.

First need to execute pnpm run new to enable the SSG feature:

? Please select the operation you want: Enable features
? Please select the feature name: Enable SSG

Register the SSG plugin in modern.config.ts after executing the command:

modern.config.ts
import { ssgPlugin } from '@modern-js/plugin-ssg';

export default defineConfig({
  output: {
    ssg: true,
  },
  plugins: [..., ssgPlugin()],
});

The usage of SSG differs between the Conventional Routing and Self-controlled Routing.

Using with Conventional Routing

In the Conventional Routing of Modern.js, the framework generates routes based on the file structure under the entry point, so it can collect complete routing information.

For example, here is a project directory structure that uses conventional routing:

.
├── src
│   └── routes
│       ├── layout.tsx
│       ├── page.tsx
│       └── user
│           ├── layout.tsx
│           ├── page.tsx
│           └── profile
│               └── page.tsx

The above file directory will generate the following three routes:

  • /
  • /user
  • /user/profile
NOTE

If you are not familiar with the rules of Conventional Routing, you can first check Routing.

Add component code in src/routes/page.tsx:

src/routes/page.tsx
export default () => {
  return <div>Index Page</div>;
};

SSG also renders pages in a Node.js environment, so we can enable SSR during development to expose code issues and validate SSG rendering effects in advance:

modern.config.ts
export default defineConfig({
  server: {
    ssr: process.env.NODE_ENV === 'development',
  }
}

Execute the pnpm run dev command in the project to view the dist/ directory, and only generate an HTML file main/index.html.

Execute the pnpm run build command in the root path of the project. After the construction is completed, view the dist/ directory, and generate main/index.html, main/user/index.html and main/user/profile/index.html three HTML files, the content corresponds to the above three routes.

Each route in the Conventional Routing will generate a separate HTML file. By viewing main/index.html, you can find the text content that includes the Index Page, which is exactly the effect of SSG.

After executing pnpm run serve to start the project, visit the page in the Network, view the document returned by the request. The document contains the complete page content rendered by the component.

Using with Self-controlled Routing

Self-controlled routing is a routing through component code, which requires the application to run to obtain accurate routing information. Therefore, the SSG function cannot be used out of the box. At this time, users needs to inform the Modern.js framework in advance which routes need to enable SSG.

For example, there is the following code which contains multiple routes. When setting output.ssg to true, only the entry route '/' will be rendered by default:

src/App.tsx
import { BrowserRouter, Route, Routes } from '@modern-js/runtime/router';
import { StaticRouter } from '@modern-js/runtime/router/server';
import React from 'react';
import { useRuntimeContext } from '@modern-js/runtime';

const Router = typeof window === 'undefined' ? StaticRouter : BrowserRouter;

export default () => {
  const { context } = useRuntimeContext();
  const pathname = context?.request?.pathname;
  return (
    <Router location={pathname}>
      <Routes>
        <Route index element={<div>index</div>} />
        <Route path="about" element={<div>about</div>} />
      </Routes>
    </Router>
  );
};

We can configure output.ssg to inform Modern.js to enable SSG for specific routes, such as /about:

modern.config.ts
export default defineConfig({
  output: {
    ssg: {
      routes: ['/', '/about'],
    },
  },
});

After executing pnpm run build and pnpm run serve, you can access http://localhost:8080/about to see the rendered page in preview.

You can check the bundle file that a new main/about/index.html file has been added to the dist/ directory.

INFO

Above only introduces the case of single entry, for more related content please refer to the SSG API.