发布于 2026-01-06 1 阅读
0

使用 Svelte、Sapper 和 Markdown 构建博客。

使用 Svelte、Sapper 和 Markdown 构建博客。

原文发表于我的博客

在这篇文章中,我们将使用 Svelte 和 Sapper 构建一个带有博客的网站。

Svelte是什么?

Svelte 是一个新推出的 JavaScript 框架,
它的理念是帮助你在不使用虚拟 DOM 等额外技术的情况下操作 DOM,
Svelte 会在构建时编译你的代码,并且你可以使用响应式轻松更新你的应用程序。

什么是工兵?

Sapper 是一个基于 Svelte 的服务器端框架,可帮助您创建具有良好 SEO 和基于文件系统路由的 PWA 应用程序。

如何初始化项目?

我们将使用 Sapper 团队提供的入门模板,
打开你常用的终端并输入以下命令:

  npx degit "sveltejs/sapper-template#rollup" cool-blog
  cd /cool-blog
  npm install
Enter fullscreen mode Exit fullscreen mode

安装完依赖项后,您就可以启动服务器了。

  npm run dev
Enter fullscreen mode Exit fullscreen mode

瞧!🎉应用程序现在已经上线运行了。

工兵模板首页

让我们用你最喜欢的编辑器打开项目,然后进入 项目blog文件夹
src/routes

我们在那里有几个文件:

  | src
    | routes
      | blog
        - index.svelte,
        - index.json.js
        - [slug].svelte
        - [slug].json.js
        - _posts.js
Enter fullscreen mode Exit fullscreen mode

Sapper 中的路由是如何工作的?

我们有两种类型:页面和服务器路由。

文件名决定路由。例如:src/routes/blog/index.svelte参考路由/blog

对于动态路由,我们将使用[slug]……例如,ser/routes/blog/[slug].svelte请参考路由/blog/the-whatever-blog-name

服务器

服务器路由是以文件形式编写的模块.js,用于导出 HTTP 函数。
例如,get用于检索博客详情的端点:

  // [slug].json.js

  import posts from './_posts.js';
  const lookup = new Map();

  posts.forEach(post => {
    lookup.set(post.slug, JSON.stringify(post));
  });

  export function get(req, res, next) {
    // the `slug` parameter is available because
    // this file is called [slug].json.js
    const { slug } = req.params;

    if (lookup.has(slug)) {
      res.writeHead(200, {
        'Content-Type': 'application/json',
      });

      res.end(lookup.get(slug));
    } else {
      res.writeHead(404, {
        'Content-Type': 'application/json',
      });

      res.end(
        JSON.stringify({
          message: `Not found`,
        })
      );
    }
  }
Enter fullscreen mode Exit fullscreen mode

content在项目根目录下创建一个目录。
在该目录下,我们将创建一个名为sample-post.mdfile 的文件。

// sample-post.md

---
slug: 'sample-blog'
title: 'Sample blog.'
---

# Sample title

this is a sample blog post.

``javascript
  console.log("test code highlight")
``

Enter fullscreen mode Exit fullscreen mode

slug必须与文件名相同,这样我们才能通过别名轻松读取文件。
您可以添加多个别名titleslug例如日期、关键字或任何您需要添加的内容。

要列出/blog路线上的所有博客src/routes/blog/index.json.js

  // src/routes/blog/index.json.js

  import fs from "fs";
  import path from "path";
  import grayMatter from "gray-matter";

  const getAllPosts = () =>
    fs.readdirSync("content").map(fileName => {
      const post = fs.readFileSync(path.resolve("content", fileName), "utf-8");
      return grayMatter(post).data;
    });

  export function get(req, res) {
    res.writeHead(200, {
      "Content-Type": "application/json"
    });
    const posts = getAllPosts();
    res.end(JSON.stringify(posts));
  }
Enter fullscreen mode Exit fullscreen mode

你需要安装一个名为 `resolve` 的额外软件包,它可以帮助你解析 markdown中的gray-matterfront matter 数据titleslug

  npm install gray-matter
Enter fullscreen mode Exit fullscreen mode

如果您导航到/blog该路线,您应该会看到类似这样的页面:

博客页面

现在我们需要处理 POST 请求。src/routes/blog/[slug].json.js

  // src/routes/blog/[slug].json.js

  import path from "path";
  import fs from "fs";
  import grayMatter from "gray-matter";
  import marked from "marked";
  import hljs from "highlight.js";

  const getPost = fileName =>
    fs.readFileSync(path.resolve("content", `${fileName}.md`), "utf-8");

  export function get(req, res, next) {
    const { slug } = req.params;

    // get the markdown text
    const post = getPost(slug);

    // function that expose helpful callbacks
    // to manipulate the data before convert it into html
    const renderer = new marked.Renderer();

    // use hljs to highlight our blocks codes
    renderer.code = (source, lang) => {
      const { value: highlighted } = hljs.highlight(lang, source);
      return `<pre class='language-javascriptreact'><code>${highlighted}</code></pre>`;
    };

    // parse the md to get front matter
    // and the content without escaping characters
    const { data, content } = grayMatter(post);

    const html = marked(content, { renderer });

    if (html) {
      res.writeHead(200, {
        "Content-Type": "application/json"
      });

      res.end(JSON.stringify({ html, ...data }));
    } else {
      res.writeHead(404, {
        "Content-Type": "application/json"
      });

      res.end(
        JSON.stringify({
          message: `Not found`
        })
      );
    }
  }
Enter fullscreen mode Exit fullscreen mode

我们需要安装两个新软件包

  • marked: 帮助我们将 markdown 文件转换为 HTML。
  • highlight.js:为代码块添加高亮显示。
  npm install highlight.js marked
Enter fullscreen mode Exit fullscreen mode

我们src/client.js导入了Github样式以用于highlight.js。

  // src/client.js
  // ...
  import "highlight.js/styles/github.css";
  // ...
Enter fullscreen mode Exit fullscreen mode

博客文章

结论

现在您可以开始为您的网站添加更多样式并自定义博客元素样式,然后使用NetlifyGithub Pages或任何其他服务
上线了。

文章来源:https://dev.to/22mahmoud/building-a-blog-with-svelte-sapper-and-markdown-390l