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

Gatsby中如何通过gatsby-node.js删除index.js并动态生成首页

问题根因

你当前代码存在两个核心错误导致运行报错:

  1. 重复创建同一路径页面:当node.slug === '/'时,你在判断分支内已经调用了一次createPage创建首页,分支外的全局createPage逻辑会再次为同一个/路径创建页面,触发路由冲突。
  2. deletePage参数不符合Gatsby API要求:deletePage不需要传入component参数,仅需传入path即可,如果你传入的path.resolve('src/pages/index.js')路径和Gatsby内部生成的首页组件路径不一致,会导致删除失败。

修复方案

  • 推荐直接在onCreatePage钩子中拦截默认的src/pages/index.js页面生成,避免后续删除操作
  • 删除重复的首页创建逻辑
  • 简化deletePage调用参数

修正后的完整代码如下:

const path = require('path')
// 原有常量定义 STATIC_DEFINED_PAGES、LAYOUT_LOOKUP 保持不变即可

const fetchAllComposePages = async ({ graphql, locales }) =>
  /* eslint implicit-arrow-linebreak: ["error", "below"] */
  graphql(`
    {
      allContentfulComposePage(filter: { node_locale: { in: ${locales} } }) {
        nodes {
          contentful_id
          title
          node_locale
          slug
          seo {
            no_follow
            no_index
            description
            name
            keywords
            title
          }
          content {
            __typename
          }
        }
      }
    }
  `);

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions;

  let locales = '';

  if (process.env.GATSBY_LOCALE === 'qc') {
    locales = '["en", "fr"]';
  } else {
    locales = '["en-CA", "fr-CA"]';
  }

  const result = await fetchAllComposePages({ graphql, locales });

  result.data.allContentfulComposePage.nodes.map((node) => {
    const { contentful_id: id, slug, seo } = node;
    const content = node.content || [{}];
    const { __typename: template } = content;

    if (STATIC_DEFINED_PAGES.includes(slug)) {
      console.info(`Skipping Page :: ID: ${id} - Slug: ${slug}`);
      return;
    }

    if (!template) {
      console.info(`No Layout Found :: ID: ${id} - Slug: ${slug}`);
      return;
    }

    let layout = '';
    if (LAYOUT_LOOKUP[template]) {
      layout = LAYOUT_LOOKUP[template];
    } else {
      console.info(`No Layout Found :: ID: ${id} - Slug: ${slug}`);
      layout = 'base/BaseTemplate.js';
    }

    if (!seo) {
      console.info(`No SEO Found for: ${slug}`);
    }

    // 全局仅保留一次createPage调用,避免重复创建
    createPage({
      path: node.slug,
      component: path.resolve(`src/layouts/${layout}`),
      context: {
        pathSlug: slug,
        pageId: id,
        seo: {
          name: seo?.name ?? '',
          description: seo?.description ?? '',
          keywords: seo?.keywords ?? '',
          title: seo?.title ?? '',
          no_follow: seo?.no_follow ?? false,
          no_index: seo?.no_index ?? false,
        },
      },
    });
  });
};

// 拦截默认的index.js页面生成,从源头避免路由冲突
exports.onCreatePage = ({ page, actions }) => {
  const { deletePage } = actions
  // 匹配默认生成的首页直接删除
  if (page.path === '/' && page.component.includes('src/pages/index.js')) {
    deletePage(page)
  }

  // 原有国际化逻辑保持不变,增加intl判空避免异常
  const lang = page.context.intl?.language
  if (lang) {
    const locale = `${lang}-CA`;
    page.context.locale = locale;
  }
  return page;
};

额外优化点

  • 用可选链?.和空值合并运算符??简化了SEO字段的判空逻辑,代码更简洁
  • 在onCreatePage中提前拦截默认首页,即使createPages逻辑执行异常也不会出现默认首页和自定义首页冲突的问题
  • 去掉了重复的createPage调用,彻底避免路由重复报错

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 10:06:03