Kto-Blog
Published on

Next.js Blog Project - Advanced Study

Authors
  • avatar
    Name
    Kto

Introduction

引言

本篇博客基于 Next.js Starter Blog 项目进行二次开发的实践经验分享。 This blog post shares practical experience from secondary development based on the Next.js Starter Blog project.

这个博客模板采用了现代化的技术栈,包括 Next.js App Router、Tailwind CSS、Contentlayer(MDX 处理)、Framer Motion 等。 This blog template uses a modern tech stack including Next.js App Router, Tailwind CSS, Contentlayer (MDX processing), Framer Motion, etc.

本文将深入介绍如何基于这个模板进行个性化定制,涵盖组件开发、样式系统、性能优化等多个方面。 This article will深入介绍 how to customize this template, covering component development, style systems, performance optimization, and more.

一、如何引入图片 | I. How to Import Images

方式一:使用本地图片 | Method 1: Using Local Images

将图片放置在 public/ 目录下,然后通过 Image 组件引用: Place images in the public/ directory and reference them via the Image component:

import Image from '@/components/Image'

// 直接使用
// Use directly
;<Image src="/images/your-image.png" alt="描述文字" width={800} height={400} />

方式二:使用远程图片 | Method 2: Using Remote Images

首先需要在 next.config.js 中配置允许的图片域名: First, configure allowed image domains in next.config.js:

// next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'example.com', // 替换为你的图片域名
        pathname: '/images/**',
      },
      // Replace with your image domain
    ],
    // 图片优化配置
    // Image optimization configuration
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
    formats: ['image/webp', 'image/avif'],
  },
}

然后在 MDX 文件中使用: Then use in MDX files:

![图片描述](https://example.com/image.png)

或使用组件: Or use component:

<Image
  src="https://example.com/image.png"
  alt="描述"
  width={800}
  height={400}
  priority // 首屏图片优先加载
/>
// Prioritize loading for above-fold images

响应式图片处理 | Responsive Image Handling

使用 sizes 属性实现响应式图片: Use sizes property for responsive images:

<Image
  src="/images/hero.jpg"
  alt="Hero Image"
  fill
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
  style={{ objectFit: 'cover' }}
/>

图片占位符和模糊效果 | Image Placeholder and Blur Effect

实现图片加载时的模糊占位效果: Implement blur placeholder effect during image loading:

<Image
  src="/images/large.jpg"
  alt="大图"
  width={1200}
  height={600}
  placeholder="blur"
  blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRg..."
/>

图片懒加载策略 | Image Lazy Loading Strategy

import Image from 'next/image'

export default function Gallery() {
  return (
    <div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3">
      {[...Array(9)].map((_, i) => (
        <Image
          key={i}
          src={`/images/image-${i}.jpg`}
          alt={`Gallery image ${i}`}
          width={400}
          height={300}
          loading="lazy" // 懒加载
          // Lazy load
          // 非首屏图片设置 loading="lazy"
          // Set loading="lazy" for non-above-fold images
        />
      ))}
    </div>
  )
}

二、如何修改样式 | II. How to Modify Styles

全局样式修改 | Global Style Modification

项目使用 Tailwind CSS 作为样式框架。全局样式文件位于 css/tailwind.css。 The project uses Tailwind CSS as the style framework. Global styles are in css/tailwind.css.

/* css/tailwind.css */

/* 自定义滚动条样式 */
/* Custom scrollbar styles */
::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

::-webkit-scrollbar-track {
  @apply bg-gray-100 dark:bg-gray-800;
}

::-webkit-scrollbar-thumb {
  @apply rounded-full bg-gray-400 dark:bg-gray-600;
}

::-webkit-scrollbar-thumb:hover {
  @apply bg-gray-500 dark:bg-gray-500;
}

/* 自定义选中文字样式 */
/* Custom text selection styles */
::selection {
  @apply bg-primary/20 text-primary;
}

/* 自定义动画 */
/* Custom animations */
@keyframes custom-animation {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-10px);
  }
}

.animate-custom {
  animation: custom-animation 2s ease-in-out infinite;
}

/* 呼吸灯效果 */
/* Breathing light effect */
@keyframes breathe {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}

.animate-breathe {
  animation: breathe 3s ease-in-out infinite;
}

Tailwind 配置扩展 | Tailwind Configuration Extension

tailwind.config.js 中可以扩展主题配置: You can extend theme configuration in tailwind.config.js:

module.exports = {
  darkMode: 'class', // 基于类的暗黑模式
  // Class-based dark mode
  content: ['./app/**/*.{ts,tsx}', './components/**/*.{ts,tsx}', './layouts/**/*.{ts,tsx}'],
  theme: {
    extend: {
      colors: {
        // 添加自定义颜色系列
        // Add custom color series
        brand: {
          50: '#eff6ff',
          100: '#dbeafe',
          200: '#bfdbfe',
          300: '#93c5fd',
          400: '#60a5fa',
          500: '#3b82f6',
          600: '#2563eb',
          700: '#1d4ed8',
          800: '#1e40af',
          900: '#1e3a8a',
        },
      },
      fontFamily: {
        // 添加自定义字体
        // Add custom fonts
        custom: ['CustomFont', 'sans-serif'],
        display: ['DisplayFont', 'sans-serif'],
      },
      animation: {
        // 添加自定义动画
        // Add custom animations
        'fade-in': 'fadeIn 0.5s ease-in-out',
        'slide-up': 'slideUp 0.5s ease-out',
        'bounce-slow': 'bounce 3s infinite',
      },
      keyframes: {
        fadeIn: {
          '0%': { opacity: '0' },
          '100%': { opacity: '1' },
        },
        slideUp: {
          '0%': { transform: 'translateY(20px)', opacity: '0' },
          '100%': { transform: 'translateY(0)', opacity: '1' },
        },
      },
      spacing: {
        // 添加自定义间距
        // Add custom spacing
        128: '32rem',
        144: '36rem',
      },
      borderRadius: {
        // 添加自定义圆角
        // Add custom border radius
        '4xl': '2rem',
      },
      boxShadow: {
        // 添加自定义阴影
        // Add custom shadows
        glow: '0 0 20px rgba(59, 130, 246, 0.5)',
      },
    },
  },
  plugins: [require('@tailwindcss/forms'), require('@tailwindcss/typography')],
}

CSS 变量系统 | CSS Variable System

使用 CSS 变量实现主题动态切换: Use CSS variables for dynamic theme switching:

/* css/tailwind.css */

:root {
  /* 颜色变量 */
  /* Color variables */
  --color-primary: 59 130 246; /* RGB values */
  --color-secondary: 139 92 246;

  /* 间距变量 */
  /* Spacing variables */
  --spacing-unit: 0.25rem;

  /* 字体大小 */
  /* Font sizes */
  --font-size-base: 1rem;

  /* 过渡时间 */
  /* Transition durations */
  --transition-fast: 150ms;
  --transition-normal: 300ms;
}

.dark {
  --color-primary: 96 165 250;
  --color-secondary: 167 139 250;
}

在 Tailwind 中使用: Use in Tailwind:

<div className="bg-[rgb(var(--color-primary))] p-[calc(var(--spacing-unit)*4)]">动态样式内容</div>
// <div>Dynamic style content</div>

组件级样式修改 | Component-level Style Modification

对于特定组件,可以直接修改组件文件。例如修改导航栏样式: For specific components, you can modify the component file directly. For example, modifying navigation bar styles:

// components/Header.tsx
import { useState, useEffect } from 'react'

const nav = `
  sticky top-0 z-50
  bg-white/80 dark:bg-gray-900/80
  backdrop-blur-md
  border-b border-gray-200 dark:border-gray-700
  transition-all duration-300
`

