@fluid-app/sites

中文文档
0.1.167发布于 2026/11/15UNLICENSEDTypeScriptES Module零依赖近 30 天下载 2.9万

成员-站点浏览器 SDK:站点自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自自自自自自自自自自自自来自自自自来自自自自自自自来自自自自自自自自自自自自自自来自自自自自自自自自自自自来自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自

中文使用文档
文档目录15 节
  1. 安装
  2. 无构建步骤: 脚本标记
  3. SDK这个
  4. fluid.auth : 谁在这里
  5. fluid.api : 作为访客的流体API
  6. fluid.db : 网站自己的数据库
  7. fluid.fn : 网站的服务器功能
  8. fluid.cart : 店面的推车
  9. fluid.history : 返回并转发单页应用程序
  10. fluid.storefront : 保持股票持有人信用的链接
  11. 地方发展: fluid sites dev
  12. 师曰: @fluid-app/sites/vite
  13. 选项
  14. 流体DAM中的媒体
  15. 错误

@fluid-app/网站

用于Fluid上托管站点的浏览器 SDK. 它给一页 fluid.auth, (中文(简体) ), fluid.api, (中文(简体) ), fluid.db, (中文(简体) ), fluid.fn, (中文(简体) ), fluid.cart, (中文(简体) ), fluid.history 财务报告和审定财务报表 fluid.storefront每通电话都来自该网站 /_fluid/, (中文(简体) ), 因此页面不需要 API 密钥, 也没有 CORS 设置 : Fluid 知道访问者是谁 以及他们在哪个地点.

还有船 fluidSite() (单位:千美元)@fluid-app/sites/vite),一个制作 一个可以被搜索引擎找到的网站,链接预览和代理.

全体导游现场直播 页面存档备份,存于互联网档案馆 docs.fluid.app数字 :

安装

npm install @fluid-app/sites
import { fluid } from "@fluid-app/sites";

正在导入套件 window.fluid,合并为任意 window.fluid 已经在页面上.

无构建步骤: 脚本标记

每个公布的网站都服务于相同的SDK /_fluid/sdk/v1/sites.js,所以一个 纯 HTML 页面无需 npm 或 捆绑器即可使用 :

<script type="module">
  import { fluid } from "/_fluid/sdk/v1/sites.js";

  const me = await fluid.auth.me();
  document.querySelector("#hello").textContent = me.viewer
    ? `Hi, ${me.viewer.name}`
    : "Hi there";
</script>

fluid sites dev 下次为同一文件服务 fluid sites CLI 发布 舰只 在此之前,脚本标记只在已出版的网站上工作.

SDK这个

fluid.auth: 谁在这里

const me = await fluid.auth.me();
// me.viewer: { userId, name, ... } or null for a signed-out visitor
// me.site:   { id, handle, name, visibility, companyName }

if (!me.viewer) fluid.auth.signIn({ returnTo: "/rsvp" });
// Open the Passport (the account menu), such as from your own account button.
// signOut() sends the same request: the visitor signs out from the Passport.
else fluid.auth.openPassport();

fluid.api: 作为访客的流体API

fluid.api 调用成员 API(/api/member/v2026-10/...)作为签入者 仅限访问者进入现场.

const orders = await fluid.api.get("/orders", { "page[limit]": "10" });

const res = await fluid.api.fetch("/orders?page[limit]=10");
if (res.status === 401) fluid.auth.signIn();

get 掷出 FluidRequestError (与 status 财务报告和审定财务报表 code,例如403 scope_not_granted在非-2xx的回答. fetch 返回当前响应.

fluid.db: 网站自己的数据库

表格及其准入规则来自 db/schema.json,与 建设。 被读作Supabase的查询和决心 { data, error, count }。 。 。 .

await fluid.db.from("rsvps").insert({ event_id: eventId, guests: 2 });

const { data, error } = await fluid.db
  .from("rsvps")
  .select("name,guests")
  .eq("event_id", eventId)
  .order("created_at", { ascending: false })
  .limit(20);

每一行都有过 id, (中文(简体) ), created_by, (中文(简体) ), created_at 财务报告和审定财务报表 updated_at。 。 。 .

fluid.fn: 网站的服务器功能

const res = await fluid.fn.fetch("rsvp", {
  method: "POST",
  body: JSON.stringify({ eventId }),
});

一个函数在 /api/<name> 财务报告和审定财务报表 /api/<name>/<sub-path> 编辑 原产地,所以 fluid.fn.fetch("orders/123?full=1") 电话 /api/orders/123?full=1 作为取景者. 一个平地 fetch("/api/rsvp") 达到 同样的功能,没有观众的标志。 服务器或其他站点呼叫 a 一个 access: "key" 函数为 Authorization: Bearer fsk_…,一个网站API 键。 声明函数的捆绑可能没有文件 /api/。 。 。 .

fluid.cart: 店面的推车

在商店前门内展示的一个站点上,推车是商店前门自己的推车. 争吵是公平分享SDK的.

await fluid.cart.add([{ variant_id: 501, quantity: 1 }]);
const stop = fluid.cart.onChange((cart) => render(cart));
fluid.cart.open();
fluid.cart.checkout();

带有 FairShare 属性的按钮, 例如 data-fluid-add-to-cart,工作内容 也没有剧本 在一个没有店面的页面上,推车呼叫拒绝.

店面画出FairShare的浮式推车按钮并引出抓取泡沫 在现场的下角。 拥有自己的推车按钮的站点可以藏起来 config/shell.json数字 :

{ "fairshare": "hidden" }

惟有出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出入出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出入出出出出出出出出出出出出出出出出出出出入出出出出出出出出出出出出出出出出出出出出出出入出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出入出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出出 FairShare 仍然负载,所以 fluid.cart, (中文(简体) ), fluid.cart.open(),退出和股权者的信用工作如前.

fluid.history: 返回并转发单页应用程序

在店面内部,地址栏属于店面. 让你 路由器跟着它:

fluid.history.onGo((path, hash) => router.navigate(path + (hash ?? "")));

散列路由器不需要更多内容:碎片中的路由(#/deals/42 或者说 #!/deals/42)在店面的地址栏显示,一个链接打开了该视图,而后, 向前再装一发回. SDK 将框架移动到另一个路径 与 replaceState,然后开火 popstate 财务报告和审定财务报表 hashchange作为碎片 导航会.

路由显示在店面的地址栏和历史, 所以不要放 散列路线的证书( e)#/oauth?access_token=…) (中文(简体) ). 碎片不是 散列路线,例如 #access_token=…,留在框内.

const shop = await fluid.storefront.url("/shop");
// "https://yoli.com/janedoe/shop"

地方发展: fluid sites dev

fluid sites dev 以自己的数据库运行您的机器上的站点, 所以 fluid.db 工作之前,你出版 从来没有触及现场的行.

npm install -g @fluid-app/fluid-cli @fluid-app/fluid-cli-member-site
fluid sites dev                  # http://127.0.0.1:9500
fluid sites dev --viewer guest   # browse as a signed-out visitor
fluid sites dev --reset-db       # start from an empty database
  • 它运行文件夹的 dev 脚本( 或服务) dist/ 当没有的时候 答题 /_fluid/db 从 .fluid/dev.sqlite,有相同的支票和表格 规则现场适用。 它又说 .fluid/ 改为 .gitignore。下一次 fluid sites CLI释放船,它也服务于 /_fluid/sdk/v1/sites.js。 。 。 .
  • 保存 db/schema.json 立即更新本地数据库。 改变 丢弃数据等待您确认.
  • 默认你是一个代理老板, local-owner,所以行 你写带 那个 created_by。 。 。 . /_fluid/api 现在回答503.

师曰: @fluid-app/sites/vite

一个网站是一个单页的应用程序,所以一个不运行 JavaScript 的爬行者看到一个 空页. fluidSite() 运行后 vite build 写作一个爬行者 从 config/meta.json数字 :

// vite.config.ts
import react from "@vitejs/plugin-react";
import { fluidSite } from "@fluid-app/sites/vite";
import { defineConfig } from "vite";

export default defineConfig({
  plugins: [react(), fluidSite()],
});
// config/meta.json
{
  "default": {
    "title": "Diamond Leaders",
    "description": "Events and training for the Diamond Leaders team.",
    "image": "/og.png"
  },
  "url": "https://shop.example.com/home/sites/diamond-leaders",
  "twitter": { "site": "@fluid" },
  "routes": ["/events", "/drafts"],
  "routeMeta": {
    "/events": { "title": "Events", "description": "What's on." },
    "/drafts": { "noindex": true }
  }
}

它写在构建输出中的内容 :

  • 头牌 内 index.html数字 : <title>, (中文(简体) ), description, (中文(简体) ), og:title, (中文(简体) ), og:description, (中文(简体) ), og:image, (中文(简体) ), og:type, (中文(简体) ), og:url 财务报告和审定财务报表 twitter:card (单位:千美元)twitter:site 财务报告和审定财务报表 twitter:creator (设定时). meta.json标题 替换页面 <title>; 页面中的其他标签已保留 . 每个网页都有绝对的地址 <link rel="canonical">;没有一条,门户的 Link 头为取名.
  • 一个 index.html 每条路线 (单位:千美元)/events → events/index.html),用这个 路由头标。 网关服务于路径的自身文件 单页应用程序倒置。 路由的标题、描述和图像来自 routeMeta[path],则 pages[path],则 default。路线来自 routes附加时 任何纯度 path: "/…" 文字单位 src/router.ts(x) 或者说 src/routes.ts(x)· ; meta.json 赢了.
  • 页面内容: 与 prerender,每页的 HTML 都会在根内 元素; 没有它, 每页都得到一个 <noscript> 标题及 说明.
  • sitemap.xml (以下有网址)和 llms.txt 列名 主页和每条路线. 两者都单独存在 public/ 自己开的船.

一条路 routeMeta 标记 noindex 获得其 HTML 文件,使用 <meta name="robots" content="noindex">,没有其他: sitemap.xml 财务报告和审定财务报表 llms.txt,以及 fluid sites publish 把它从 清单 routes,这是网关自己的 sitemap.xml 财务报告和审定财务报表 llms.txt 列表中选择一个选项.

网站地址必须是绝对的 http(s) URL,没有用户名,密码, 查询或碎片meta.json url 必须是https);任何其他 siteUrl 实值 被忽略 。 没有一个人, llms.txt 财务报告和审定财务报表 og:url 将路径拖入 /,没有 sitemap.xml 写入: 站点映射需要 绝对地址, 插件从不写亲属 <loc>。 。 。 .

