当前位置:首页 > 网站建设 > 正文内容

从0到1搭建技术博客,Next.js Tailwind CSS MDX全流程

znbo4个月前 (03-30)网站建设537

本文目录导读:

  1. 引言
  2. 1. 技术选型与项目初始化
  3. 2. 搭建博客核心功能
  4. 3. 优化与部署
  5. 4. 总结

在当今互联网时代,拥有一个个人技术博客不仅能帮助开发者记录学习历程,还能提升个人品牌影响力,许多开发者可能会因为技术选型或搭建过程的复杂性而望而却步,本文将详细介绍如何从零开始搭建一个现代化的技术博客,使用 Next.js 作为前端框架,Tailwind CSS 进行样式设计,并支持 MDX 格式的博客内容管理,我们将涵盖从项目初始化到部署的全流程,帮助你快速构建一个高性能、可扩展的技术博客。

从0到1搭建技术博客,Next.js Tailwind CSS MDX全流程


技术选型与项目初始化

1 为什么选择 Next.js + Tailwind CSS + MDX?

  • Next.js:基于 React 的框架,支持 SSR(服务端渲染)和 SSG(静态生成),适合 SEO 优化,并提供优秀的开发体验。
  • Tailwind CSS:一个实用优先的 CSS 框架,可以快速构建响应式 UI,无需编写大量自定义 CSS。
  • MDX:Markdown 的扩展,允许在 Markdown 中嵌入 React 组件,适合技术博客的内容管理。

2 初始化项目

使用 create-next-app 快速搭建 Next.js 项目:

npx create-next-app@latest my-tech-blog --typescript
cd my-tech-blog

安装 Tailwind CSS:

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

配置 tailwind.config.js

