Remix样式链接 #

一、样式链接概述 #

Remix 提供了 links 函数来管理样式表,支持按路由加载样式、预加载和并行加载。

二、links函数 #

2.1 基本用法 #

tsx
import type { LinksFunction } from "@remix-run/node";
import styles from "./styles.css?url";

export const links: LinksFunction = () => [
  { rel: "stylesheet", href: styles },
];

2.2 链接对象属性 #

tsx
export const links: LinksFunction = () => [
  {
    rel: "stylesheet",
    href: "/styles/main.css",
    media: "screen",
    title: "主样式",
  },
  {
    rel: "stylesheet",
    href: "/styles/print.css",
    media: "print",
  },
];

2.3 多个样式表 #

tsx
import type { LinksFunction } from "@remix-run/node";
import mainStyles from "~/styles/main.css?url";
import componentStyles from "./Component.css?url";

export const links: LinksFunction = () => [
  { rel: "stylesheet", href: mainStyles },
  { rel: "stylesheet", href: componentStyles },
];

三、按路由加载 #

3.1 路由级样式 #

每个路由可以有自己的样式:

tsx
// app/routes/admin.tsx
import type { LinksFunction } from "@remix-run/node";
import adminStyles from "~/styles/admin.css?url";

export const links: LinksFunction = () => [
  { rel: "stylesheet", href: adminStyles },
];

export default function AdminLayout() {
  return <Outlet />;
}

3.2 嵌套路由样式 #

样式会自动合并:

tsx
// app/routes/admin.tsx
export const links: LinksFunction = () => [
  { rel: "stylesheet", href: adminLayoutStyles },
];

// app/routes/admin.users.tsx
export const links: LinksFunction = () => [
  { rel: "stylesheet", href: usersPageStyles },
];

访问 /admin/users 时,两个样式表都会加载。

四、预加载样式 #

4.1 使用preload #

tsx
export const links: LinksFunction = () => [
  {
    rel: "preload",
    href: "/fonts/inter.woff2",
    as: "font",
    type: "font/woff2",
    crossOrigin: "anonymous",
  },
  {
    rel: "stylesheet",
    href: "/styles/main.css",
  },
];

4.2 字体预加载 #

tsx
export const links: LinksFunction = () => [
  {
    rel: "preload",
    href: "/fonts/inter-var.woff2",
    as: "font",
    type: "font/woff2",
    crossOrigin: "anonymous",
  },
];

五、条件样式 #

5.1 媒体查询 #

tsx
export const links: LinksFunction = () => [
  {
    rel: "stylesheet",
    href: "/styles/mobile.css",
    media: "(max-width: 768px)",
  },
  {
    rel: "stylesheet",
    href: "/styles/desktop.css",
    media: "(min-width: 769px)",
  },
];

5.2 打印样式 #

tsx
export const links: LinksFunction = () => [
  {
    rel: "stylesheet",
    href: "/styles/print.css",
    media: "print",
  },
];

六、图标和Favicon #

6.1 Favicon #

tsx
export const links: LinksFunction = () => [
  { rel: "icon", href: "/favicon.ico" },
  { rel: "apple-touch-icon", href: "/apple-touch-icon.png" },
];

6.2 多尺寸图标 #

tsx
export const links: LinksFunction = () => [
  { rel: "icon", type: "image/png", sizes: "32x32", href: "/favicon-32x32.png" },
  { rel: "icon", type: "image/png", sizes: "16x16", href: "/favicon-16x16.png" },
  { rel: "apple-touch-icon", sizes: "180x180", href: "/apple-touch-icon.png" },
];

七、RSS和替代链接 #

7.1 RSS订阅 #

tsx
export const links: LinksFunction = () => [
  {
    rel: "alternate",
    type: "application/rss+xml",
    title: "RSS Feed",
    href: "/rss.xml",
  },
];

7.2 多语言链接 #

tsx
export const links: LinksFunction = () => [
  { rel: "alternate", hrefLang: "en", href: "/en" },
  { rel: "alternate", hrefLang: "zh", href: "/zh" },
];

八、Links组件 #

8.1 在根组件中使用 #

tsx
import { Links, Meta, Outlet, Scripts } from "@remix-run/react";
import type { LinksFunction } from "@remix-run/node";

export const links: LinksFunction = () => [
  { rel: "stylesheet", href: "/styles/global.css" },
];

export default function App() {
  return (
    <html>
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <Outlet />
        <Scripts />
      </body>
    </html>
  );
}

8.2 Links函数的渲染 #

<Links /> 组件会渲染当前路由及其父路由的所有链接:

html
<link rel="stylesheet" href="/styles/global.css" />
<link rel="stylesheet" href="/styles/admin.css" />
<link rel="stylesheet" href="/styles/users.css" />

九、样式组织最佳实践 #

9.1 目录结构 #

text
app/
├── styles/
│   ├── global.css        # 全局样式
│   ├── variables.css     # CSS变量
│   └── components/       # 组件样式
│       ├── button.css
│       └── card.css
└── routes/
    ├── admin.css         # 路由样式
    └── admin.users.css

9.2 全局样式 #

在根组件加载全局样式:

tsx
import type { LinksFunction } from "@remix-run/node";
import globalStyles from "~/styles/global.css?url";
import variables from "~/styles/variables.css?url";

export const links: LinksFunction = () => [
  { rel: "stylesheet", href: variables },
  { rel: "stylesheet", href: globalStyles },
];

9.3 组件样式 #

tsx
import type { LinksFunction } from "@remix-run/node";
import styles from "./Button.css?url";

export const links: LinksFunction = () => [
  { rel: "stylesheet", href: styles },
];

export function Button() {
  return <button className="button">点击</button>;
}

十、性能优化 #

10.1 避免重复加载 #

tsx
// 使用相同的href,只会加载一次
export const links: LinksFunction = () => [
  { rel: "stylesheet", href: "/styles/shared.css" },
];

10.2 合理使用预加载 #

tsx
export const links: LinksFunction = () => [
  // 预加载关键字体
  {
    rel: "preload",
    href: "/fonts/inter.woff2",
    as: "font",
    type: "font/woff2",
    crossOrigin: "anonymous",
  },
  // 样式表
  { rel: "stylesheet", href: "/styles/main.css" },
];

十一、总结 #

本章我们学习了:

  1. links函数:定义样式链接
  2. 按路由加载:每个路由独立样式
  3. 预加载:优化关键资源加载
  4. 条件样式:媒体查询和打印样式
  5. 最佳实践:样式组织和性能优化

核心要点:

  • 使用 links 函数管理样式
  • 按路由加载样式减少初始加载
  • 预加载关键资源
  • 合理组织样式文件
最后更新:2026-03-28