logo
  • Guide
  • Config
  • Plugin
  • API
  • Examples
  • Community
  • Modern.js 2.x Docs
  • English
    • 简体中文
    • English
    • Start
      Introduction
      Quick Start
      Upgrading
      Glossary
      Tech Stack
      Core Concept
      Page Entry
      Build Engine
      Web Server
      Basic Features
      Routes
      Routing
      Config Routes
      Data Solution
      Data Fetching
      Data Writing
      Data Caching
      Rendering
      Server-Side Rendering
      Streaming SSR
      Rendering Cache
      Static Site Generation
      Render Preprocessing
      Styling
      Styling
      Use CSS Modules
      Using CSS-in-JS
      Using Tailwind CSS
      HTML Template
      Import Static Assets
      Import JSON Files
      Import SVG Assets
      Import Wasm Assets
      Debug
      Data Mocking
      Network Proxy
      Using Rsdoctor
      Using Storybook
      Testing
      Playwright
      Vitest
      Jest
      Cypress
      Path Alias
      Environment Variables
      Output Files
      Deploy Application
      Advanced Features
      Using Rspack
      Using BFF
      Basic Usage
      Runtime Framework
      Extend BFF Server
      Extend Request SDK
      File Upload
      Cross-Project Invocation
      Optimize Page Performance
      Code Splitting
      Inline Static Assets
      Bundle Size Optimization
      React Compiler
      Improve Build Performance
      Browser Compatibility
      Low-Level Tools
      Source Code Build Mode
      Server Monitor
      Monitors
      Logs Events
      Metrics Events
      Internationalization
      Basic Concepts
      Quick Start
      Configuration
      Locale Detection
      Resource Loading
      Routing Integration
      API Reference
      Advanced Usage
      Best Practices
      Custom Web Server
      Topic Detail
      Module Federation
      Introduction
      Getting Started
      Application-Level Modules
      Server-Side Rendering
      Deployment
      Integrating Internationalization
      FAQ
      Dependencies FAQ
      CLI FAQ
      Build FAQ
      HMR FAQ
      Deprecated
      📝 Edit this page
      Previous pageRendering CacheNext pageRender Preprocessing

      #Static Site Generation

      SSG (Static Site Generation) is a technical solution that generates complete static web pages at build time based on data and templates. This means that in a production environment, pages are pre-rendered with content and can be cached by a CDN. SSG can offer better performance and higher security for pages that do not require dynamic data.

      #Enabling SSG

      First, we need to enable the SSG feature by running pnpm run new:

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

      After running the command, register the SSG plugin in modern.config.ts:

      modern.config.ts
      import { ssgPlugin } from '@modern-js/plugin-ssg';
      
      export default defineConfig({
        output: {
          ssg: true,
        },
        plugins: [..., ssgPlugin()],
      });

      ::::info Scope

      • Use output.ssg for single-entry apps.
      • Use output.ssgByEntries for multi-entry apps.
      • If output.ssg is true and output.ssgByEntries is not set, all routes under all entries are treated as SSG routes. ::::

      #Development Debugging

      Since SSG also renders pages in a Node.js environment, we can enable SSR during the development phase to expose code issues early and validate the SSG rendering effect:

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

      #Using SSG in Conventional Routing

      In conventional routing, Modern.js generates routes based on the file structure under the entry point, allowing the framework to collect complete route information.

      #Basic Usage

      For example, the following is a project directory structure using conventional routing:

      .
      └── 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
      Tip

      If you are not familiar with the rules of conventional routing, refer to the Routing Solution first.

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

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

      Run the command pnpm run dev at the project root and check the dist/ directory, where only one HTML file main/index.html is generated.

      Run the command pnpm run build at the project root, and after the build completes, check the dist/ directory again. This time, you'll find main/index.html, main/user/index.html, and main/user/profile/index.html files, each corresponding to the routes listed above.

      Each route in conventional routing will generate a separate HTML file. Checking main/index.html, you will find it contains the text Index Page, which demonstrates the effect of SSG.

      After running pnpm run serve to start the project, inspect the returned document in the Network tab of the browser's development tools. The document includes the fully rendered content from the component.

      #Preventing Default Behavior

      By default, all routes in conventional routing have SSG enabled. Modern.js provides another field to prevent the default SSG behavior.

      For example, in the following directory structure, routes /, /user, and /user/profile all have SSG enabled:

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

      You can disable the default behavior of certain routes by configuring preventDefault. After configuring as shown below, only the SSG pages for / and /user/profile will be generated:

      export default defineConfig({
        output: {
          ssg: {
            preventDefault: ['/user'],
          },
        },
      });

      #Using SSG in Manual Routing

      Manual routing defines routes through component code, requiring the application to run to obtain accurate route information. Therefore, you cannot use the SSG feature out of the box. Developers need to configure which routes require SSG.

      For example, consider the following code with multiple routes. By setting output.ssg to true, it will only render the entry route (/) by default.

      src/App.tsx
      import { BrowserRouter, Route, Routes } from '@modern-js/runtime/router';
      import { StaticRouter } from '@modern-js/runtime/router/server';
      import { use } from 'react';
      import { RuntimeContext } from '@modern-js/runtime';
      
      const Router = typeof window === 'undefined' ? StaticRouter : BrowserRouter;
      
      export default () => {
        const context = use(RuntimeContext);
        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>
        );
      };

      If you want to enable SSG for /about as well, you can configure output.ssg:

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

      After running pnpm run build, you will see a new main/about/index.html file in the dist/ directory.

      After running pnpm run serve to start the project, inspect the returned document in the Network tab of the browser's development tools. The document includes the fully rendered content from the component.

      Info

      The above example introduces single-entry scenarios. For more information, refer to the API Documentation.

      #Adding Dynamic Routes

      In manual routing or conventional routing with dynamic segments (e.g., /user/[id]), provide concrete paths directly in routes.

      export default defineConfig({
        output: {
          ssg: {
            routes: [
              '/',
              '/about',
              '/user/modernjs',
            ],
          },
        },
      });

      #Multi-entry

      For multi-entry apps, configure per entry via output.ssgByEntries:

      export default defineConfig({
        output: {
          ssgByEntries: {
            home: {
              routes: ['/', '/about', '/user/modernjs'],
            },
            admin: false,
          },
        },
      });
      Info

      See API details: output.ssgByEntries

      #Configuring Request Headers for Rendering

      Modern.js supports configuring request headers for specific entries or routes. For example:

      export default defineConfig({
        output: {
          ssg: {
            headers: {
              "x-tt-env": "ppe_modernjs"
            },
            routes: [
              '/',
              {
                url: '/about',
                headers: {
                  "from": "modern-website"
                },
              },
            ],
          },
        },
      });

      In the above configuration, the x-tt-env request header is set for all routes, and the from request header is specifically set for the /about route.

      Tip

      Headers set in routes will override headers set for entries.