const navLinkClass = `
  relative
  px-4 py-2
  text-gray-700 dark:text-gray-300
  hover:text-primary dark:hover:text-primary
  transition-colors duration-200
  after:content-[''] after:absolute after:bottom-0 after:left-0 after:w-0 after:h-0.5
  after:bg-primary after:transition-all after:duration-300
  hover:after:w-full
`

export default function Header() {
  const [scrolled, setScrolled] = useState(false)

  useEffect(() => {
    const handleScroll = () => {
      setScrolled(window.scrollY > 20)
    }
    window.addEventListener('scroll', handleScroll)
    return () => window.removeEventListener('scroll', handleScroll)
  }, [])

  return (
    <header className={`${nav} ${scrolled ? 'shadow-lg' : ''}`}>
      <nav className="container mx-auto px-4">{/* 导航内容 */}</nav>
      {/* Navigation content */}
    </header>
  )
}

动态样式和条件样式 | Dynamic and Conditional Styles

使用 clsx 或 classnames 实现动态样式: Use clsx or classnames for dynamic styles:

import { clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'

// 合并 Tailwind 类的工具函数
// Utility function to merge Tailwind classes
function cn(...inputs) {
  return twMerge(clsx(inputs))
}

export function Button({ variant = 'primary', size = 'md', children, className }) {
  const baseStyles = 'rounded-lg font-medium transition-all duration-200'

  const variants = {
    primary: 'bg-primary text-white hover:bg-primary-dark',
    secondary: 'bg-gray-200 text-gray-800 hover:bg-gray-300',
    outline: 'border-2 border-primary text-primary hover:bg-primary hover:text-white',
  }

  const sizes = {
    sm: 'px-3 py-1.5 text-sm',
    md: 'px-4 py-2 text-base',
    lg: 'px-6 py-3 text-lg',
  }

  return (
    <button className={cn(baseStyles, variants[variant], sizes[size], className)}>
      {children}
    </button>
  )
}

三、如何修改背景色 | III. How to Modify Background Color

修改全局背景 | Modify Global Background

app/layout.tsx 中修改 body 的背景: Modify body background in app/layout.tsx:

// app/layout.tsx
export default function RootLayout({ children }) {
  return (
    <html lang="zh-cn" className="scroll-smooth">
      <body className="bg-gray-50 dark:bg-gray-900">{/* 页面内容 */}</body>
      {/* Page content */}
    </html>
  )
}

渐变背景 | Gradient Background

项目当前使用了渐变背景效果: The project currently uses gradient background effect:

// app/layout.tsx
<body className="
  animate-gradient
  bg-gradient-to-r
  from-indigo-50 via-purple-50 to-pink-50
  dark:from-stone-900 dark:via-zinc-900 dark:to-slate-900
  pl-[calc(100vw-100%)]
  text-black antialiased dark:text-white
">

关键类说明: Key class descriptions:

  • animate-gradient: 自定义动画类,让渐变缓慢移动

  • Custom animation class for slow gradient movement

  • bg-gradient-to-r: 水平渐变方向

  • Horizontal gradient direction

  • from-{color}, via-{color}, to-{color}: 渐变颜色点

  • Gradient color points

  • dark: 前缀: 暗黑模式下的样式

  • Dark mode styles

  • pl-[calc(100vw-100%)]: 防止滚动条出现时的布局偏移

  • Prevent layout shift when scrollbar appears

  • antialiased: 字体抗锯齿

  • Font antialiasing

修改渐变动画 | Modify Gradient Animation

css/tailwind.css 中定义动画: Define animation in css/tailwind.css:

@keyframes gradient {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

.animate-gradient {
  background-size: 200% 200%;
  animation: gradient 10s ease infinite;
}

/* 更快的渐变动画 */
/* Faster gradient animation */
.animate-gradient-fast {
  background-size: 200% 200%;
  animation: gradient 5s ease infinite;
}

/* 垂直渐变动画 */
/* Vertical gradient animation */
@keyframes gradient-vertical {
  0% {
    background-position: 50% 0%;
  }
  50% {
    background-position: 50% 100%;
  }
  100% {
    background-position: 50% 0%;
  }
}

.animate-gradient-vertical {
  background-size: 200% 200%;
  animation: gradient-vertical 15s ease infinite;
}

四、如何添加组件 | IV. How to Add Components

创建新组件 | Create New Component

components/ 目录下创建新的组件文件: Create new component file in components/ directory:

// components/MyComponent.tsx
import { ReactNode } from 'react'

interface MyComponentProps {
  title: string
  children?: ReactNode
  variant?: 'default' | 'primary' | 'secondary'
}

export default function MyComponent({ title, children, variant = 'default' }: MyComponentProps) {
  const variants = {
    default: 'border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800',
    primary: 'border-primary bg-primary/5 dark:bg-primary/10',
    secondary: 'border-purple-300 bg-purple-50 dark:border-purple-700 dark:bg-purple-900/20',
  }

  return (
    <div
      className={`
      rounded-lg border p-4 shadow-sm transition-all duration-200
      hover:shadow-md
      ${variants[variant]}
    `}
    >
      <h3 className="mb-2 text-lg font-semibold">{title}</h3>
      {children}
    </div>
  )
}

在 MDX 中使用组件 | Use Components in MDX

首先在 components/MDXComponents.tsx 中注册组件: First register component in components/MDXComponents.tsx:

// components/MDXComponents.tsx
import { MDXComponents } from 'mdx/types'
import Image from './Image'
import TOCInline from './TOCInline'
import MyComponent from './MyComponent'
import CustomLink from './Link'

export const components: MDXComponents = {
  Image,
  TOCInline,
  MyComponent,
  a: CustomLink,
}

然后在 MDX 文件中直接使用: Then use directly in MDX files:

---
title: 使用自定义组件
date: 2026-01-02
tags: ['nextjs', 'mdx']
---

## 引言

这是一个演示如何使用自定义组件的文章。
This is an article demonstrating how to use custom components.

<MyComponent title="提示信息" variant="primary">
  这是组件的内容部分。你可以在这里放置任何内容。 This is the content part of the component. You can
  place any content here.
</MyComponent>

五、如何添加进度条 | V. How to Add Progress Bar

项目包含一个精美的阅读进度条组件,位于 components/ProgressBar.tsx。 The project includes a beautiful reading progress bar component at components/ProgressBar.tsx.

使用进度条 | Use Progress Bar

app/layout.tsx 中引入: Import in app/layout.tsx:

import ProgressBar from '@/components/ProgressBar'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <ProgressBar />
        {children}
      </body>
    </html>
  )
}

