静态产物背后没有服务器,这些文件里错了什么,对每一个访客就都是错的。下面这些 React2Static 会拿你自己的产物全跑一遍。这里是完整清单,每条都附修法。
下面示例里的包名、路径和数值都只是举例,工作台填进去的是你自己项目里的那个。
你看到的是
dist/
.env
index.html
assets/index-a3f1c2.js整个文件任何访客都能直接下载。先把里面的每一个值都轮换掉,再把 .env 移出构建会原样拷贝的那个目录(通常是 public/)。
你看到的是
const apiKey = process.env.API_KEY;
fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
// Vite turns process.env into {} — the header goes out as
// "Bearer undefined" and the API answers 401. No error in the console.Vite 会把 process.env 整个替换成空对象,所以这个值在浏览器里就是 undefined——不报错,也没有任何提示,请求照发,只是没带上这个值,然后接口回你一个 401。改成用 import.meta.env.VITE_xxx 读,或者在 vite.config 里 define 它。
改成
const apiKey = import.meta.env.VITE_API_KEY;你看到的是
Uncaught ReferenceError: process is not defined
at index-a3f1c2.js:1:2043浏览器里没有 process 这个对象,代码跑到这行就会报错,通常表现为整页白屏。在 Vite 里,浏览器要用的值必须通过 import.meta.env 读,而且变量名要以 VITE_ 开头。
改成
const apiKey = import.meta.env.VITE_API_KEY;你看到的是
const API = "http://localhost:3000/api";里面有 http://localhost:3000/api。这个地址只在构建这台机器上存在,所有访客的这个请求都会失败。改成一个公网地址。
改成
const API = "https://api.example.com";你看到的是
dist/
assets/index-a3f1c2.js
assets/index-9b2e01.css静态托管把 index.html 当入口页。没有它,访客看到的是文件列表或者 404。确认一下你的构建到底输出了什么。
你看到的是
<title>Vite + React + TS</title>现在是"Vite + React + TS"。搜索结果和别人分享出去的链接显示的就是这行字。到 index.html 里改掉。
改成
<title>Your product name — what it does, in one line</title>浏览器标签页和所有搜索结果用的都是 <title> 标签。在 index.html 里补一个。
改成
<title>Your product name — what it does, in one line</title>搜索引擎只能自己从页面里抓一段来凑。<meta name="description"> 里那一句话,直接决定别人点不点进来。
改成
<meta name="description" content="One clear sentence about what this page is for." />手机会按桌面宽度渲染再缩小,结果就是所有字都小得看不清。在 index.html 里加上 <meta name="viewport" content="width=device-width, initial-scale=1">。
改成
<meta name="viewport" content="width=device-width, initial-scale=1" />分享到聊天软件或社交平台时,只会显示一条光秃秃的网址,没有标题也没有配图。补上 og:title、og:description 和 og:image。
改成
<meta property="og:title" content="Your product name" />
<meta property="og:description" content="One clear sentence." />
<meta property="og:image" content="https://example.com/og.png" />你看到的是
<link rel="icon" type="image/svg+xml" href="/vite.svg" />浏览器标签页和收藏夹里显示的是一张白纸,或者你从模板里继承下来的那个图标。放一个自己的 favicon,并在 index.html 里引用。
改成
<link rel="icon" href="/favicon.ico" sizes="any" />读屏软件靠它决定怎么念,浏览器靠它决定要不要提示翻译。加上 lang="zh",或者页面实际用的语言。
改成
<html lang="en">没有它爬虫照样会收录,但 robots.txt 是你告诉它们 sitemap 在哪的地方。可以在"上线"那一步让我们补上。
改成
User-agent: *
Allow: /
Sitemap: https://example.com/sitemap.xml你看到的是
dist/assets/index-a3f1c2.js 2,418.55 kB │ gzip: 731.20 kB
(!) Some chunks are larger than 500 kB after minification.手机网络下这就是好几秒的白屏。用动态 import() 把重的部分拆出去,首屏通常能降下来一大截。
改成
const Editor = lazy(() => import('./Editor'));你看到的是
dist/assets/hero-8f2a1b.png 4,102.11 kB大图和大字体会拖住首屏渲染。把图片转成 WebP、按实际显示尺寸缩小,通常能去掉大部分体积。