Skip to content

feat(category): change news category page posts data source from GraphQL to JSON#1452

Open
Wendyooo7 wants to merge 7 commits intomirror-media:devfrom
Wendyooo7:change-category-page-data-source-from-gql-to-json
Open

feat(category): change news category page posts data source from GraphQL to JSON#1452
Wendyooo7 wants to merge 7 commits intomirror-media:devfrom
Wendyooo7:change-category-page-data-source-from-gql-to-json

Conversation

@Wendyooo7
Copy link
Contributor

@Wendyooo7 Wendyooo7 commented Mar 13, 2026

@Wendyooo7 Wendyooo7 requested a review from v61265 March 13, 2026 06:29
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取請求重構了新聞分類頁面 (/category/news) 的資料獲取機制,改為使用靜態 JSON 檔案而非 GraphQL。這項變更旨在解決頁面上可能出現重複文章的已知問題,特別是在同時發布多個新聞項目時。透過切換到 JSON 資料來源,系統旨在為新聞分類提供更一致且可靠的內容傳遞。

Highlights

  • 資料來源轉換: 將新聞分類頁面文章的資料來源從 GraphQL 轉換為靜態 JSON 檔案。
  • 問題解決: 此變更旨在解決可能因編輯檯同時發布多則新聞而導致頁面新聞重複的問題。
Changelog
  • packages/mirror-media-next/components/category/category-articles.js
    • 引入了 fetchNewsCategoryPostsJSON 函數。
    • 新增了 isNewsCategory 屬性。
    • 修改了資料獲取邏輯,針對新聞分類頁面條件性地使用 fetchNewsCategoryPostsJSON
    • 調整了新聞分類文章的返回值以提取 items
  • packages/mirror-media-next/config/index.mjs
    • 新增了 URL_STATIC_NEWS_CATEGORY_INFOURL_STATIC_NEWS_CATEGORY_POSTS 配置變數。
    • 為不同環境(生產、預發、開發)初始化了這些新的 URL。
    • 導出了新的 URL 常數。
  • packages/mirror-media-next/pages/category/[slug].js
    • 引入了 fetchNewsCategoryInfofetchNewsCategoryPostsJSON 函數。
    • Category 組件新增了 isNewsCategory 屬性。
    • 修改了 getServerSideProps,如果為新聞分類,則條件性地使用 fetchNewsCategoryInfo 獲取分類資訊。
    • getServerSideProps 中新增了一個條件區塊,當 isNewsCategory 為 true 且 isPremium 為 false 時,使用 fetchNewsCategoryPostsJSON 獲取新聞分類文章。
    • isNewsCategory 屬性傳遞給 CategoryArticles 組件。
  • packages/mirror-media-next/utils/api/category.js
    • 引入了 axiosAPI_TIMEOUTURL_STATIC_NEWS_CATEGORY_INFOURL_STATIC_NEWS_CATEGORY_POSTS
    • 新增了 fetchNewsCategoryInfo 函數,用於從靜態 JSON URL 獲取新聞分類資訊。
    • 新增了 fetchNewsCategoryPostsJSON 函數,用於從靜態 JSON URL 獲取分頁新聞文章,並處理了透過計算正確的 JSON 檔案和切片資料來實現分頁的邏輯。
  • packages/mirror-media-next/utils/api/index.js
    • createStaticJsonRequestfetchPremiumSections 函數進行了輕微的格式調整(換行)。
Activity
  • 此拉取請求由 Wendyooo7 建立。
  • PR 描述指出其目的是透過將資料來源從 GraphQL 切換到 JSON,解決分類頁面上潛在的新聞重複問題。
  • PR 描述中也提供了 Asana 任務的參考連結,用於追蹤相關工作。
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

這項 Pull Request 將「新聞」分類頁面的文章資料來源從 GraphQL 改為靜態 JSON,以解決潛在的文章重複問題。整體改動方向正確,但有幾個地方需要注意:

  1. 新的 API 呼叫函式 (fetchNewsCategoryInfo, fetchNewsCategoryPostsJSON) 在發生錯誤時沒有正確地將錯誤拋出,這會導致頁面在生產環境中崩潰。
  2. getServerSideProps 中,新的資料獲取邏輯缺乏錯誤處理,且與現有程式碼風格不一致。
  3. 判斷是否為「新聞」分類的邏輯可以更精確。
    我已經在相關的程式碼片段提供了具體的修改建議,以提高程式碼的穩健性和可維護性。

Comment on lines +34 to +36
} catch (err) {
console.error('Error fetching news category info: ', JSON.stringify(err))
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

catch 區塊中僅將錯誤印出至 console,但未將錯誤向上拋出。這會導致函式在發生錯誤時返回 undefined,而呼叫此函式的地方 (例如 pages/category/[slug].js 中的 getServerSideProps) 在試圖對 undefined 進行解構時 (如 const { data } = ...) 會觸發 TypeError,導致頁面崩潰。建議在 catch 區塊中重新拋出錯誤,讓上層的錯誤處理機制(如 Promise.allSettledtry/catch)能夠捕捉到。

  } catch (err) {
    console.error('Error fetching news category info: ', JSON.stringify(err))
    throw err
  }

