Sapper 中有两种类型的路由——页面路由和服务器路由。

页面

页面,也就是以 .svelte 文件形式编写的 Svelte 组件。当用户首次访问应用程序时,他们会进入到由服务端渲染的路由,其中包含一些“混合”了页面并能初始化客户端路由的 JavaScript 代码。此后,访问其他页面的操作都是完全由客户端进行处理,为用户带来快速、高性能的体验。

路由是由文件名决定的。例如, src/routes/index.svelte 是网站的根路由:

  1. <!-- src/routes/index.svelte -->
  2. <svelte:head>
  3. <title>Welcome</title>
  4. </svelte:head>
  5. <h1>Hello and welcome to my site!</h1>

命名为 src/routes/about.sveltesrc/routes/about/index.svelte 都指向 /about 路由:

  1. <!-- src/routes/about.svelte -->
  2. <svelte:head>
  3. <title>About</title>
  4. </svelte:head>
  5. <h1>About this site</h1>
  6. <p>TODO...</p>

动态参数均使用 [方括号] 进行转码。例如,创建一个渲染博客文章的页面:

  1. <!-- src/routes/blog/[slug].svelte -->
  2. <script context="module">
  3. // the (optional) preload function takes a
  4. // `{ path, params, query }` object and turns it into
  5. // the data we need to render the page
  6. export async function preload(page, session) {
  7. // the `slug` parameter is available because this file
  8. // is called [slug].svelte
  9. const { slug } = page.params;
  10. // `this.fetch` is a wrapper around `fetch` that allows
  11. // you to make credentialled requests on both
  12. // server and client
  13. const res = await this.fetch(`blog/${slug}.json`);
  14. const article = await res.json();
  15. return { article };
  16. }
  17. </script>
  18. <script>
  19. export let article;
  20. </script>
  21. <svelte:head>
  22. <title>{article.title}</title>
  23. </svelte:head>
  24. <h1>{article.title}</h1>
  25. <div class='content'>
  26. {@html article.html}
  27. </div>

查阅 预加载 了解更多关于 preloadthis.fetch 的信息。

服务器路由

服务器路由是 .js 文件类型的模块,它可以导出指向 HTTP 方法的函数。每个函数接收 HTTP 请求想要 对象作为参数,以及一个 next 函数。这对于创建 JSON API 是非常有用的。例如,如何创建一个为前文例子提供博客文章的端点:

  1. // routes/blog/[slug].json.js
  2. import db from './_database.js'; // the underscore tells Sapper this isn't a route
  3. export async function get(req, res, next) {
  4. // the `slug` parameter is available because this file
  5. // is called [slug].json.js
  6. const { slug } = req.params;
  7. const article = await db.get(slug);
  8. if (article !== null) {
  9. res.setHeader('Content-Type', 'application/json');
  10. res.end(JSON.stringify(article));
  11. } else {
  12. next();
  13. }
  14. }

delete 是 JavaScript 的保留字。如需处理 DELETE 请求,可以导出名为 del 的函数进行替代。

文件命名规则

用于定义路由的文件,有以下三个简单的命名规则:

  • 命名为 src/routes/about.svelte 的文件对应 /about 路由。命名为 src/routes/blog/[slug].svelte 的文件对应 /blog/:slug 路由,此时 params.slug 可以在 preload 中使用。
  • 命名为 src/routes/index.svelte 对应应用程序的根路由。并且 src/routes/about/index.sveltesrc/routes/about.svelte 是同效的。
  • 以下划线开头的文件或目录不会创建路由。这样就可以将助手模块或者组件跟路由放在一起了 — 例如,你可以创建一个名为 src/routes/_helpers/datetime.js 的文件,它不会创建 /_helpers/datetime 路由。

    错误页面

    除了常规的页面,Sapper 还期望找到特殊的文件 — src/routes/_error.svelte 。它会在渲染页面出错时显示。

实际上, error 对象可以联调 HTTP status 状态码一起在模板里使用。

路由中的正则表达式

可以使用一段正则表达式来限定路由参数,只需将正则表达式放到路由参数名后的圆括号中即可。

例如, src/routes/items/[id([0-9]+)].svelte 只会匹配到数字id —— /items/123 会被匹配到,但 /items/xyz 不会被匹配到。

由于技术限制,这些符号不能使用: /\?:()