mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-12 23:33:43 +08:00
fix: disable Vercel analytics outside Vercel
This commit is contained in:
@@ -765,7 +765,7 @@ ALLOW_LAN_ACCESS=true LAN_ALLOWED_DEV_ORIGINS="kvideo.lan,192.168.50.10" npm run
|
|||||||
|
|
||||||
- **ESLint 10**:代码质量检查
|
- **ESLint 10**:代码质量检查
|
||||||
- **PostCSS 8**:CSS 处理器
|
- **PostCSS 8**:CSS 处理器
|
||||||
- **Vercel Analytics**:性能监控和分析
|
- **Vercel Analytics**:仅在 Vercel 部署中启用的性能监控和分析
|
||||||
- **Cloudflare Pages**:边缘部署支持
|
- **Cloudflare Pages**:边缘部署支持
|
||||||
|
|
||||||
### 架构特点
|
### 架构特点
|
||||||
|
|||||||
+11
-1
@@ -4,8 +4,18 @@
|
|||||||
"name": "KVideo",
|
"name": "KVideo",
|
||||||
"branch": "main"
|
"branch": "main"
|
||||||
},
|
},
|
||||||
"currentVersion": "4.9.4",
|
"currentVersion": "4.9.5",
|
||||||
"releases": [
|
"releases": [
|
||||||
|
{
|
||||||
|
"version": "4.9.5",
|
||||||
|
"publishedAt": "2026-07-09",
|
||||||
|
"title": "修复 Docker 登录页 Analytics 404",
|
||||||
|
"notes": [
|
||||||
|
"Vercel Analytics 现在只会在真实 Vercel 部署中注入,Docker、自托管和 Cloudflare Pages 不再请求 /_vercel/insights/script.js。",
|
||||||
|
"Cloudflare 部署环境判定优先于 Vercel 风格环境变量,避免适配器环境被误判为 Vercel。",
|
||||||
|
"新增部署环境单元测试,覆盖自托管、Vercel、Cloudflare 和混合环境变量场景。"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "4.9.4",
|
"version": "4.9.4",
|
||||||
"publishedAt": "2026-07-08",
|
"publishedAt": "2026-07-08",
|
||||||
|
|||||||
+3
-1
@@ -16,6 +16,7 @@ import { ScrollPositionManager } from "@/components/ScrollPositionManager";
|
|||||||
import { LocaleProvider } from "@/components/LocaleProvider";
|
import { LocaleProvider } from "@/components/LocaleProvider";
|
||||||
import { RuntimeFeaturesProvider } from "@/components/RuntimeFeaturesProvider";
|
import { RuntimeFeaturesProvider } from "@/components/RuntimeFeaturesProvider";
|
||||||
import { VideoTogetherController } from '@/components/VideoTogetherController';
|
import { VideoTogetherController } from '@/components/VideoTogetherController';
|
||||||
|
import { shouldEnableVercelAnalytics } from '@/lib/config/deployment';
|
||||||
import { getRuntimeFeatures } from "@/lib/server/runtime-features";
|
import { getRuntimeFeatures } from "@/lib/server/runtime-features";
|
||||||
import { resolveSiteIconSrc } from '@/lib/server/site-icon';
|
import { resolveSiteIconSrc } from '@/lib/server/site-icon';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
@@ -86,6 +87,7 @@ export default async function RootLayout({
|
|||||||
process.env.VIDEOTOGETHER_SCRIPT_URL?.trim() || DEFAULT_VIDEOTOGETHER_SCRIPT_URL;
|
process.env.VIDEOTOGETHER_SCRIPT_URL?.trim() || DEFAULT_VIDEOTOGETHER_SCRIPT_URL;
|
||||||
const videoTogetherSettingUrl = process.env.VIDEOTOGETHER_SETTING_URL?.trim();
|
const videoTogetherSettingUrl = process.env.VIDEOTOGETHER_SETTING_URL?.trim();
|
||||||
const videoTogetherEnvEnabled = process.env.VIDEOTOGETHER_ENABLED !== 'false';
|
const videoTogetherEnvEnabled = process.env.VIDEOTOGETHER_ENABLED !== 'false';
|
||||||
|
const vercelAnalyticsEnabled = shouldEnableVercelAnalytics();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang="zh-CN" suppressHydrationWarning>
|
<html lang="zh-CN" suppressHydrationWarning>
|
||||||
@@ -136,7 +138,7 @@ export default async function RootLayout({
|
|||||||
<ScrollPositionManager />
|
<ScrollPositionManager />
|
||||||
</PasswordGate>
|
</PasswordGate>
|
||||||
</TVProvider>
|
</TVProvider>
|
||||||
<Analytics />
|
{vercelAnalyticsEnabled ? <Analytics /> : null}
|
||||||
<ServiceWorkerRegister />
|
<ServiceWorkerRegister />
|
||||||
</RuntimeFeaturesProvider>
|
</RuntimeFeaturesProvider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
type EnvLike = Record<string, string | undefined>;
|
||||||
|
|
||||||
|
export function isVercelDeployment(env: EnvLike = process.env): boolean {
|
||||||
|
return env.VERCEL === '1' || Boolean(env.VERCEL_ENV);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isCloudflareDeployment(env: EnvLike = process.env): boolean {
|
||||||
|
return (
|
||||||
|
env.CF_PAGES === '1' ||
|
||||||
|
Boolean(env.CF_PAGES_URL) ||
|
||||||
|
Boolean(env.CLOUDFLARE_ACCOUNT_ID) ||
|
||||||
|
Boolean(env.CF_ACCOUNT_ID) ||
|
||||||
|
Boolean(env.WORKERS_CI)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function shouldEnableVercelAnalytics(env: EnvLike = process.env): boolean {
|
||||||
|
return isVercelDeployment(env) && !isCloudflareDeployment(env);
|
||||||
|
}
|
||||||
@@ -1,20 +1,7 @@
|
|||||||
import 'server-only';
|
import 'server-only';
|
||||||
|
|
||||||
import type { RuntimeFeatures } from '@/lib/config/runtime-features';
|
import type { RuntimeFeatures } from '@/lib/config/runtime-features';
|
||||||
|
import { isCloudflareDeployment, isVercelDeployment } from '@/lib/config/deployment';
|
||||||
function isVercelDeployment(): boolean {
|
|
||||||
return process.env.VERCEL === '1' || Boolean(process.env.VERCEL_ENV);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isCloudflareDeployment(): boolean {
|
|
||||||
return (
|
|
||||||
process.env.CF_PAGES === '1' ||
|
|
||||||
Boolean(process.env.CF_PAGES_URL) ||
|
|
||||||
Boolean(process.env.CLOUDFLARE_ACCOUNT_ID) ||
|
|
||||||
Boolean(process.env.CF_ACCOUNT_ID) ||
|
|
||||||
Boolean(process.env.WORKERS_CI)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRestrictedFeatures(
|
function getRestrictedFeatures(
|
||||||
deploymentProvider: RuntimeFeatures['deploymentProvider'],
|
deploymentProvider: RuntimeFeatures['deploymentProvider'],
|
||||||
@@ -31,14 +18,14 @@ function getRestrictedFeatures(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getRuntimeFeatures(): RuntimeFeatures {
|
export function getRuntimeFeatures(): RuntimeFeatures {
|
||||||
if (isVercelDeployment()) {
|
|
||||||
return getRestrictedFeatures('vercel', 'Vercel');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCloudflareDeployment()) {
|
if (isCloudflareDeployment()) {
|
||||||
return getRestrictedFeatures('cloudflare', 'Cloudflare');
|
return getRestrictedFeatures('cloudflare', 'Cloudflare');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isVercelDeployment()) {
|
||||||
|
return getRestrictedFeatures('vercel', 'Vercel');
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
deploymentProvider: 'self-hosted',
|
deploymentProvider: 'self-hosted',
|
||||||
deploymentProviderLabel: '自托管',
|
deploymentProviderLabel: '自托管',
|
||||||
@@ -48,4 +35,3 @@ export function getRuntimeFeatures(): RuntimeFeatures {
|
|||||||
restrictionSummary: null,
|
restrictionSummary: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "kvideo",
|
"name": "kvideo",
|
||||||
"version": "4.9.4",
|
"version": "4.9.5",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "kvideo",
|
"name": "kvideo",
|
||||||
"version": "4.9.4",
|
"version": "4.9.5",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.3.1",
|
||||||
"@dnd-kit/sortable": "^10.0.0",
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "kvideo",
|
"name": "kvideo",
|
||||||
"version": "4.9.4",
|
"version": "4.9.5",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node scripts/next-with-lan-access.mjs dev",
|
"dev": "node scripts/next-with-lan-access.mjs dev",
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import test from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
|
||||||
|
import {
|
||||||
|
isCloudflareDeployment,
|
||||||
|
isVercelDeployment,
|
||||||
|
shouldEnableVercelAnalytics,
|
||||||
|
} from '@/lib/config/deployment';
|
||||||
|
|
||||||
|
test('self-hosted deployments do not enable Vercel Analytics', () => {
|
||||||
|
const env = {};
|
||||||
|
|
||||||
|
assert.equal(isVercelDeployment(env), false);
|
||||||
|
assert.equal(isCloudflareDeployment(env), false);
|
||||||
|
assert.equal(shouldEnableVercelAnalytics(env), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Vercel deployments enable Vercel Analytics', () => {
|
||||||
|
assert.equal(shouldEnableVercelAnalytics({ VERCEL: '1' }), true);
|
||||||
|
assert.equal(shouldEnableVercelAnalytics({ VERCEL_ENV: 'production' }), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Cloudflare deployments do not enable Vercel Analytics', () => {
|
||||||
|
assert.equal(shouldEnableVercelAnalytics({ CF_PAGES: '1' }), false);
|
||||||
|
assert.equal(shouldEnableVercelAnalytics({ CF_PAGES_URL: 'https://kvideo.pages.dev' }), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Cloudflare wins when adapter environments expose Vercel-like variables', () => {
|
||||||
|
const env = {
|
||||||
|
VERCEL: '1',
|
||||||
|
VERCEL_ENV: 'production',
|
||||||
|
CF_PAGES: '1',
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.equal(isVercelDeployment(env), true);
|
||||||
|
assert.equal(isCloudflareDeployment(env), true);
|
||||||
|
assert.equal(shouldEnableVercelAnalytics(env), false);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user