@@ -57,6 +82,7 @@ const ResultContainer: FC<{
);
};
+
export const PingServerToBrowser: FC = () => {
const {
isPing,
@@ -71,52 +97,77 @@ export const PingServerToBrowser: FC = () => {
setIsPingServerToBrowser: s.setIsPingServerToBrowser,
})),
);
+
const refItemContainer = useRef(null);
- const refPingTimer = useRef(0);
+ const refPingTimer = useRef | null>(null);
+
const ServerTimeMultiplier = 1000;
const TimeoutTimerMs = 1000;
- const ScrollTimerMs = 100;
+
+ // 核心单次 Ping 请求
const ping = useCallback(async (): Promise => {
const start = Date.now();
- const { data, status } = await serverFetch(
- "ping",
- );
- if (data?.time && status === OK) {
- const { id, time } = data;
- const end = Date.now();
- const serverTime = time * ServerTimeMultiplier;
- addServerToBrowserPingItem({
- id,
- time: Math.floor(end - start - serverTime),
- });
- setTimeout(() => {
- if (!refItemContainer.current) {
- return;
- }
- const st = refItemContainer.current.scrollTop;
- const sh = refItemContainer.current.scrollHeight;
- if (st < sh) {
- refItemContainer.current.scrollTop = sh;
- }
- }, ScrollTimerMs);
+ try {
+ const { data, status } = await serverFetch(
+ "ping",
+ );
+ if (data?.time && status === OK) {
+ const { id, time } = data;
+ const end = Date.now();
+ const serverTime = time * ServerTimeMultiplier;
+
+ // 防御本地与服务端时钟不同步导致的负数问题
+ const calculatedTime = Math.max(
+ 0,
+ Math.floor(end - start - serverTime),
+ );
+
+ addServerToBrowserPingItem({
+ id,
+ time: calculatedTime,
+ });
+ }
+ } catch (error) {
+ console.error("Ping failed:", error);
}
}, [addServerToBrowserPingItem]);
- const pingLoop = useCallback(async (): Promise => {
- await ping();
- refPingTimer.current = window.setTimeout(async () => {
- await pingLoop();
- }, TimeoutTimerMs);
- }, [ping]);
- const handlePing = useCallback(async () => {
+
+ // 利用 useEffect 集中管理循环逻辑与定时器的销毁
+ useEffect(() => {
+ if (!isPingServerToBrowser) {
+ if (refPingTimer.current) {
+ clearTimeout(refPingTimer.current);
+ refPingTimer.current = null;
+ }
+ return;
+ }
+
+ const runLoop = async () => {
+ await ping();
+ // 只有在依然处于激活状态时才继续下一个定时
+ if (isPingServerToBrowser) {
+ refPingTimer.current = setTimeout(runLoop, TimeoutTimerMs);
+ }
+ };
+
+ runLoop();
+
+ // 组件卸载或状态变为不 Ping 时,严格执行垃圾清理
+ return () => {
+ if (refPingTimer.current) {
+ clearTimeout(refPingTimer.current);
+ }
+ };
+ }, [isPingServerToBrowser, ping]);
+
+ const handlePing = useCallback(() => {
if (isPing || isPingServerToBrowser) {
setIsPingServerToBrowser(false);
- clearTimeout(refPingTimer.current);
return;
}
setIsPingServerToBrowser(true);
- await pingLoop();
- }, [isPing, isPingServerToBrowser, pingLoop, setIsPingServerToBrowser]);
- // const count = serverToBrowserPingItems.length;
+ }, [isPing, isPingServerToBrowser, setIsPingServerToBrowser]);
+
return (
diff --git a/vite.config.dev.mjs b/vite.config.dev.mjs
index d0cc079..0b11211 100644
--- a/vite.config.dev.mjs
+++ b/vite.config.dev.mjs
@@ -11,19 +11,6 @@ export default defineConfig(({ mode }) => {
manifest: true,
outDir: "../dist",
target: "esnext",
- // rollupOptions: {
- // external: ['react', 'react-dom'],
- // output: {
- // globals: {
- // react: 'React',
- // 'react-dom': 'ReactDOM',
- // },
- // },
- // },
-
- // rollupOptions: {
- // input: new URL('./src/main.tsx', import.meta.url).pathname,
- // },
},
css: {
modules: {
diff --git a/vite.config.dist.mjs b/vite.config.dist.mjs
index e50b349..894c951 100644
--- a/vite.config.dist.mjs
+++ b/vite.config.dist.mjs
@@ -6,61 +6,29 @@ import { defineConfig } from "vite";
const __dirname = dirname(fileURLToPath(import.meta.url));
const tmpDir = resolve(__dirname, ".tmp");
-
if (!existsSync(tmpDir)) {
mkdirSync(tmpDir);
}
-
export default defineConfig({
build: {
emptyOutDir: true,
lib: {
- cssFileName: "app", // 如果想让生成的 css 叫 app.css,保留此项
+ cssFileName: "app",
entry: resolve(__dirname, "src/main.tsx"),
fileName: () => "app.js",
formats: ["umd"],
name: "app",
},
outDir: tmpDir,
- sourcemap: "hidden",
- target: "es2024",
- // 如果之后需要强制把所有 asset/css 改名,可以取消下方注释
- // rollupOptions: {
- // output: {
- // assetFileNames: (assetInfo) => {
- // if (assetInfo.name && assetInfo.name.endsWith('.css')) {
- // return 'app.css';
- // }
- // return '[name].[ext]';
- // }
- // }
- // }
},
-
- // 1. 核心 CSS 优化(适配 Vite 8.1 + 解决 lightningcss 的 :global 报错)
- css: {
- lightningcss: {
- // 👈 开启这个,lightningcss 就能完美识别并处理 :global 语法了
- cssModules: true,
- },
- minify: true, // Vite 8.x 推荐直接在这里开启 CSS 压缩
- transformer: "lightningcss",
- },
-
define: {
__DEV__: "false",
DEBUG: "false",
"process.env.NODE_ENV": JSON.stringify("production"),
"process.env.WEBPACK_ENV": JSON.stringify("production"),
},
-
- esbuild: {
- legalComments: "none",
- },
mode: "production",
-
plugins: [react()],
-
resolve: {
alias: {
"@": resolve(__dirname, "src/"),