Comment on lines +67 to +72
} catch (err) {
console.error(
'Failed to fetch JSON of URL_STATIC_NEWS_CATEGORY_POSTS: ',
JSON.stringify(err)
)
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

fetchNewsCategoryInfo 函式有相同的問題。catch 區塊補捉到錯誤後沒有重新拋出,會導致函式在發生錯誤時返回 undefined,進而使呼叫端在解構時發生 TypeError 並崩潰。請在 catch 區塊中重新拋出錯誤。

  } catch (err) {
    console.error(
      'Failed to fetch JSON of URL_STATIC_NEWS_CATEGORY_POSTS: ',
      JSON.stringify(err)
    )
    throw err
  }

Comment on lines +412 to +429
if (isNewsCategory && !isPremium) {
const responses = await Promise.allSettled([
fetchHeaderDataInDefaultPageLayout(),
])

// handle header data
;[sectionsData, topicsData] = processSettledResult(
responses[0],
getSectionAndTopicFromDefaultHeaderData,
`Error occurs while getting header data in category page (categorySlug: ${categorySlug})`,
globalLogFields
)

// handle fetch post data
const { data } = await fetchNewsCategoryPostsJSON()
posts = data.posts.items || []
postsCount = data.posts.counts || 0
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

此處直接呼叫 fetchNewsCategoryPostsJSON 並解構其結果,但沒有任何錯誤處理。如果 API 請求失敗,getServerSideProps 將會拋出錯誤,導致伺服器回傳 500 錯誤頁面。建議參考此檔案中其他資料請求的作法,使用 Promise.allSettled 搭配 processSettledResult 來處理,以確保在 API 請求失敗時能有優雅的降級處理(graceful degradation)。

  if (isNewsCategory && !isPremium) {
    const responses = await Promise.allSettled([
      fetchHeaderDataInDefaultPageLayout(),
      fetchNewsCategoryPostsJSON(),
    ])

    // handle header data
    ;[sectionsData, topicsData] = processSettledResult(
      responses[0],
      getSectionAndTopicFromDefaultHeaderData,
      `Error occurs while getting header data in category page (categorySlug: ${categorySlug})`,
      globalLogFields
    )

    // handle fetch post data
    const postsWrapper = processSettledResult(
      responses[1],
      (res) => res?.data?.posts,
      `Error occurs while getting news category posts in category page (categorySlug: ${categorySlug})`,
      globalLogFields
    )

    posts = postsWrapper?.items || []
    postsCount = postsWrapper?.counts || 0
  }

Comment on lines +307 to +308
const isNewsCategory =
categorySlug.startsWith('news') || categorySlug.startsWith('news?')

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

判斷是否為「新聞」分類的邏輯 categorySlug.startsWith('news') || categorySlug.startsWith('news?') 可能不夠穩健。categorySlug 是從 URL 路徑中解析而來,不包含查詢參數(query string)。因此,對於 /category/news?page=2 這樣的 URL,categorySlug 的值會是 newsstartsWith('news?') 這個條件可能永遠不會為真,或者會意外匹配到名為 news-something 的分類。建議將判斷條件修改為更精確的 categorySlug === 'news',以符合預期行為。

Suggested change
const isNewsCategory =
categorySlug.startsWith('news') || categorySlug.startsWith('news?')
const isNewsCategory = categorySlug === 'news'

Comment on lines +310 to 328
if (isNewsCategory) {
try {
const { data } = await fetchNewsCategoryInfo()
category = data.category || category
} catch (error) {
console.error('Error fetching news category:', error)
}
} else {
try {
const { data } = await fetchCategoryByCategorySlug(categorySlug)
category = data.category || category
} catch (error) {
logGqlError(
error,
`Error occurs while getting category data in category page (${categorySlug})`,
globalLogFields
)
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

這段程式碼透過 if/else 處理兩種不同來源的分類資料,但錯誤處理方式不一致(console.error vs logGqlError),且程式碼結構可以更簡潔。建議將其重構,使用 Promise.allSettledprocessSettledResult 來統一處理資料獲取與錯誤記錄,這也符合此檔案中其他資料獲取邏輯的風格。

  const fetchCategoryPromise = isNewsCategory
    ? fetchNewsCategoryInfo()
    : fetchCategoryByCategorySlug(categorySlug)

  const categoryResponses = await Promise.allSettled([fetchCategoryPromise])
  const categoryResult = processSettledResult(
    categoryResponses[0],
    (res) => res?.data?.category,
    `Error occurs while getting category data in category page (${categorySlug})`,
    globalLogFields
  )
  category = categoryResult || category

Comment on lines +68 to +71
console.error(
'Failed to fetch JSON of URL_STATIC_NEWS_CATEGORY_POSTS: ',
JSON.stringify(err)
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

使用 JSON.stringify(err) 來記錄錯誤可能會遺失 Error 物件中的重要資訊(例如 stack trace),尤其對於 axios 的錯誤物件。建議直接記錄整個 err 物件,或使用專案中既有的錯誤記錄工具(如 logAxiosError),以便於日後除錯。這個建議同樣適用於 fetchNewsCategoryInfo 函式。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant