You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Svelte博客:如何禁止published: false的Markdown文章直接访问

问题描述

我用Markdown文件搭建了一个Svelte网站,需求是当文章frontmatter里有published: false时,该文章不发布且从列表中排除。目前已经修改api/posts/+server.js实现了列表过滤,但这类文章还是能通过直接链接访问,需要实现让它无法访问并返回404,该怎么操作?

现有代码如下:

  1. 工具函数lib/utils/getPosts.js:
/*lib/utils/getPosts.js*/
// @ts-nocheck
export const getMarkdownPosts = async () => {
    const allPostFiles = import.meta.glob('/src/content/posts/*.md')
    const iterablePostFiles = Object.entries(allPostFiles)
    const allPosts = await Promise.all(
        iterablePostFiles.map(async ([path, resolver]) => {
            const { metadata } = await resolver()
            const postPath = path.split('/').at(-1)?.replace('.md', '')
            return {
                meta: metadata,
                path: postPath,
            }
        })
    )
    return allPosts
}
  1. 修改后的api/posts/+server.js:
/*api/posts/+server.js*/
import { getMarkdownPosts } from '$lib/utils/getPosts'
import { json } from '@sveltejs/kit'
export const GET = async () => {
  const allPosts = await getMarkdownPosts()
  const sortedPosts = allPosts.sort((a, b) => {
    return new Date(b.meta.date) - new Date(a.meta.date)
  }).filter(post => post.meta.published === true)
  return json(sortedPosts)
}
  1. 文章页面的load函数blog/[slug]/+page.js:
/*blog/[slug]/+page.js*/
export async function load({ params }){
    const post = await import(`../../../content/posts/${params.slug}.md`)
    const { title, date, categories, draft } = post.metadata
    const content = post.default
    return {
      content,
      title,
      date,
      categories
    }
}
解决方案

要实现未发布文章无法直接访问,核心是在文章页面的加载逻辑中增加发布状态校验,结合SvelteKit的错误处理机制返回404,以下是具体实现步骤:

步骤1:修改文章页面的load函数

在加载文章时,先读取frontmatter中的published字段,若为false则抛出404错误。同时增加异常捕获,处理文件不存在的情况:

/*blog/[slug]/+page.js*/
import { error } from '@sveltejs/kit';

export async function load({ params }){
    try {
        const post = await import(`../../../content/posts/${params.slug}.md`);
        const { title, date, categories, published } = post.metadata;
        const content = post.default;

        // 校验发布状态,未发布则返回404
        if (published === false) {
            throw error(404, '文章未发布或不存在');
        }

        return {
            content,
            title,
            date,
            categories
        };
    } catch (err) {
        // 文件不存在或校验失败时返回404
        throw error(404, '文章未发布或不存在');
    }
}

步骤2:(可选)统一校验逻辑到工具函数

如果需要在多个场景复用校验逻辑,可以给lib/utils/getPosts.js新增根据slug获取已发布文章的函数:

/*lib/utils/getPosts.js*/
// @ts-nocheck
export const getMarkdownPosts = async () => {
    const allPostFiles = import.meta.glob('/src/content/posts/*.md');
    const iterablePostFiles = Object.entries(allPostFiles);
    const allPosts = await Promise.all(
        iterablePostFiles.map(async ([path, resolver]) => {
            const { metadata } = await resolver();
            const postPath = path.split('/').at(-1)?.replace('.md', '');
            return {
                meta: metadata,
                path: postPath,
            };
        })
    );
    return allPosts;
};

// 新增:根据slug获取已发布的文章
export const getPublishedPostBySlug = async (slug) => {
    try {
        const post = await import(`../../content/posts/${slug}.md`);
        const { metadata, default: content } = post;

        if (metadata.published === false) {
            return null;
        }

        return {
            meta: metadata,
            content,
            slug
        };
    } catch (err) {
        return null;
    }
};

然后在blog/[slug]/+page.js中调用该工具函数:

/*blog/[slug]/+page.js*/
import { error } from '@sveltejs/kit';
import { getPublishedPostBySlug } from '$lib/utils/getPosts';

export async function load({ params }){
    const post = await getPublishedPostBySlug(params.slug);

    if (!post) {
        throw error(404, '文章未发布或不存在');
    }

    const { title, date, categories } = post.meta;
    return {
        content: post.content,
        title,
        date,
        categories
    };
}

步骤3:静态生成场景额外处理(若启用SSG)

如果网站使用静态生成,需要确保未发布文章不会被预渲染,在blog/[slug]/+page.js中添加getStaticPaths函数过滤路径:

/*blog/[slug]/+page.js*/
import { error } from '@sveltejs/kit';
import { getMarkdownPosts } from '$lib/utils/getPosts';

export async function getStaticPaths() {
    const allPosts = await getMarkdownPosts();
    // 仅生成已发布文章的静态路径
    const publishedPosts = allPosts.filter(post => post.meta.published === true);

    return {
        paths: publishedPosts.map(post => ({ params: { slug: post.path } })),
        fallback: 'blocking' // 根据需求选择false或blocking
    };
}

export async function load({ params }){
    const post = await import(`../../../content/posts/${params.slug}.md`);
    const { title, date, categories, published } = post.metadata;
    const content = post.default;

    if (published === false) {
        throw error(404, '文章未发布或不存在');
    }

    return {
        content,
        title,
        date,
        categories
    };
}

内容的提问来源于stack exchange,提问作者Лео

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 16:16:00