module.exports = {
  content: [
    "./pages/**/*.{js,ts,jsx,tsx}",
    "./components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

globals.css 中引入 Tailwind:

@tailwind base;
@tailwind components;
@tailwind utilities;

搭建博客核心功能

1 文章管理与 MDX 集成

安装 @next/mdxremark 相关插件:

npm install @next/mdx @mdx-js/loader @mdx-js/react remark-gfm rehype-highlight

next.config.js 中配置 MDX:

const withMDX = require("@next/mdx")({
  extension: /\.mdx?$/,
  options: {
    remarkPlugins: [require("remark-gfm")],
    rehypePlugins: [require("rehype-highlight")],
  },
});
module.exports = withMDX({
  pageExtensions: ["ts", "tsx", "md", "mdx"],
});

创建 posts 目录存放 MDX 文件,示例 hello-world.mdx

--- "Hello World"
date: "2023-10-01"
description: "我的第一篇博客文章"
---
# Hello World
这是我的第一篇博客文章,使用 **MDX** 编写!
```js
console.log("Hello, MDX!");

### **2.2 实现文章列表与详情页**
#### **文章列表页 (`pages/index.tsx`)**
```tsx
import { GetStaticProps } from "next";
import fs from "fs";
import path from "path";
import matter from "gray-matter";
interface Post {
  slug: string;
  frontmatter: { string;
    date: string;
    description: string;
  };
}
export default function Home({ posts }: { posts: Post[] }) {
  return (
    <div className="max-w-3xl mx-auto p-4">
      <h1 className="text-3xl font-bold mb-6">技术博客</h1>
      <ul className="space-y-4">
        {posts.map((post) => (
          <li key={post.slug} className="border-b pb-4">
            <a href={`/posts/${post.slug}`} className="block hover:text-blue-500">
              <h2 className="text-xl font-semibold">{post.frontmatter.title}</h2>
              <p className="text-gray-600">{post.frontmatter.date}</p>
              <p className="text-gray-500">{post.frontmatter.description}</p>
            </a>
          </li>
        ))}
      </ul>
    </div>
  );
}
export const getStaticProps: GetStaticProps = async () => {
  const postsDir = path.join(process.cwd(), "posts");
  const filenames = fs.readdirSync(postsDir);
  const posts = filenames.map((filename) => {
    const filePath = path.join(postsDir, filename);
    const fileContent = fs.readFileSync(filePath, "utf-8");
    const { data } = matter(fileContent);
    return {
      slug: filename.replace(/\.mdx$/, ""),
      frontmatter: data,
    };
  });
  return { props: { posts } };
};

文章详情页 (pages/posts/[slug].tsx)

import { GetStaticProps, GetStaticPaths } from "next";
import fs from "fs";
import path from "path";
import matter from "gray-matter";
import { MDXRemote } from "next-mdx-remote";
import { serialize } from "next-mdx-remote/serialize";
interface PostProps {
  frontmatter: { string;
    date: string;
    description: string;
  };
  mdxSource: any;
}
export default function Post({ frontmatter, mdxSource }: PostProps) {
  return (
    <div className="max-w-3xl mx-auto p-4">
      <h1 className="text-3xl font-bold mb-2">{frontmatter.title}</h1>
      <p className="text-gray-600 mb-6">{frontmatter.date}</p>
      <article className="prose prose-lg">
        <MDXRemote {...mdxSource} />
      </article>
    </div>
  );
}
export const getStaticPaths: GetStaticPaths = async () => {
  const postsDir = path.join(process.cwd(), "posts");
  const filenames = fs.readdirSync(postsDir);
  const paths = filenames.map((filename) => ({
    params: { slug: filename.replace(/\.mdx$/, "") },
  }));
  return { paths, fallback: false };
};
export const getStaticProps: GetStaticProps = async ({ params }) => {
  const filePath = path.join(process.cwd(), "posts", `${params?.slug}.mdx`);
  const fileContent = fs.readFileSync(filePath, "utf-8");
  const { data, content } = matter(fileContent);
  const mdxSource = await serialize(content);
  return { props: { frontmatter: data, mdxSource } };
};

优化与部署

1 样式优化

  • 使用 @tailwindcss/typography 优化文章排版:
    npm install @tailwindcss/typography

    tailwind.config.js 中添加:

    plugins: [require("@tailwindcss/typography")],

2 SEO 优化

pages/_app.tsx 中添加 <Head>

import Head from "next/head";
function MyApp({ Component, pageProps }) {
  return (
    <>
      <Head>
        <title>我的技术博客</title>
        <meta name="description" content="记录技术学习与思考" />
      </Head>
      <Component {...pageProps} />
    </>
  );
}

3 部署

推荐使用 Vercel(Next.js 官方托管平台):

  1. Vercel 上注册并连接 GitHub/GitLab。
  2. 选择项目仓库,一键部署。

本文详细介绍了如何从零开始搭建一个基于 Next.js + Tailwind CSS + MDX 的技术博客,涵盖:

  1. 项目初始化与配置
  2. MDX 文章管理
  3. 文章列表与详情页实现
  4. SEO 优化与部署

通过这个流程,你可以快速搭建一个高性能、现代化的个人博客,并专注于内容创作,希望本文对你有所帮助!🚀

标签: jsMDX

相关文章

广州做网站公司哪家好?如何选择最适合的网站建设服务商?

本文目录导读:广州网站建设市场现状如何判断一家网站建设公司是否靠谱?广州做网站公司推荐选择网站建设公司的注意事项在数字化时代,网站已经成为企业展示形象、推广产品和服务的重要窗口,无论是初创企业还是成熟...

广东广州网站建设,数字化转型的关键一步

本文目录导读:广州网站建设的背景与现状广州网站建设的主要特点广州网站建设的行业应用广州网站建设的未来趋势广州网站建设对企业和社会的意义在当今数字化时代,网站建设已成为企业、机构乃至个人展示形象、拓展业...

广州网站建设价格解析,如何选择性价比高的建站服务?

本文目录导读:广州网站建设价格的主要构成因素广州网站建设市场的价格区间如何选择性价比高的建站服务?广州网站建设价格的未来趋势在当今数字化时代,网站已成为企业展示形象、推广产品和服务的重要工具,对于广州...

广州网站建设设计,打造数字化时代的品牌竞争力

本文目录导读:广州网站建设设计的重要性广州网站建设设计的核心要素广州网站建设设计的未来趋势如何选择广州的网站建设设计服务在数字化时代,网站已经成为企业展示品牌形象、吸引客户、提升市场竞争力的重要工具,...

广州网站建设推广服务中心官网,打造企业数字化转型的核心引擎

本文目录导读:广州网站建设推广服务中心官网的核心价值广州网站建设推广服务中心官网的主要服务内容广州网站建设推广服务中心官网如何助力企业数字化转型成功案例分享在当今数字化时代,企业的发展离不开互联网的支...

广州网站建设优化公司,如何选择专业服务提升企业数字化竞争力

本文目录导读:广州网站建设优化公司的市场现状网站建设与优化的核心服务内容如何选择一家专业的广州网站建设优化公司广州网站建设优化公司的未来发展趋势在数字化时代,企业网站不仅是品牌形象的展示窗口,更是与客...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。