廣州白云做網(wǎng)站濟寧百度推廣電話
文章目錄
- 前言
- 網(wǎng)站默認語言問題
- 網(wǎng)站訪問統(tǒng)計問題
- Error: Empty components are self-closing
- Error: A space is required before closing bracket
- 總結(jié)
前言
看標題大概能猜到這是一篇雜合體的總結(jié),是這兩天處理網(wǎng)站遇到的小問題,怕過段時間再忘了所以總結(jié)到一起便于反過來查找問題解決方案,這個問題都是之前未曾接觸過的,但遇到他們不用懼怕,只要假裝自己能解決就行,這樣穩(wěn)扎穩(wěn)打的找方案就能解決了。
網(wǎng)站默認語言問題
一個使用Nextjs框架編寫的網(wǎng)站,支持中日英三種語言,如果訪問主頁面時未選擇語言,則按照瀏覽器的語言來選擇,這是合理的,一個人如果總用中文的瀏覽器,那么他在訪問一個新網(wǎng)站時較大可能是想看中文的頁面,所以我們優(yōu)先選擇當前瀏覽器的語言即可,默認跳轉(zhuǎn)到指定語言的頁面,選擇語言的代碼如下,是一個中間件 middleware.ts
,問題在于默認語言為日文的瀏覽器,打開網(wǎng)頁是英文的,這就得查查是因為什么了:
import { NextRequest, NextResponse } from 'next/server';
import acceptLanguage from 'accept-language';
import { fallbackLng, languages } from './app/i18n/settings';acceptLanguage.languages(languages);export const config = {// matcher: '/:lng*'matcher: ['/((?!api|_next/static|_next/image|images|svg|assets|favicon.ico|sw.js).*)']
};const cookieName = 'i18next';export function middleware(req: NextRequest) {let lng;// if (req.cookies.has(cookieName)) lng = acceptLanguage.get(req.cookies.get(cookieName)?.value);if (!lng) lng = acceptLanguage.get(req.headers.get('Accept-Language'));if (!lng) lng = fallbackLng;// Redirect if lng in path is not supportedif (!languages.some((loc) => req.nextUrl.pathname.startsWith(`/${loc}`))&& !req.nextUrl.pathname.startsWith('/_next')) {return NextResponse.redirect(new URL(`/${lng}${req.nextUrl.pathname}`, req.url));}if (req.headers.has('referer')) {const refererUrl = new URL(req.headers.get('referer') || 'zh');const lngInReferer = languages.find((l) => refererUrl.pathname.startsWith(`/${l}`));const response = NextResponse.next();if (lngInReferer) response.cookies.set(cookieName, lngInReferer);return response;}return NextResponse.next();
}
其中 matcher
是用來匹配路徑的,這個配置表示,中間件會在請求的路徑不包含特定字符串時觸發(fā)。也就是說,路徑不能包含指定的 api
、_next/static
等詞綴。
網(wǎng)站語言看這一句 if (!lng) lng = acceptLanguage.get(req.headers.get('Accept-Language'));
就行了,它的含義是網(wǎng)站可以根據(jù) Accept-Language 請求頭來檢測瀏覽器的首選語言,并返回相應語言的內(nèi)容。
而我將瀏覽器默認語言設置為日語時,打開網(wǎng)站傳遞的 Accept-Language
內(nèi)容為 ja,en;q=0.9,zh-CN;q=0.8,zh;q=0.7
根據(jù)你提供的 Accept-Language
內(nèi)容 ja,en;q=0.9,zh-CN;q=0.8,zh;q=0.7
,以下是中間件的處理過程:
acceptLanguage.get(req.headers.get('Accept-Language'))
函數(shù)會根據(jù) Accept-Language
頭部的內(nèi)容來選擇最適合的語言。根據(jù)我瀏覽器傳遞的內(nèi)容:
ja
(日語)有最高的優(yōu)先級。en
(英語)優(yōu)先級為 0.9。zh-CN
(簡體中文)優(yōu)先級為 0.8。zh
(中文)優(yōu)先級為 0.7。
由于 ja
的優(yōu)先級是 1(默認)并且是最優(yōu)的匹配,所以 acceptLanguage.get()
會選擇 ja
作為首選語言。
但是可以還取決于 languages
的值,因為 acceptLanguage
是通過 languages
完成初始化的,而我查詢了項目中它的值為 export const languages = ['jp', 'en', 'zh'];
,發(fā)現(xiàn)問題了沒有?日語瀏覽器將 ja
作為最優(yōu)先展示語言,但是備選項里沒有 ja
,所以最終選出的結(jié)果是 en
,這也就解釋了為什么日語瀏覽器默認打開網(wǎng)頁時顯示英文頁面的現(xiàn)象了。
日文的縮寫通常是 “ja”,而不是 “jp”。
- “ja” 是 ISO 639-1 標準中日語的語言代碼。
- “jp” 通常用來表示 日本(Japan)的國家代碼,在 ISO 3166-1 標準中使用。
因此,在國際化(i18n)和多語言網(wǎng)站的語言代碼中,日文通常使用 “ja”。
只要原因后就好修改了,改成ja也好,保持jp也罷,修正邏輯按照一致的順序處理,問題也就能解決了。
網(wǎng)站訪問統(tǒng)計問題
如果是一個網(wǎng)站開發(fā)者遇到這種問題,應該會有一個完整的解決方案,而我這種半吊子的網(wǎng)頁開發(fā)人員,只想盡快的解決問題,所以我的搜索方向就是怎么盡快解決這個問題。起初搜到的方案是使用 Vercel Analytics
來查看,初始有個免費額度,超過25,000 events要進行收費,因為我的網(wǎng)站就部署在 Vercel 上,所以這種方案應該是最融洽的,查看每月的 events 使用量估算了費用,每月要 $100 以上,糾結(jié)中。
然后就搜到了 Google Analytics
,介紹里說它完全免費,應用廣泛,但是最近評價卻不好,一方面是指責它收集隱私信息,另一方面是說它被很多瀏覽器插件屏蔽,導致無法準確統(tǒng)計,在抵制它的同時很多人都推薦使用了 Umami
。
Umami
是一個開源的簡單、隱私友好的網(wǎng)站分析工具。它提供了類似于 Google Analytics 的功能,但更加專注于數(shù)據(jù)隱私,且無需依賴第三方 cookies。這使得 Umami 成為那些希望追蹤用戶活動但又需要遵守嚴格隱私法律(如 GDPR 或 CCPA)的個人和企業(yè)的理想選擇。
Umami
是完全開源的(使用 MIT 許可證),代碼可以在 GitHub 上找到并自行部署。客戶端腳本文件僅約 2 KB,加載速度快,不會影響網(wǎng)頁性能。時查看訪問者活動,例如當前在線人數(shù)、瀏覽器、設備、地域等信息。
后端:Node.js 和 PostgreSQL。前端:基于 React 構(gòu)建。部署:支持 Docker,配置簡單。技術(shù)棧提起來挺簡單,但是像我這么懶的人現(xiàn)在還不打算配置一遍,自己配置還要買服務器和數(shù)據(jù)庫,因為我查到它有一個 Umami Cloud
。
Umami Cloud 是 Umami
的云托管服務,提供了一個簡單、隱私友好的網(wǎng)站分析工具的在線版本。它允許用戶通過 Umami 提供的 Web 界面,無需自行托管和管理服務器即可使用該分析工具。相比自己搭建 Umami,使用 Umami Cloud 可以節(jié)省大量的部署和維護成本,適合不想處理服務器配置的用戶。
用戶無需擔心部署和維護服務器,Umami Cloud 提供了一個即開即用的服務,只需要注冊并配置網(wǎng)站即可開始使用。與自托管的 Umami 一樣,Umami Cloud 注重用戶隱私,不收集個人可識別信息。它也不依賴 cookies 或第三方追蹤,因此完全符合 GDPR 和其他隱私法規(guī)。
用戶只需要將提供的 JavaScript 跟蹤代碼插入到網(wǎng)站頁面,不需要任何后端代碼,適合非技術(shù)用戶。Umami Cloud 提供了不同的定價套餐,包括免費和付費版本。免費版本適合小型網(wǎng)站或個人使用,付費版本提供更多的功能和數(shù)據(jù)存儲選項。
看起來數(shù)據(jù)大了還是得付錢,免費版本限制 100K events per month,Up to 3 websites,6 month data retention,對于我的網(wǎng)站來說還是不夠用,但付費的價格相比Vercel算是降了不少,所以我把它的 跟蹤代碼 胡亂的集成到了我項目的 <head>...</head>
中,進而引發(fā)了后面的問題
<script defer src="https://cloud.umami.is/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
Error: Empty components are self-closing
這個錯誤的完整顯示如下:
Failed to compile.
30:13 Error: Empty components are self-closing react/self-closing-comp
info - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/basic-features/eslint#disabling-rulesELIFECYCLE? Command failed with exit code 1.
Error: Command "pnpm run build" exited with 1
我的代碼開始寫成了這樣:
export default function RootLayout({children,params: { lng },
}: {children: React.ReactNode;params: { lng: LanguageType };
}) {return (<html lang={lng} className={myFont.variable}><head><script defer src="https://cloud.umami.is/script.js" data-website-id="YOUR_WEBSITE_ID"></script></head><body className="relative font-my">{children}</body></html>);
}
看著ChatGPT的解釋我陷入了沉思,不過后來我明白了它的意思,這個錯誤是由于 ESLint 中的 react/self-closing-comp
規(guī)則引起的,該規(guī)則要求空的組件標簽必須是自閉合的。
解決方法是檢查報錯所在的代碼(通常是在第 30 行第 13 列),很可能是你有一個空的元素,例如:
<div></div>
它應該改成自閉合的寫法:
<div />
所以我把代碼改成了這樣 <head><script defer src="https://cloud.umami.is/script.js" data-website-id="YOUR_WEBSITE_ID"/></head>
,去掉了 </script>
然后就報了下面這個錯。
Error: A space is required before closing bracket
完整錯誤如下:
Failed to compile.
30:120 Error: A space is required before closing bracket react/jsx-tag-spacing
info - Need to disable some ESLint rules? Learn more here: https://nextjs.org/docs/basic-features/eslint#disabling-rulesELIFECYCLE? Command failed with exit code 1.
Error: Command "pnpm run build" exited with 1
這次我還是沒反應過來,經(jīng)過ChatGPT解釋發(fā)現(xiàn),之前就已經(jīng)給出準備的例子了,這個新的錯誤是由 ESLint 的 react/jsx-tag-spacing 規(guī)則引起的,它要求在自閉合標簽的閉合括號前留一個空格。所以最終改成下面這樣就沒問題了
<head><script defer src="https://cloud.umami.is/script.js" data-website-id="YOUR_WEBSITE_ID" /></head>
真是一個空格也不能錯啊~
總結(jié)
- 網(wǎng)站的默認語言可以根據(jù)瀏覽器的設置語言來初始化,獲取代碼簡化為
acceptLanguage.get(req.headers.get('Accept-Language'));
- 網(wǎng)頁統(tǒng)計可以使用
Vercel Analytics
、Google Analytics
或者Umami
Vercel Analytics
與 Vercel 兼容性好,畢竟出自同一家班底,配合會比較順暢,應該還會有自家產(chǎn)品的關聯(lián)優(yōu)化Google Analytics
依賴 cookies,可能涉及隱私問題,數(shù)據(jù)存儲在 Google 的服務器,由 Google 管理,功能全面,適合復雜需求Umami
完全隱私友好,無 cookies,核心功能足夠,但比 Google Analytics 少,可以用戶自行托管,完全掌控
他日若是同淋雪,也算此生共白頭。在兩個人維系的關系中,一方的忍耐退讓并不會讓另一方生出善意,反而會導致對方以為之前的所有都是理所應當,進而變本加厲??倳袃蓚€人不在一個頻道上,你給她講理,她跟你講情,你跟她講情,她跟你講法,你跟她講法,他跟你講理,反正你永遠對不了~