Conversation
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 25 minutes and 51 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (17)
📝 WalkthroughWalkthrough更新 Node 版本指令、重构 Docker 为参数化三阶段构建、迁移 next-i18next 导入路径、新增地图组件与坐标解析工具、扩展全局 TypeScript 声明、移除 Mixpanel 调用并更新若干本地化文案与依赖版本。 Changes
Sequence Diagram(s)sequenceDiagram
participant Page as Next.js Page
participant EventMapCard as EventMapCard Component
participant Script as next/script
participant WindowTMap as window.TMap
participant Map as TMap.Map
Page->>EventMapCard: render(latitudeText, longitudeText)
EventMapCard->>Script: mount Tencent map script (lazyOnload)
Script-->>EventMapCard: script onReady / loaded
EventMapCard->>WindowTMap: construct LatLng / create Map
WindowTMap->>Map: initialize map instance
Map-->>EventMapCard: emit tilesloaded
EventMapCard->>EventMapCard: set status Finished / create MultiMarker
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/pages/[organization]/[slug].tsx (1)
47-50:⚠️ Potential issue | 🔴 Critical修复
addressLat/addressLon类型不匹配问题,阻止构建失败
addressLat和addressLon在src/types/event.ts中定义为string | null,但在 Line 59 和 Line 90 直接传给TMap.LatLng(number, number)构造函数,导致类型不符。Line 48 的&&检查无法进行类型收窄。需要在调用前显式将字符串转换为数字并验证空值。修复方案
const [mapLoadingStatus, setMapLoadingStatus] = useState(() => { - if (event.addressLat && event.addressLon) { + if (event.addressLat != null && event.addressLon != null) { return MapLoadingStatus.Loading; } return MapLoadingStatus.Idle; }); const initMap = () => { if (!window.TMap) throw new Error("TMap is not loaded"); + const lat = typeof event.addressLat === "string" ? Number(event.addressLat) : event.addressLat; + const lon = typeof event.addressLon === "string" ? Number(event.addressLon) : event.addressLon; + if (lat == null || lon == null || Number.isNaN(lat) || Number.isNaN(lon)) { + setMapLoadingStatus(MapLoadingStatus.Error); + return; + } setMapLoadingStatus(MapLoadingStatus.Loading); - const center = new window.TMap.LatLng(event.addressLat, event.addressLon); + const center = new window.TMap.LatLng(lat, lon); try { // ... id: "demo", styleId: "marker", - position: new window.TMap.LatLng(event.addressLat, event.addressLon), + position: new window.TMap.LatLng(lat, lon),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/`[organization]/[slug].tsx around lines 47 - 50, The event.addressLat/addressLon are typed as string | null so the current && check doesn't narrow to numbers and passing them to TMap.LatLng causes a type error; before using them (in the useState initializer for mapLoadingStatus and wherever TMap.LatLng is called) explicitly check for non-null, convert to numbers (e.g., via Number(...) or parseFloat(...)), validate with !isNaN(...), and only call new TMap.LatLng(latNum, lonNum) when both parsed values are valid; update code paths that reference mapLoadingStatus, setMapLoadingStatus, MapLoadingStatus, event.addressLat, event.addressLon, and the TMap.LatLng calls accordingly to use the parsed numeric values and handle the invalid/null case.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@Dockerfile`:
- Around line 99-110: The Dockerfile uses COPY --chown=nextjs:nodejs in the COPY
lines (the two COPY statements that copy next.config.js and
next-i18next.config.js), but the base node:...-slim image only provides the node
user/group so the build fails; change those COPY --chown entries to use
--chown=node:node (or remove the --chown) so they match the existing USER node
and available /etc/passwd:/etc/group entries, ensuring the files are owned by
node before the final USER node step.
- Around line 36-37: The Dockerfile currently uses "FROM node:${NODE_VERSION} AS
builder" with NODE_VERSION defaulting to a "-slim" (Debian) image but runs "apk
add --no-cache git" which fails on Debian; either switch the base to an Alpine
variant (e.g., change the FROM to node:${NODE_VERSION}-alpine) or replace the
apk command with Debian/apt commands (run apt-get update && apt-get install -y
git ca-certificates && rm -rf /var/lib/apt/lists/*) so the package manager
matches the base image; update the Dockerfile lines referencing FROM
node:${NODE_VERSION} AS builder and the package installation step accordingly.
- Around line 16-29: The Dockerfile COPY currently includes a glob ".npmrc*"
which will bake any .npmrc (and credentials) into the image layer; remove
".npmrc*" from the COPY step and instead supply npm credentials as a BuildKit
secret during the RUN dependency-install step (the RUN that checks
package-lock.json / yarn.lock / pnpm-lock.yaml) by using
--mount=type=secret,id=npmrc (or a similar secret id) so the installer can read
the credentials only at build time; update the dependency-install RUN
invocations (the RUN that contains npm ci / corepack enable yarn && yarn install
/ corepack enable pnpm && pnpm install) to mount the secret and point the
installer to it (e.g., via NPM_CONFIG_USERCONFIG or appropriate flag) rather
than copying .npmrc into the image.
In `@src/pages/_document.tsx`:
- Line 8: 在 _document.tsx 中将 Html 元素启用了平滑滚动(Html
data-scroll-behavior="smooth")但未对 prefers-reduced-motion
做降级处理;请在全局样式文件(src/styles/globals.css)中添加针对媒体查询 `@media` (prefers-reduced-motion:
reduce) 的规则,将 html 的 scroll-behavior 改回 auto,以便为前庭功能障碍用户禁用平滑滚动并确保无障碍访问;检查并更新
globals.css 中现有 scroll-behavior 规则以包含该媒体查询以覆盖默认平滑行为。
---
Outside diff comments:
In `@src/pages/`[organization]/[slug].tsx:
- Around line 47-50: The event.addressLat/addressLon are typed as string | null
so the current && check doesn't narrow to numbers and passing them to
TMap.LatLng causes a type error; before using them (in the useState initializer
for mapLoadingStatus and wherever TMap.LatLng is called) explicitly check for
non-null, convert to numbers (e.g., via Number(...) or parseFloat(...)),
validate with !isNaN(...), and only call new TMap.LatLng(latNum, lonNum) when
both parsed values are valid; update code paths that reference mapLoadingStatus,
setMapLoadingStatus, MapLoadingStatus, event.addressLat, event.addressLon, and
the TMap.LatLng calls accordingly to use the parsed numeric values and handle
the invalid/null case.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 75c80b56-a4c7-4dd2-bd04-2fb5ac4f8d3e
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (29)
.nvmrcDockerfileadditional.d.tspackage.jsonpublic/locales/en/common.jsonpublic/locales/zh-Hans/common.jsonsrc/components/OrganizationLinkButton/index.tsxsrc/components/SimpleEventCard/index.tsxsrc/components/event/EventSourceButton/index.tsxsrc/components/eventCard/index.tsxsrc/components/layout/footer.tsxsrc/components/layout/header.tsxsrc/components/layout/index.tsxsrc/components/layout/localeMenu.tsxsrc/components/organizationStatus/index.tsxsrc/pages/404.tsxsrc/pages/500.tsxsrc/pages/[organization]/[slug].tsxsrc/pages/[organization]/index.tsxsrc/pages/_app.tsxsrc/pages/_document.tsxsrc/pages/about.tsxsrc/pages/city/[code].tsxsrc/pages/city/index.tsxsrc/pages/index.tsxsrc/pages/organization.tsxsrc/pages/years.tsxsrc/utils/track.tstsconfig.json
| COPY package.json yarn.lock* .yarnrc.yml package-lock.json* pnpm-lock.yaml* .npmrc* ./ | ||
|
|
||
| # Install project dependencies with frozen lockfile for reproducible builds | ||
| RUN --mount=type=cache,target=/root/.npm \ | ||
| --mount=type=cache,target=/usr/local/share/.cache/yarn \ | ||
| --mount=type=cache,target=/root/.local/share/pnpm/store \ | ||
| if [ -f package-lock.json ]; then \ | ||
| npm ci --no-audit --no-fund; \ | ||
| elif [ -f yarn.lock ]; then \ | ||
| corepack enable yarn && yarn install --frozen-lockfile --production=false; \ | ||
| elif [ -f pnpm-lock.yaml ]; then \ | ||
| corepack enable pnpm && pnpm install --frozen-lockfile; \ | ||
| else \ | ||
| echo "No lockfile found." && exit 1; \ |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# 查看 Dockerfile 全部内容
find . -name "Dockerfile" -type f | head -5Repository: FurryConsChina/website
Length of output: 78
🏁 Script executed:
# 查找 Dockerfile 位置和内容
git ls-files | grep -i dockerfile | head -10Repository: FurryConsChina/website
Length of output: 76
🏁 Script executed:
# 读取 Dockerfile 完整内容
cat -n DockerfileRepository: FurryConsChina/website
Length of output: 5052
🏁 Script executed:
# 检查是否存在 .npmrc 文件
find . -name ".npmrc*" -type f 2>/dev/nullRepository: FurryConsChina/website
Length of output: 48
🏁 Script executed:
# 检查 .dockerignore 文件
if [ -f .dockerignore ]; then cat -n .dockerignore; else echo ".dockerignore 不存在"; fiRepository: FurryConsChina/website
Length of output: 175
🏁 Script executed:
# 检查项目根目录所有隐藏文件
ls -la | grep -E '^\.' | head -20Repository: FurryConsChina/website
Length of output: 48
🏁 Script executed:
# 读取 .dockerignore 文件内容
cat -n .dockerignoreRepository: FurryConsChina/website
Length of output: 175
🏁 Script executed:
# 直接读取 .dockerignore
cat .dockerignoreRepository: FurryConsChina/website
Length of output: 133
不要直接复制 .npmrc 到构建层。
Line 16 在 COPY 命令中包含 .npmrc* 的通配符模式。如果 .npmrc 包含 npm registry 凭据,当前做法会将其作为普通文件复制到镜像层,导致凭据暴露在构建缓存中。Docker 官方推荐使用 BuildKit secret mount 处理敏感凭据,使其仅在安装命令期间临时可见。
建议修改
-COPY package.json yarn.lock* .yarnrc.yml package-lock.json* pnpm-lock.yaml* .npmrc* ./
+COPY package.json yarn.lock* .yarnrc.yml package-lock.json* pnpm-lock.yaml* ./
RUN --mount=type=cache,target=/root/.npm \
--mount=type=cache,target=/usr/local/share/.cache/yarn \
--mount=type=cache,target=/root/.local/share/pnpm/store \
+ --mount=type=secret,id=npmrc,target=/app/.npmrc,required=false \
if [ -f package-lock.json ]; then \参考:Docker BuildKit Secrets Documentation
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Dockerfile` around lines 16 - 29, The Dockerfile COPY currently includes a
glob ".npmrc*" which will bake any .npmrc (and credentials) into the image
layer; remove ".npmrc*" from the COPY step and instead supply npm credentials as
a BuildKit secret during the RUN dependency-install step (the RUN that checks
package-lock.json / yarn.lock / pnpm-lock.yaml) by using
--mount=type=secret,id=npmrc (or a similar secret id) so the installer can read
the credentials only at build time; update the dependency-install RUN
invocations (the RUN that contains npm ci / corepack enable yarn && yarn install
/ corepack enable pnpm && pnpm install) to mount the secret and point the
installer to it (e.g., via NPM_CONFIG_USERCONFIG or appropriate flag) rather
than copying .npmrc into the image.
| export default function Document() { | ||
| return ( | ||
| <Html> | ||
| <Html data-scroll-behavior="smooth"> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 查找是否启用了平滑滚动及 reduced-motion 降级
rg -n -C2 'scroll-behavior'
rg -n -C2 'prefers-reduced-motion'Repository: FurryConsChina/website
Length of output: 1196
需要补充 prefers-reduced-motion 媒体查询以确保无障碍访问。
平滑滚动已在 src/styles/globals.css 第 13 行和 src/pages/_document.tsx 第 8 行启用,但缺少针对 prefers-reduced-motion 的降级处理。前庭功能障碍用户会因过度的平滑动画而感到不适。建议在全局样式中添加:
`@media` (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/pages/_document.tsx` at line 8, 在 _document.tsx 中将 Html 元素启用了平滑滚动(Html
data-scroll-behavior="smooth")但未对 prefers-reduced-motion
做降级处理;请在全局样式文件(src/styles/globals.css)中添加针对媒体查询 `@media` (prefers-reduced-motion:
reduce) 的规则,将 html 的 scroll-behavior 改回 auto,以便为前庭功能障碍用户禁用平滑滚动并确保无障碍访问;检查并更新
globals.css 中现有 scroll-behavior 规则以包含该媒体查询以覆盖默认平滑行为。
📦 Next.js Bundle Analysis for furrycons-siteThis analysis was generated by the Next.js Bundle Analysis action. 🤖
|
| Page | Size (compressed) |
|---|---|
global |
352.31 KB (🟡 +17.04 KB) |
Details
The global bundle is the javascript bundle that loads alongside every page. It is in its own category because its impact is much higher - an increase to its size means that every page on your website loads slower, and a decrease means every page loads faster.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
If you want further insight into what is behind the changes, give @next/bundle-analyzer a try!
Nine Pages Changed Size
The following pages changed size from the code in this PR compared to its base branch:
| Page | Size (compressed) | First Load | % of Budget (350 KB) |
|---|---|---|---|
/ |
43.07 KB |
395.38 KB | 112.97% (+/- <0.01%) |
/404 |
877 B |
353.17 KB | 100.91% (+/- <0.01%) |
/500 |
875 B |
353.17 KB | 100.90% (🟡 +0.01%) |
/[organization] |
8.66 KB |
360.97 KB | 103.13% (🟡 +0.01%) |
/[organization]/[slug] |
37.5 KB |
389.82 KB | 111.38% (🟡 +0.06%) |
/city |
997 B |
353.29 KB | 100.94% (+/- <0.01%) |
/city/[code] |
1.69 KB |
354 KB | 101.14% (🟡 +0.01%) |
/organization |
3.8 KB |
356.11 KB | 101.75% (+/- <0.01%) |
/years |
4.9 KB |
357.21 KB | 102.06% (+/- <0.01%) |
Details
Only the gzipped size is provided here based on an expert tip.
First Load is the size of the global bundle plus the bundle for the individual page. If a user were to show up to your website and land on a given page, the first load size represents the amount of javascript that user would need to download. If next/link is used, subsequent page loads would only need to download that page's bundle (the number in the "Size" column), since the global bundle has already been downloaded.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
The "Budget %" column shows what percentage of your performance budget the First Load total takes up. For example, if your budget was 100kb, and a given page's first load size was 10kb, it would be 10% of your budget. You can also see how much this has increased or decreased compared to the base branch of your PR. If this percentage has increased by 20% or more, there will be a red status indicator applied, indicating that special attention should be given to this. If you see "+/- <0.01%" it means that there was a change in bundle size, but it is a trivial enough amount that it can be ignored.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/components/event/EventMapCard.tsx (1)
52-54: 为地图实例和事件监听增加卸载清理。第 52-54 行注册
tilesloaded事件后缺少清理逻辑;第 83-87 行的useEffect没有返回清理函数。建议存储 map 和 marker 实例到 ref,在useEffectcleanup 中调用map.off()解除监听、multiMarker.setMap(null)移除标记、map.destroy()销毁实例。建议修改(示意)
+ const mapRef = useRef<any>(null); + const markerRef = useRef<any>(null); + const tilesLoadedHandlerRef = useRef<(() => void) | null>(null); const initMap = useCallback(() => { if (!window.TMap || !isValid || !mapContainerRef.current || hasInitializedRef.current) { return; } setMapLoadingStatus(MapLoadingStatus.Loading); try { const center = new window.TMap.LatLng(latitude, longitude); const map = new window.TMap.Map(mapContainerRef.current, { center, zoom: 17.2, pitch: 43.5, rotation: 45, }); + mapRef.current = map; hasInitializedRef.current = true; - map.on("tilesloaded", () => { + tilesLoadedHandlerRef.current = () => { setMapLoadingStatus(MapLoadingStatus.Finished); - }); + }; + map.on("tilesloaded", tilesLoadedHandlerRef.current); - new window.TMap.MultiMarker({ + markerRef.current = new window.TMap.MultiMarker({ id: "marker-layer", map, styles: { marker: new window.TMap.MarkerStyle({ width: 25, height: 35, anchor: { x: 16, y: 32 }, }), }, geometries: [ { id: "event-location-marker", styleId: "marker", position: center, properties: { title: "marker", }, }, ], - }); + }); } catch (error) { console.error(error); setMapLoadingStatus(MapLoadingStatus.Error); } }, [isValid, latitude, longitude]); useEffect(() => { if (window.TMap) { queueMicrotask(initMap); } + return () => { + if (mapRef.current && tilesLoadedHandlerRef.current) { + mapRef.current.off?.("tilesloaded", tilesLoadedHandlerRef.current); + } + markerRef.current?.setMap?.(null); + mapRef.current?.destroy?.(); + hasInitializedRef.current = false; + }; }, [initMap]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/event/EventMapCard.tsx` around lines 52 - 54, The tilesloaded event listener on the map and the map/marker instances aren't cleaned up; update the component to store the map and multiMarker in refs (e.g., mapRef, multiMarkerRef), add a cleanup function to the useEffect that registered the tilesloaded listener to call mapRef.current?.off("tilesloaded", ...), call multiMarkerRef.current?.setMap(null) to remove markers, and finally call mapRef.current?.destroy() to fully destroy the map instance; ensure setMapLoadingStatus(MapLoadingStatus.Finished) stays inside the listener and the same listener reference is used when calling off.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/event/EventMapCard.tsx`:
- Around line 95-99: The Script component usage only handles onReady (initMap)
so failures leave mapLoadingStatus stuck in loading; add an error branch to
handle script load failures by using Script's onError (or attach an error
handler) to set mapLoadingStatus to Error and surface the error state (e.g.,
stop the loading overlay and optionally log the error), referencing the existing
Script element, initMap callback, and state variable mapLoadingStatus to locate
where to wire the handler.
---
Nitpick comments:
In `@src/components/event/EventMapCard.tsx`:
- Around line 52-54: The tilesloaded event listener on the map and the
map/marker instances aren't cleaned up; update the component to store the map
and multiMarker in refs (e.g., mapRef, multiMarkerRef), add a cleanup function
to the useEffect that registered the tilesloaded listener to call
mapRef.current?.off("tilesloaded", ...), call
multiMarkerRef.current?.setMap(null) to remove markers, and finally call
mapRef.current?.destroy() to fully destroy the map instance; ensure
setMapLoadingStatus(MapLoadingStatus.Finished) stays inside the listener and the
same listener reference is used when calling off.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 78988e26-7f80-480f-93c4-4ad071cbdf54
📒 Files selected for processing (4)
package.jsonsrc/components/event/EventMapCard.tsxsrc/pages/[organization]/[slug].tsxsrc/utils/coordinate.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- src/pages/[organization]/[slug].tsx
- package.json
📦 Next.js Bundle Analysis for furrycons-siteThis analysis was generated by the Next.js Bundle Analysis action. 🤖
|
| Page | Size (compressed) |
|---|---|
global |
352.31 KB (🟡 +17.04 KB) |
Details
The global bundle is the javascript bundle that loads alongside every page. It is in its own category because its impact is much higher - an increase to its size means that every page on your website loads slower, and a decrease means every page loads faster.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
If you want further insight into what is behind the changes, give @next/bundle-analyzer a try!
Nine Pages Changed Size
The following pages changed size from the code in this PR compared to its base branch:
| Page | Size (compressed) | First Load | % of Budget (350 KB) |
|---|---|---|---|
/ |
43.07 KB |
395.39 KB | 112.97% (+/- <0.01%) |
/404 |
877 B |
353.17 KB | 100.91% (+/- <0.01%) |
/500 |
875 B |
353.17 KB | 100.91% (+/- <0.01%) |
/[organization] |
8.66 KB |
360.97 KB | 103.13% (🟡 +0.01%) |
/[organization]/[slug] |
37.5 KB |
389.82 KB | 111.38% (🟡 +0.06%) |
/city |
997 B |
353.29 KB | 100.94% (+/- <0.01%) |
/city/[code] |
1.69 KB |
354.01 KB | 101.14% (🟡 +0.01%) |
/organization |
3.8 KB |
356.12 KB | 101.75% (+/- <0.01%) |
/years |
4.9 KB |
357.22 KB | 102.06% (+/- <0.01%) |
Details
Only the gzipped size is provided here based on an expert tip.
First Load is the size of the global bundle plus the bundle for the individual page. If a user were to show up to your website and land on a given page, the first load size represents the amount of javascript that user would need to download. If next/link is used, subsequent page loads would only need to download that page's bundle (the number in the "Size" column), since the global bundle has already been downloaded.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
The "Budget %" column shows what percentage of your performance budget the First Load total takes up. For example, if your budget was 100kb, and a given page's first load size was 10kb, it would be 10% of your budget. You can also see how much this has increased or decreased compared to the base branch of your PR. If this percentage has increased by 20% or more, there will be a red status indicator applied, indicating that special attention should be given to this. If you see "+/- <0.01%" it means that there was a change in bundle size, but it is a trivial enough amount that it can be ignored.
📦 Next.js Bundle Analysis for furrycons-siteThis analysis was generated by the Next.js Bundle Analysis action. 🤖
|
| Page | Size (compressed) |
|---|---|
global |
352.29 KB (🟡 +17.02 KB) |
Details
The global bundle is the javascript bundle that loads alongside every page. It is in its own category because its impact is much higher - an increase to its size means that every page on your website loads slower, and a decrease means every page loads faster.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
If you want further insight into what is behind the changes, give @next/bundle-analyzer a try!
Nine Pages Changed Size
The following pages changed size from the code in this PR compared to its base branch:
| Page | Size (compressed) | First Load | % of Budget (350 KB) |
|---|---|---|---|
/ |
43.07 KB |
395.36 KB | 112.96% (+/- <0.01%) |
/404 |
877 B |
353.15 KB | 100.90% (+/- <0.01%) |
/500 |
875 B |
353.14 KB | 100.90% (+/- <0.01%) |
/[organization] |
8.66 KB |
360.94 KB | 103.13% (+/- <0.01%) |
/[organization]/[slug] |
37.63 KB |
389.92 KB | 111.40% (🟡 +0.11%) |
/city |
997 B |
353.26 KB | 100.93% (+/- <0.01%) |
/city/[code] |
1.69 KB |
353.98 KB | 101.14% (+/- <0.01%) |
/organization |
3.8 KB |
356.09 KB | 101.74% (+/- <0.01%) |
/years |
4.9 KB |
357.19 KB | 102.05% (🟡 +0.01%) |
Details
Only the gzipped size is provided here based on an expert tip.
First Load is the size of the global bundle plus the bundle for the individual page. If a user were to show up to your website and land on a given page, the first load size represents the amount of javascript that user would need to download. If next/link is used, subsequent page loads would only need to download that page's bundle (the number in the "Size" column), since the global bundle has already been downloaded.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
The "Budget %" column shows what percentage of your performance budget the First Load total takes up. For example, if your budget was 100kb, and a given page's first load size was 10kb, it would be 10% of your budget. You can also see how much this has increased or decreased compared to the base branch of your PR. If this percentage has increased by 20% or more, there will be a red status indicator applied, indicating that special attention should be given to this. If you see "+/- <0.01%" it means that there was a change in bundle size, but it is a trivial enough amount that it can be ignored.
📦 Next.js Bundle Analysis for furrycons-siteThis analysis was generated by the Next.js Bundle Analysis action. 🤖
|
| Page | Size (compressed) |
|---|---|
global |
356.25 KB (🟡 +20.98 KB) |
Details
The global bundle is the javascript bundle that loads alongside every page. It is in its own category because its impact is much higher - an increase to its size means that every page on your website loads slower, and a decrease means every page loads faster.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
If you want further insight into what is behind the changes, give @next/bundle-analyzer a try!
Ten Pages Changed Size
The following pages changed size from the code in this PR compared to its base branch:
| Page | Size (compressed) | First Load | % of Budget (350 KB) |
|---|---|---|---|
/ |
45.47 KB |
401.72 KB | 114.78% (🟡 +0.68%) |
/404 |
878 B |
357.11 KB | 102.03% (+/- <0.01%) |
/500 |
875 B |
357.11 KB | 102.03% (+/- <0.01%) |
/[organization] |
8.66 KB |
364.91 KB | 104.26% (+/- <0.01%) |
/[organization]/[slug] |
37.62 KB |
393.88 KB | 112.54% (🟡 +0.10%) |
/_error |
2.46 KB |
358.72 KB | 102.49% (+/- <0.01%) |
/city |
997 B |
357.23 KB | 102.07% (+/- <0.01%) |
/city/[code] |
1.69 KB |
357.95 KB | 102.27% (+/- <0.01%) |
/organization |
3.8 KB |
360.06 KB | 102.87% (+/- <0.01%) |
/years |
4.9 KB |
361.15 KB | 103.19% (+/- <0.01%) |
Details
Only the gzipped size is provided here based on an expert tip.
First Load is the size of the global bundle plus the bundle for the individual page. If a user were to show up to your website and land on a given page, the first load size represents the amount of javascript that user would need to download. If next/link is used, subsequent page loads would only need to download that page's bundle (the number in the "Size" column), since the global bundle has already been downloaded.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
The "Budget %" column shows what percentage of your performance budget the First Load total takes up. For example, if your budget was 100kb, and a given page's first load size was 10kb, it would be 10% of your budget. You can also see how much this has increased or decreased compared to the base branch of your PR. If this percentage has increased by 20% or more, there will be a red status indicator applied, indicating that special attention should be given to this. If you see "+/- <0.01%" it means that there was a change in bundle size, but it is a trivial enough amount that it can be ignored.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/components/event/EventMapCard.tsx (2)
110-116: 建议将 API 密钥移至环境变量。第 112 行硬编码了腾讯地图 API 密钥,静态分析工具也标记了此问题。虽然地图 API 密钥通常通过服务端域名白名单保护,但将其暴露在客户端代码中仍有风险(如滥用配额、逆向分析等)。
建议使用
NEXT_PUBLIC_前缀的环境变量:♻️ 建议修改
<Script key={scriptReloadKey} - src="https://map.qq.com/api/gljs?v=1.exp&key=PXEBZ-QLM6C-RZX2K-AV2XX-SBBW5-VGFC4" + src={`https://map.qq.com/api/gljs?v=1.exp&key=${process.env.NEXT_PUBLIC_TENCENT_MAP_KEY}`} strategy="lazyOnload" onReady={initMap} onError={() => setMapLoadingStatus(MapLoadingStatus.Error)} />在
.env.local或部署环境中配置:NEXT_PUBLIC_TENCENT_MAP_KEY=PXEBZ-QLM6C-RZX2K-AV2XX-SBBW5-VGFC4🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/event/EventMapCard.tsx` around lines 110 - 116, The Tencent Maps API key is hardcoded in the Script component (Script with key={scriptReloadKey}, onReady={initMap}, onError={() => setMapLoadingStatus(MapLoadingStatus.Error)}); move the key into an environment variable (NEXT_PUBLIC_TENCENT_MAP_KEY) and update the Script src to interpolate process.env.NEXT_PUBLIC_TENCENT_MAP_KEY so the component reads the key from the environment instead of embedding the literal string.
43-56: 考虑在组件卸载时清理地图实例。
initMap中创建的地图实例未存储到 ref 中,组件卸载时无法调用清理方法。如果 TMap SDK 内部持有引用,可能导致内存泄漏。♻️ 可选改进
+ const mapInstanceRef = useRef<InstanceType<typeof window.TMap.Map> | null>(null); const initMap = useCallback(() => { // ...existing checks... try { const center = new window.TMap.LatLng(latitude, longitude); const map = new window.TMap.Map(mapContainerRef.current, { center, zoom: 17.2, pitch: 43.5, rotation: 45, }); + mapInstanceRef.current = map; hasInitializedRef.current = true; // ...rest of code... } }, [isValid, latitude, longitude]); + useEffect(() => { + return () => { + mapInstanceRef.current?.destroy?.(); + }; + }, []);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/event/EventMapCard.tsx` around lines 43 - 56, The map instance created in initMap is not saved and therefore cannot be cleaned up on unmount; store the created window.TMap.Map instance in a ref (e.g., mapRef) when you create it inside initMap, and in the component's cleanup (the return function of the useEffect that calls initMap) check mapRef.current and call the TMap cleanup method (e.g., mapRef.current.destroy() or mapRef.current.dispose()) and null it out, also clear any listeners (e.g., the "tilesloaded" handler) and set hasInitializedRef.current = false to avoid leaks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@Dockerfile`:
- Around line 37-39: 在 Dockerfile 中的 RUN 指令开头包含多余的 "+" 符号(看到的 "+RUN apt-get
update ..." 与后续行),这些是 diff 标记而非合法 Dockerfile 语法;删除所有行首的 "+",保留 RUN apt-get
update \ && apt-get install -y --no-install-recommends git \ && rm -rf
/var/lib/apt/lists/* 的原始内容并确保反斜线续行和空格正确,以修复构建失败和 Hadolint DL1000 报错(定位符:RUN 指令)。
---
Nitpick comments:
In `@src/components/event/EventMapCard.tsx`:
- Around line 110-116: The Tencent Maps API key is hardcoded in the Script
component (Script with key={scriptReloadKey}, onReady={initMap}, onError={() =>
setMapLoadingStatus(MapLoadingStatus.Error)}); move the key into an environment
variable (NEXT_PUBLIC_TENCENT_MAP_KEY) and update the Script src to interpolate
process.env.NEXT_PUBLIC_TENCENT_MAP_KEY so the component reads the key from the
environment instead of embedding the literal string.
- Around line 43-56: The map instance created in initMap is not saved and
therefore cannot be cleaned up on unmount; store the created window.TMap.Map
instance in a ref (e.g., mapRef) when you create it inside initMap, and in the
component's cleanup (the return function of the useEffect that calls initMap)
check mapRef.current and call the TMap cleanup method (e.g.,
mapRef.current.destroy() or mapRef.current.dispose()) and null it out, also
clear any listeners (e.g., the "tilesloaded" handler) and set
hasInitializedRef.current = false to avoid leaks.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 2cdbf1b7-a277-47bc-85d9-0d9b3eafe934
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (10)
AGENTS.mdDockerfilepackage.jsonpublic/locales/zh-Hans/common.jsonpublic/locales/zh-Hant/common.jsonsrc/components/event/EventMapCard.tsxsrc/pages/_app.tsxsrc/pages/index.tsxsrc/types/list.tssrc/utils/event.ts
✅ Files skipped from review due to trivial changes (2)
- AGENTS.md
- public/locales/zh-Hant/common.json
🚧 Files skipped from review as they are similar to previous changes (3)
- public/locales/zh-Hans/common.json
- package.json
- src/pages/index.tsx
| +RUN apt-get update \ | ||
| + && apt-get install -y --no-install-recommends git \ | ||
| + && rm -rf /var/lib/apt/lists/* |
There was a problem hiding this comment.
Dockerfile 语法错误:+ 字符导致构建失败。
第 37-39 行开头的 + 符号是 diff 标记,不是有效的 Dockerfile 语法。这会导致 docker build 立即失败,Hadolint 也报告了 DL1000 错误。
🐛 修复建议
FROM node:${NODE_VERSION} AS builder
-+RUN apt-get update \
-+ && apt-get install -y --no-install-recommends git \
-+ && rm -rf /var/lib/apt/lists/*
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends git \
+ && rm -rf /var/lib/apt/lists/*🧰 Tools
🪛 Hadolint (2.14.0)
[error] 37-37: unexpected '+'
expecting '#', '', ADD, ARG, CMD, COPY, ENTRYPOINT, ENV, EXPOSE, FROM, HEALTHCHECK, LABEL, MAINTAINER, ONBUILD, RUN, SHELL, STOPSIGNAL, USER, VOLUME, WORKDIR, a pragma, at least one space, or end of input
(DL1000)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Dockerfile` around lines 37 - 39, 在 Dockerfile 中的 RUN 指令开头包含多余的 "+" 符号(看到的
"+RUN apt-get update ..." 与后续行),这些是 diff 标记而非合法 Dockerfile 语法;删除所有行首的 "+",保留 RUN
apt-get update \ && apt-get install -y --no-install-recommends git \ && rm -rf
/var/lib/apt/lists/* 的原始内容并确保反斜线续行和空格正确,以修复构建失败和 Hadolint DL1000 报错(定位符:RUN 指令)。
📦 Next.js Bundle Analysis for furrycons-siteThis analysis was generated by the Next.js Bundle Analysis action. 🤖
|
| Page | Size (compressed) |
|---|---|
global |
356.25 KB (🟡 +20.98 KB) |
Details
The global bundle is the javascript bundle that loads alongside every page. It is in its own category because its impact is much higher - an increase to its size means that every page on your website loads slower, and a decrease means every page loads faster.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
If you want further insight into what is behind the changes, give @next/bundle-analyzer a try!
Ten Pages Changed Size
The following pages changed size from the code in this PR compared to its base branch:
| Page | Size (compressed) | First Load | % of Budget (350 KB) |
|---|---|---|---|
/ |
19.98 KB |
376.23 KB | 107.49% (🟢 -6.59%) |
/404 |
878 B |
357.11 KB | 102.03% (+/- <0.01%) |
/500 |
875 B |
357.11 KB | 102.03% (+/- <0.01%) |
/[organization] |
8.66 KB |
364.91 KB | 104.26% (+/- <0.01%) |
/[organization]/[slug] |
12.16 KB |
368.42 KB | 105.26% (🟢 -7.17%) |
/_error |
2.46 KB |
358.72 KB | 102.49% (+/- <0.01%) |
/city |
996 B |
357.23 KB | 102.06% (🟡 +0.01%) |
/city/[code] |
1.69 KB |
357.94 KB | 102.27% (+/- <0.01%) |
/organization |
3.8 KB |
360.05 KB | 102.87% (+/- <0.01%) |
/years |
4.9 KB |
361.15 KB | 103.19% (+/- <0.01%) |
Details
Only the gzipped size is provided here based on an expert tip.
First Load is the size of the global bundle plus the bundle for the individual page. If a user were to show up to your website and land on a given page, the first load size represents the amount of javascript that user would need to download. If next/link is used, subsequent page loads would only need to download that page's bundle (the number in the "Size" column), since the global bundle has already been downloaded.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
The "Budget %" column shows what percentage of your performance budget the First Load total takes up. For example, if your budget was 100kb, and a given page's first load size was 10kb, it would be 10% of your budget. You can also see how much this has increased or decreased compared to the base branch of your PR. If this percentage has increased by 20% or more, there will be a red status indicator applied, indicating that special attention should be given to this. If you see "+/- <0.01%" it means that there was a change in bundle size, but it is a trivial enough amount that it can be ignored.
📦 Next.js Bundle Analysis for furrycons-siteThis analysis was generated by the Next.js Bundle Analysis action. 🤖
|
| Page | Size (compressed) |
|---|---|
global |
356.25 KB (🟡 +20.98 KB) |
Details
The global bundle is the javascript bundle that loads alongside every page. It is in its own category because its impact is much higher - an increase to its size means that every page on your website loads slower, and a decrease means every page loads faster.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
If you want further insight into what is behind the changes, give @next/bundle-analyzer a try!
Ten Pages Changed Size
The following pages changed size from the code in this PR compared to its base branch:
| Page | Size (compressed) | First Load | % of Budget (350 KB) |
|---|---|---|---|
/ |
19.98 KB |
376.23 KB | 107.49% (🟢 -6.59%) |
/404 |
878 B |
357.11 KB | 102.03% (+/- <0.01%) |
/500 |
875 B |
357.1 KB | 102.03% (+/- <0.01%) |
/[organization] |
8.66 KB |
364.91 KB | 104.26% (+/- <0.01%) |
/[organization]/[slug] |
12.16 KB |
368.41 KB | 105.26% (🟢 -7.17%) |
/_error |
2.46 KB |
358.71 KB | 102.49% (+/- <0.01%) |
/city |
996 B |
357.22 KB | 102.06% (+/- <0.01%) |
/city/[code] |
1.69 KB |
357.94 KB | 102.27% (+/- <0.01%) |
/organization |
3.8 KB |
360.05 KB | 102.87% (+/- <0.01%) |
/years |
4.9 KB |
361.15 KB | 103.19% (+/- <0.01%) |
Details
Only the gzipped size is provided here based on an expert tip.
First Load is the size of the global bundle plus the bundle for the individual page. If a user were to show up to your website and land on a given page, the first load size represents the amount of javascript that user would need to download. If next/link is used, subsequent page loads would only need to download that page's bundle (the number in the "Size" column), since the global bundle has already been downloaded.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
The "Budget %" column shows what percentage of your performance budget the First Load total takes up. For example, if your budget was 100kb, and a given page's first load size was 10kb, it would be 10% of your budget. You can also see how much this has increased or decreased compared to the base branch of your PR. If this percentage has increased by 20% or more, there will be a red status indicator applied, indicating that special attention should be given to this. If you see "+/- <0.01%" it means that there was a change in bundle size, but it is a trivial enough amount that it can be ignored.
📦 Next.js Bundle Analysis for furrycons-siteThis analysis was generated by the Next.js Bundle Analysis action. 🤖
|
| Page | Size (compressed) |
|---|---|
global |
356.25 KB (🟡 +20.98 KB) |
Details
The global bundle is the javascript bundle that loads alongside every page. It is in its own category because its impact is much higher - an increase to its size means that every page on your website loads slower, and a decrease means every page loads faster.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
If you want further insight into what is behind the changes, give @next/bundle-analyzer a try!
Ten Pages Changed Size
The following pages changed size from the code in this PR compared to its base branch:
| Page | Size (compressed) | First Load | % of Budget (350 KB) |
|---|---|---|---|
/ |
19.98 KB |
376.23 KB | 107.49% (🟢 -6.59%) |
/404 |
878 B |
357.11 KB | 102.03% (+/- <0.01%) |
/500 |
875 B |
357.1 KB | 102.03% (+/- <0.01%) |
/[organization] |
8.66 KB |
364.91 KB | 104.26% (+/- <0.01%) |
/[organization]/[slug] |
12.16 KB |
368.41 KB | 105.26% (🟢 -7.17%) |
/_error |
2.46 KB |
358.71 KB | 102.49% (+/- <0.01%) |
/city |
996 B |
357.22 KB | 102.06% (+/- <0.01%) |
/city/[code] |
1.69 KB |
357.94 KB | 102.27% (+/- <0.01%) |
/organization |
3.8 KB |
360.05 KB | 102.87% (+/- <0.01%) |
/years |
4.9 KB |
361.15 KB | 103.19% (+/- <0.01%) |
Details
Only the gzipped size is provided here based on an expert tip.
First Load is the size of the global bundle plus the bundle for the individual page. If a user were to show up to your website and land on a given page, the first load size represents the amount of javascript that user would need to download. If next/link is used, subsequent page loads would only need to download that page's bundle (the number in the "Size" column), since the global bundle has already been downloaded.
Any third party scripts you have added directly to your app using the <script> tag are not accounted for in this analysis
The "Budget %" column shows what percentage of your performance budget the First Load total takes up. For example, if your budget was 100kb, and a given page's first load size was 10kb, it would be 10% of your budget. You can also see how much this has increased or decreased compared to the base branch of your PR. If this percentage has increased by 20% or more, there will be a red status indicator applied, indicating that special attention should be given to this. If you see "+/- <0.01%" it means that there was a change in bundle size, but it is a trivial enough amount that it can be ignored.
Summary by CodeRabbit
新功能
更新