六、如何添加文章 TOC 组件 | VI. How to Add Article TOC Component

文章目录(Table of Contents)组件位于 components/TOCInline.tsx。 The Table of Contents component is located at components/TOCInline.tsx.

在文章中使用 TOC | Use TOC in Articles

在 MDX 文件中直接使用: Use directly in MDX files:

---
title: 你的文章标题
date: 2026-01-02
tags: ['nextjs']
---

# Your Article Title

## 引言

文章引言内容,介绍文章的主要内容...
Article introduction content, describing the main content...

<TOCInline />

## 第一节:基础概念

这是第一节的详细内容...
This is the detailed content of section 1...

## 第二节:进阶应用

这是第二节的详细内容...
This is the detailed content of section 2...

七、其他实用组件 | VII. Other Useful Components

加载进度条 (LoadingBar) | Loading Progress Bar

位于 components/LoadingBar.tsx,在路由切换时显示加载进度。 Located at components/LoadingBar.tsx, displays loading progress during route transitions.

特性: Features:

  • 监听页面加载和路由切换

  • Monitors page loading and route transitions

  • 自动完成机制(最多5秒)

  • Auto-completion mechanism (max 5 seconds)

  • 渐变色动画效果

  • Gradient color animation effect

  • 防止重复触发

  • Prevents duplicate triggers

主题切换 (ThemeSwitch) | Theme Switcher