网站网关服务 sitemap.xml 财务报告和审定财务报表 llms.txt 仅用于可索引 网站:一个在SEO环境中启用索引的现场公共公司网站, 也没有公司或主题设置 阻碍索引。 新站点开始 索引关闭。 会员自己的网站,分会和私人网站从不 可指数化. 其它任何网站都不提供文件 连捆绑都不行 一个 可索引网站为捆绑自己的文件服务, 不变( set) url 联 合 国 建筑 sitemap.xml一个独立的人,没有一个人能创造他们 清单 meta.routes。 。 。 .

每一个成员 meta.json 是可选的, {} 包含。 一个名字 替换页本身 <title>,例如模板的: default.title 编辑 网页,以及 routeMeta[path].title (那时) pages[path],则 default在一个 路由的页面; 相接的字段倒回同样的方式。 没有标题, 页面 自己留着吧 <title>,以及 llms.txt 以主页命名。 打开 仓库前部,壳头取出每个字段 routeMeta编号 :pages 联 合 国 准确路径,然后是网站的 SIO 设置(管理员或 API),然后是 default离开吧 default 让SEO设置决定. 其他标签跟随该页面:主页和该架构自己写的任意一页 保持他们自己的 description,打开图和Twitter标签. 一个路线的页面 由主页创建 index.html 在主页上贴上路由的标签 永远不要保留家 页面 robots 或犬科动物。 路线是一页 不论有无后行斜线 以及作为建筑文件的路线 (例如: /feed.xml 从 public/) 保留那个文件.

选项

