URL 結構

URL 結構是 SEO 策略的重要組成部分。雖然 Google 並未公開 SEO 各部分的權重比例,但無論最終影響排名因素的大小,良好的 URL 結構都被視為最佳實踐。

您可以遵循以下原則:

  • 語意化:最好使用具有語意的 URL,即使用單詞而非 ID 或隨機數字。例如: /learn/basics/create-nextjs-app 就比 /learn/course-1/lesson-1 更好
  • 邏輯一致的模式:URL 應遵循某種在頁面間一致的結構模式。例如,您會希望將所有產品頁面歸類到同一個資料夾,而不是為每個產品設置不同的路徑
  • 關鍵字導向:Google 的系統仍相當程度基於網站包含的關鍵字。您可以在 URL 中使用關鍵字,幫助理解頁面目的
  • 避免參數化:使用參數構建 URL 通常不是好主意。大多數情況下它們不具語意,搜尋引擎可能會混淆並降低其在結果中的排名

Next.js 如何定義路由?

Next.js 採用基於 頁面 (pages) 概念的 檔案系統路由 (file-system routing)。當檔案被添加到 pages 目錄時,它會自動成為可用路由。pages 目錄中的檔案和資料夾可用於定義大多數常見模式。

以下是一些簡單 URL 及其對應的 Next.js 路由設定方式:

  • 首頁https://www.example.compages/index.js
  • 列表頁https://www.example.com/productspages/products.jspages/products/index.js
  • 詳細頁https://www.example.com/products/productpages/products/product.js

對於部落格或電子商務網站,您可能會希望使用產品 ID 或文章名稱作為 URL 的 slug。這稱為 動態路由 (dynamic routing)

  • 產品頁https://www.example.com/products/nextjs-shirtpages/products/[product].js
  • 部落格文章https://www.example.com/blog/seo-in-nextjspages/blog/[blog-name].js

要使用動態路由,您可以在 productsblogs 子資料夾中的頁面名稱添加方括號。

以下是一個使用 SSG (靜態生成) 優化的頁面範例:

// pages/blog/[slug].js
 
import Head from 'next/head';
 
export async function getStaticPaths() {
  // 呼叫外部 API 端點取得文章
  const res = await fetch('https://www.example.com/api/posts');
  const posts = await res.json();
 
  // 根據文章獲取需要預渲染的路徑
  const paths = posts.map((post) => ({
    params: { slug: post.slug },
  }));
  // 設置 fallback 為 blocking。現在任何建置後新增的文章都會進行 SSR
  // 以確保 SEO。之後的請求都會是靜態的
  return { paths, fallback: 'blocking' };
}
 
export async function getStaticProps({ params }) {
  const res = await fetch(`https://www.example.com/api/blog/${params.slug}`);
  const data = await res.json();
 
  return {
    props: {
      blog: data,
    },
  };
}
 
function BlogPost({ blog }) {
  return (
    <>
      <Head>
        <title>{blog.title} | My Site</title>
      </Head>
      <div>
        <h1>{blog.title}</h1>
        <p>{blog.text}</p>
      </div>
    </>
  );
}
 
export default BlogPost;

以下是使用 SSR (伺服器端渲染) 的另一個範例:

// pages/blog/[slug].js
 
import Head from 'next/head';
function BlogPost({ blog }) {
  return (
    <div>
      <Head>
        <title>{blog.title} | My Site</title>
      </Head>
      <div>
        <h1>{blog.title}</h1>
        <p>{blog.text}</p>
      </div>
    </div>
  );
}
 
export async function getServerSideProps({ query }) {
  const res = await fetch(`https://www.example.com/api/blog/${query.slug}`);
  const data = await res.json();
 
  return {
    props: {
      blog: data,
    },
  };
}
 
export default BlogPost;

延伸閱讀

On this page