位于 components/ThemeSwitch.tsx,支持亮色/暗色主题切换。 Located at components/ThemeSwitch.tsx, supports light/dark theme switching.

特性: Features:

  • 使用 next-themes 管理主题

  • Uses next-themes for theme management

  • 优雅的切换动画

  • Elegant switching animation

  • 太阳/月亮图标

  • Sun/moon icons

  • 自动适配系统主题

  • Auto-adapts to system theme

返回顶部 (ScrollTopAndComment) | Back to Top

位于 components/ScrollTopAndComment.tsx,提供返回顶部和跳转评论区的按钮。 Located at components/ScrollTopAndComment.tsx, provides back-to-top and jump-to-comment buttons.

特性: Features:

  • 滚动超过50px后显示

  • Shows after scrolling more than 50px

  • 返回顶部功能

  • Back to top functionality

  • 跳转到评论区

  • Jump to comment section

  • 平滑滚动动画

  • Smooth scroll animation

八、性能优化技巧 | VIII. Performance Optimization Tips

React 性能优化 | React Performance Optimization

使用 React.memo 防止不必要的重渲染 | Use React.memo to prevent unnecessary re-renders

import { memo } from 'react'

const ExpensiveComponent = memo(function ExpensiveComponent({ data }: { data: any }) {
  // 组件逻辑
  // Component logic
  return <div>{/* 渲染内容 */}</div>
  // Render content
})

使用 useMemo 缓存计算结果 | Use useMemo to cache calculation results

import { useMemo } from 'react'

function ProcessedList({ items }: { items: any[] }) {
  const processed = useMemo(() => {
    return items.map((item) => {
      // 昂贵的计算
      // Expensive calculation
      return transform(item)
    })
  }, [items])

  return <div>{processed}</div>
}

使用 useCallback 稳定函数引用 | Use useCallback to stabilize function references

import { useCallback } from 'react'

function ParentComponent() {
  const handleClick = useCallback(() => {
    // 处理点击
    // Handle click
  }, [])

  return <ChildComponent onClick={handleClick} />
}

代码分割和懒加载 | Code Splitting and Lazy Loading

import dynamic from 'next/dynamic'

const HeavyComponent = dynamic(() => import('@/components/HeavyComponent'), {
  loading: () => <div>Loading...</div>,
  ssr: false, // 客户端渲染
  // Client-side rendering
})

九、SEO 优化 | IX. SEO Optimization

元数据配置 | Metadata Configuration

// app/layout.tsx
export const metadata = {
  title: {
    default: '网站标题', // Website title
    template: '%s | 网站标题', // %s | Website title
  },
  description: '网站描述', // Website description
  keywords: ['关键词1', '关键词2'], // Keywords
  openGraph: {
    title: '网站标题', // Website title
    description: '网站描述', // Website description
    url: 'https://example.com',
    images: [
      {
        url: 'https://example.com/og.jpg',
        width: 1200,
        height: 630,
      },
    ],
  },
}

总结 | Summary

这个 Next.js 博客模板提供了完善的组件体系和样式系统,通过合理使用和扩展这些功能,可以快速构建出功能完善、外观精美的个人博客。 This Next.js blog template provides a comprehensive component system and style system. Through proper use and extension of these features, you can quickly build a fully functional, beautiful personal blog.

学习路径建议 | Learning Path Recommendations

  1. 基础阶段:熟悉项目结构,理解组件系统

  2. Basic Stage: Familiarize with project structure, understand component system

  3. 进阶阶段:定制样式,添加自定义组件

  4. Advanced Stage: Customize styles, add custom components

  5. 优化阶段:性能优化,SEO 提升

  6. Optimization Stage: Performance optimization, SEO improvement

  7. 高级阶段:扩展功能,集成第三方服务

  8. Expert Stage: Extend features, integrate third-party services

参考资源 | Reference Resources

Comments

Join the discussion and share your thoughts

Sort after loading
Sign in to post comments and replies