选项默认它会做什么
siteUrlmeta.json url网站的公开地址,其中 sitemap.xml, (中文(简体) ), llms.txt, (中文(简体) ), og:url 财务报告和审定财务报表 og:image 从
prerender无导出模块 render(path): string | Promise<string>,用Vite的 SSR 建造
rootId"root"空元素的前置 HTML 的 ID 进入
routersrc/router.ts(x),则 src/routes.ts(x)路由器文件为普通路径读取,或 false 无
metaconfig/meta.json地点的元是
media打开下面的媒体步骤; { manifest } 说出另外一份清单, false 关掉

React 站点的前置条目 :

// src/prerender.tsx
import { renderToString } from "react-dom/server";

import { App } from "./App";

export function render(path: string): string {
  return renderToString(<App path={path} />);
}
fluidSite({ prerender: "./src/prerender.tsx" });

A 类 meta.json 合同拒绝失败 建设, 与字段命名. fluid sites lint 警告没有产权或说明的公司网站,或 没有路线 也没有退路.

流体DAM中的媒体

图像、视频、音频和大字体属于公司的流体DAM,而不是 捆绑:DAM的CDN为它们服务,应要求调整图像大小,以及 捆绑不小 放进去 public/media/ 并依他们 路径,如您想要任何公开文件:

<video src="/media/hero.mp4" autoplay muted loop playsinline></video>
<img src="/media/team.jpg?tr=w-800" alt="The team" />

fluid sites media sync (管理员登录; fluid deploy 运行它之前 build)上传每个新文件或已更改文件到 DAM,并记录其 CDN 地址和SHA-256在 config/media.json。提交该文件:文件 字节不变,再也不上传.

建成后, fluidSite() 点出每条记录文件的引用 其CDN地址,保留任何查询(?tr=w-800 是一个DAM变换),并且 离开文件 dist然后警告每个视频或音频文件, 和每个超过256 KiB的图像或字体,仍在构建中。 小图标和 SVG 留在捆绑.

成员登录尚不能上传到公司的DAM,所以成员的网站 保持媒体的捆绑 与警告.

DAM媒体通过URL公开,无论网站的能见度如何. 一个CDN 地址为任何有地址的人工作,没有网站的观众检查 在某人进入私人网站被取消后继续工作。 仅a 检查后面的捆绑文件 任何必须保存的东西 在捆绑中保持隐私( 外部) public/media/),或出站.

错误

  • FluidRequestError(单位:千美元) /_fluid/* 路由以非状态响应 2xx (英语). 它已经 status, (中文(简体) ), code 财务报告和审定财务报表 body。 。 。 .
  • NotSupportedError(单位:千美元) fluid.db 方法.

版本与发布记录

@fluid-app/sites 共发布 169 个版本,首次发布于 2026/11/07;过去 12 个月发布了 169 个版本。

版本发布日期距今
0.1.167latest2026/11/15今天
0.1.1662026/11/15今天
0.1.1652026/11/15今天
0.1.1642026/11/15今天
0.1.1632026/11/15今天
0.1.1622026/11/151 天前

关于 @fluid-app/sites 的常见问题

@fluid-app/sites 是什么?

成员-站点浏览器 SDK:站点自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自来自自自自自自自自自自自自来自自自自来自自自自自自自来自自自自自自自自自自自自自自来自自自自自自自自自自自自来自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自自

如何安装 @fluid-app/sites?

在项目目录运行 npm install @fluid-app/sites,或使用 pnpm add / yarn add / bun add。

@fluid-app/sites 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@fluid-app/sites 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@fluid-app/sites 可以商用吗?

@fluid-app/sites 使用 UNLICENSED 许可。作者声明为 UNLICENSED,即不授予公开使用许可(与公共领域的 Unlicense 不同)。使用前需获得作者授权。以上为概括,不构成法律意见,请以许可原文为准。

@fluid-app/sites 的下载量有多少?

根据 npm 官方下载统计,@fluid-app/sites 在 2026/10/15 – 2026/11/13 这 30 天内被下载 29,350 次,日均约 978 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@fluid-app/sites 还在维护吗?

最新版本 0.1.167 发布于 2026/11/15(今天);至今共发布 169 个版本,其中过去 12 个月发布了 169 个;首次发布于 2026/11/07。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。