You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将多页面Web应用(MPA)连接至GraphQL?后端渲染方案问询

Connecting an MPA CMS to Your Express/GraphQL Backend (Server-Side Data Fetching & Page Rendering)

Hey there! Let's break down how to hook up your new MPA CMS to your existing Express + GraphQL backend, including how to fetch data server-side and render pages for end users. Here's a step-by-step approach based on practical experience:

1. Fetching GraphQL Data from Your Express Backend

First, you need a way for your Express server to query your GraphQL endpoint. You have two solid options here:

Option A: Use Apollo Client (Node.js Version)

Apollo Client isn't just for frontend—it works great on Node.js too, and gives you built-in features like caching (optimized for SSR) and structured error handling.

  • Install dependencies:

    npm install @apollo/client graphql
    
  • Initialize Apollo Client in Express:
    Create a reusable client instance (you can put this in a separate file like apollo-client.js):

    const { ApolloClient, InMemoryCache, createHttpLink } = require('@apollo/client');
    const { setContext } = require('@apollo/client/link/context');
    
    // Point to your existing GraphQL endpoint
    const httpLink = createHttpLink({
      uri: 'http://localhost:4000/graphql', // Update this to your actual GraphQL URL
    });
    
    // Optional: Add auth if your GraphQL endpoint requires it (e.g., JWT from cookies)
    const authLink = setContext((_, { headers }) => {
      // Grab auth token from incoming request cookies (adjust based on your auth setup)
      const token = req.cookies?.authToken;
      return {
        headers: {
          ...headers,
          authorization: token ? `Bearer ${token}` : '',
        },
      };
    });
    
    // Initialize client with SSR mode enabled (avoids client-side caching conflicts)
    const client = new ApolloClient({
      link: authLink.concat(httpLink),
      cache: new InMemoryCache(),
      ssrMode: true,
    });
    
    module.exports = client;
    
  • Use the client in your Express routes:

    const client = require('./apollo-client');
    const { gql } = require('@apollo/client');
    
    app.get('/article/:id', async (req, res) => {
      try {
        // Query your GraphQL API for the article data
        const { data } = await client.query({
          query: gql`
            query GetArticle($id: ID!) {
              article(id: $id) {
                title
                content
                author {
                  name
                }
                publishDate
              }
            }
          `,
          variables: { id: req.params.id },
        });
    
        // If no article found, send 404
        if (!data.article) {
          return res.status(404).render('404');
        }
    
        // Pass data to your template renderer (we'll cover this next)
        res.render('article', { article: data.article });
      } catch (err) {
        console.error('GraphQL fetch error:', err);
        res.status(500).render('500');
      }
    });
    

Option B: Raw Fetch API (No Extra Dependencies)

If you prefer to keep things lightweight, you can directly send POST requests to your GraphQL endpoint using Node's native fetch (or node-fetch if you're on an older Node version):

app.get('/article/:id', async (req, res) => {
  try {
    const response = await fetch('http://localhost:4000/graphql', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        // Add auth headers here if needed (e.g., from cookies)
        ...(req.cookies.authToken && { authorization: `Bearer ${req.cookies.authToken}` }),
      },
      body: JSON.stringify({
        query: `
          query GetArticle($id: ID!) {
            article(id: $id) {
              title
              content
              author { name }
              publishDate
            }
          }
        `,
        variables: { id: req.params.id },
      }),
    });

    const result = await response.json();

    if (result.errors) {
      throw new Error(result.errors[0].message);
    }

    if (!result.data.article) {
      return res.status(404).render('404');
    }

    res.render('article', { article: result.data.article });
  } catch (err) {
    console.error('Fetch error:', err);
    res.status(500).render('500');
  }
});

2. Rendering MPA Pages with a Template Engine

For your MPA, use a server-side template engine to generate HTML from fetched data. We'll use EJS as an example (Pug or Handlebars work similarly):

  • Install EJS:

    npm install ejs
    
  • Configure Express to use EJS:

    // Set EJS as the view engine
    app.set('view engine', 'ejs');
    // Define where your template files live (create this folder if it doesn't exist)
    app.set('views', './views');
    
  • Create a template file (e.g., views/article.ejs):

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title><%= article.title %></title>
      <link rel="stylesheet" href="/css/styles.css">
    </head>
    <body>
      <header>
        <h1>My CMS</h1>
      </header>
      <main>
        <article>
          <h2><%= article.title %></h2>
          <p class="meta">By <%= article.author.name %> | <%= article.publishDate %></p>
          <div class="content"><%- article.content %></div>
        </article>
      </main>
      <footer>
        <p>&copy; 2024 My CMS</p>
      </footer>
    </body>
    </html>
    
  • Add static file serving (for CSS, JS, images):

    app.use(express.static('public'));
    

    Put your static assets (like css/styles.css) in a public folder at your project root.

3. Key Optimizations & Considerations

  • Error Handling: Always catch GraphQL query errors and render user-friendly error pages (404 for missing content, 500 for server issues).
  • Caching: For frequently accessed content, add server-side caching (e.g., with Redis) to reduce repeated GraphQL queries and boost performance.
  • Auth & Permissions: If some content is restricted, ensure your Express server passes the correct auth tokens to the GraphQL endpoint (as shown in the Apollo Client example with cookies).
  • Static Site Generation (SSG): If your content doesn't change often, pre-render pages at build time using tools like Next.js (with SSG features) — this is optional if you need dynamic server-side rendering.

内容的提问来源于stack exchange,提问作者Kucl Stha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:20:22