从零构建个人博客:技术栈与架构详解

一、引言

背景
在当今数字时代,个人博客不仅是展示专业技能的窗口,也是记录个人成长和分享知识的平台。 作为一名Web开发爱好者,我决定从零开始构建这个博客网站,而不是依赖现成的博客平台或内容管理系统, 这个过程充满了挑战和收获。🚀

本文目标
本文将详细介绍这个博客的技术栈、架构设计、核心JavaScript功能实现以及部署方案。 无论你是Web开发新手还是有经验的开发者,希望这篇文章能为你提供一些启发, 帮助你理解如何构建一个功能完善且个性化的静态博客网站。📝

核心理念
与使用WordPress或其他CMS相比,从零构建博客的优势在于完全掌控网站的各个方面, 从性能优化到用户体验设计,同时也是提升前端开发技能的绝佳机会。 正如我在设计这个博客时所遵循的理念:"简洁、高效、个性化"💡

二、技术栈

2.1 核心技术

前端三件套
这个博客采用了纯前端技术栈构建,不依赖任何后端服务或数据库,完全由静态文件组成。 这种架构具有部署简单、加载迅速的优势。

技术选择详解
具体技术选择及其优势:

  • HTML5 - 语义化标签提升了网站结构清晰度和SEO表现
  • CSS3 - 自定义变量、Flexbox和Grid布局、媒体查询实现响应式设计
  • 原生JavaScript - 不依赖任何框架,实现主题切换、语言国际化、动态内容加载等功能

2.2 外部库

精选辅助库
虽然尽量减少外部依赖,但为了增强特定功能和用户体验,我选择了几个轻量级库:📚

  • Font Awesome - 提供丰富的图标集
  • Google Fonts - 引入多种精美字体,如SF Pro Display(主字体)、Chewy和ZCOOL KuaiLe(特殊标题)
  • Highlight.js - 代码高亮功能

引入方式
外部库引用示例:

<!-- 外部库引用示例 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/atom-one-light.min.css">
<link href="https://fonts.googleapis.com/css2?family=SF+Pro+Display:wght@300;400;500;600&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Chewy&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=ZCOOL+KuaiLe&display=swap" rel="stylesheet">

2.3 开发工具

工具链
开发过程中使用的工具:🛠️

  • Visual Studio Code - 主要代码编辑器,配置了HTML/CSS/JS插件增强开发体验
  • Git & GitHub - 版本控制和代码托管,同时也用于网站部署
  • Browser DevTools - 调试和优化网站性能、响应式设计测试
  • Lighthouse - 网站性能、可访问性、SEO和最佳实践评估

技术栈选择理由
对于个人博客项目,我优先考虑了以下因素:💭

  • 简洁高效:无需复杂的构建流程和依赖管理
  • 长期可维护:使用基础且经典的技术,降低技术债务
  • 学习价值:深入理解Web基础,提升原生JavaScript编程能力
  • 性能优先:轻量级技术栈确保网站加载速度快
  • 部署便捷:静态网站可以轻松部署在任何托管服务上

三、网站架构

3.1 文件结构

组织原则
博客采用了模块化的文件结构,按功能和类型组织文件,便于维护和扩展:📂

healthjianblog/
├── index.html                 # 网站首页
├── css/                       # 样式文件目录
│   ├── style.css              # 全局样式
│   ├── dark-mode.css          # 暗黑模式样式
│   ├── blog.css               # 博客列表样式
│   ├── blog-post.css          # 博客文章页样式
│   └── ...                    # 其他样式文件
├── js/                        # JavaScript文件目录
│   ├── main.js                # 主要功能
│   ├── theme.js               # 主题切换功能
│   ├── language.js            # 语言切换功能
│   ├── blog.js                # 博客相关功能
│   └── ...                    # 其他功能模块
├── images/                    # 图片资源目录
├── pages/                     # 页面目录
│   ├── blog.html              # 博客列表页
│   ├── about.html             # 关于页面
│   ├── links.html             # 链接页面
│   ├── project/               # 项目展示页目录
│   │   ├── project.html       # 项目列表页
│   │   └── ...                # 项目详情页
│   └── blog/                  # 博客文章目录
│       ├── tech/              # 技术类文章
│       ├── life/              # 生活类文章
│       └── thoughts/          # 随想类文章
└── README.md                  # 项目说明

结构优势
这种组织方式有以下优点:

  • 清晰的资源分类,易于查找和管理
  • 模块化的JavaScript和CSS文件,有利于代码复用
  • 文章按主题分类,简化内容管理
  • 直观的目录结构,易于新成员理解项目

3.2 设计理念

核心设计原则
博客设计遵循以下核心理念:🎨

  • 内容为王 - 简洁的设计突出内容本身,避免过多视觉干扰
  • 用户体验优先 - 直观的导航、合理的布局、舒适的阅读体验
  • 响应式设计 - 适配从手机到桌面的各种设备尺寸
  • 可访问性 - 考虑色彩对比度、键盘导航等无障碍设计
  • 性能优化 - 资源按需加载、图片优化、代码精简

3.3 组件结构

无框架组件化
虽然没有使用前端框架,但博客仍然采用了"组件化"的思想来组织HTML结构,每个页面主要分为以下几个组件:🧩

  • 导航栏(Navbar) - 包含logo、菜单、社交图标和主题/语言切换按钮
  • 页面内容(Main Content) - 根据页面类型展示不同内容
  • 页脚(Footer) - 包含版权信息、联系方式和快速导航链接

文章页组件
对于博客文章页,还包含:

  • 侧边栏(Sidebar) - 展示目录、文章元信息和导航
  • 文章内容(Article) - 包含标题、正文和结语
  • 评论区(Comments) - 允许读者互动

3.4 多语言支持

双语实现策略
博客实现了中英双语支持,采用了以下策略:🌐

  • 使用HTML数据属性(data-en和data-zh)存储不同语言的文本
  • 创建.bilingual-content容器包裹需要双语显示的长文本内容
  • 通过添加/移除body上的CSS类(en/zh)控制当前语言显示
  • 使用localStorage存储用户语言偏好

代码实现
双语支持的HTML结构示例:

<!-- 简短文本的双语实现 -->
<h2 data-en="About Me" data-zh="关于我">关于我</h2>

<!-- 长文本的双语实现 -->
<div class="bilingual-content">
    <p class="zh-content">这是中文内容</p>
    <p class="en-content" style="display: none;">This is English content</p>
</div>

四、JavaScript实现

4.1 主题切换功能

功能描述
博客实现了亮色/暗色主题切换功能,核心实现包括:🌓

  • 使用CSS变量定义不同主题的颜色方案
  • 通过在body上切换CSS类(light-mode/dark-mode)实现主题转换
  • 使用localStorage存储用户主题偏好
  • 根据当前时间自动选择默认主题(白天/黑夜)

核心代码
主题切换功能的JavaScript实现:

// 根据当前时间获取合适的主题
function getThemeByTime() {
    const hour = new Date().getHours();
    // 6:00-18:00 为日间模式,19:00-5:00 为夜间模式
    return (hour >= 6 && hour <= 18) ? 'light-mode' : 'dark-mode';
}

// 检查用户之前的主题偏好
function checkThemePreference() {
    const savedTheme = localStorage.getItem('theme');
    // 如果用户手动设置了主题,优先使用
    if (savedTheme) {
        document.body.className = savedTheme;
        updateThemeToggleIcon(savedTheme);
    } 
    // 如果没有手动设置,根据时间自动判断
    else {
        const timeBasedTheme = getThemeByTime();
        document.body.className = timeBasedTheme;
        updateThemeToggleIcon(timeBasedTheme);
    }
}

// 切换主题
function toggleTheme() {
    if (document.body.classList.contains('dark-mode')) {
        document.body.classList.remove('dark-mode');
        document.body.classList.add('light-mode');
        localStorage.setItem('theme', 'light-mode');
        updateThemeToggleIcon('light-mode');
    } else {
        document.body.classList.remove('light-mode');
        document.body.classList.add('dark-mode');
        localStorage.setItem('theme', 'dark-mode');
        updateThemeToggleIcon('dark-mode');
    }
}

4.2 语言切换功能

多语言实现
博客的多语言实现原理:🔄

  • 通过在body上切换CSS类(en/zh)控制当前语言
  • 使用数据属性存储双语文本
  • 针对更长的内容,使用带有显示/隐藏控制的容器元素
  • 使用localStorage保存用户语言偏好

核心实现
语言切换的JavaScript函数:

// 更新所有带有语言属性的元素
function updateAllLanguageElements(lang) {
    const elements = document.querySelectorAll('[data-en][data-zh]');
    elements.forEach(element => {
        element.textContent = element.getAttribute(`data-${lang}`);
    });
    
    // 更新搜索框占位符
    const searchInputs = document.querySelectorAll('input[data-en-placeholder][data-zh-placeholder]');
    searchInputs.forEach(input => {
        input.placeholder = input.getAttribute(`data-${lang}-placeholder`);
    });
    
    // 更新长文本内容的显示/隐藏
    const zhContents = document.querySelectorAll('.zh-content');
    const enContents = document.querySelectorAll('.en-content');
    
    if (lang === 'zh') {
        zhContents.forEach(el => el.style.display = 'block');
        enContents.forEach(el => el.style.display = 'none');
    } else {
        zhContents.forEach(el => el.style.display = 'none');
        enContents.forEach(el => el.style.display = 'block');
    }
}

4.3 动态内容加载

动态加载优势
博客列表页使用JavaScript动态加载文章内容,这种方式相比于静态HTML有以下优势:🔄

  • 更容易实现文章过滤、搜索和分页功能
  • 便于将来扩展,比如从API或JSON文件加载内容
  • 避免重复的HTML代码,提高维护效率

实现示例
博客文章数据和加载函数:

// 博客文章数据示例
const blogPosts = [
    {
        id: 1,
        title: { zh: "从零构建个人博客:技术栈与架构详解", en: "Building a Personal Blog from Scratch: Tech Stack and Architecture" },
        excerpt: { zh: "详细介绍个人博客的技术栈、架构设计和核心功能实现...", en: "Detailed introduction to the tech stack, architecture design, and core functionality implementation of a personal blog..." },
        date: "2025-04-25",
        category: "tech",
        tags: ["web-development", "frontend", "html-css-js"],
        url: "blog/tech/blog-building.html"
    },
    // 更多文章...
];

// 加载特定页面的文章
function loadPagePosts(page, filter = 'all') {
    const postsPerPage = 6;
    const startIndex = (page - 1) * postsPerPage;
    const endIndex = startIndex + postsPerPage;
    
    // 根据筛选条件过滤文章
    let filteredPosts = blogPosts;
    if (filter !== 'all') {
        filteredPosts = blogPosts.filter(post => post.tags.includes(filter) || post.category === filter);
    }
    
    const currentPosts = filteredPosts.slice(startIndex, endIndex);
    const blogList = document.querySelector('.blog-list');
    blogList.innerHTML = '';
    
    // 当前语言
    const currentLang = document.body.classList.contains('en') ? 'en' : 'zh';
    
    // 生成文章卡片HTML
    currentPosts.forEach(post => {
        const postElement = document.createElement('article');
        postElement.className = 'blog-post';
        postElement.innerHTML = `
            

${post.title[currentLang]}

${post.excerpt[currentLang]}

`; blogList.appendChild(postElement); }); // 更新分页状态 updatePagination(page, Math.ceil(filteredPosts.length / postsPerPage)); }

4.4 性能优化技巧

优化策略
在JavaScript实现中采用了多种性能优化措施:

  • 事件委托 - 减少事件监听器数量,提高性能
  • 防抖与节流 - 优化频繁触发的事件处理(如搜索、滚动)
  • 异步加载 - 非关键资源延迟加载
  • 代码模块化 - 按需加载不同功能模块
  • 缓存DOM查询 - 避免重复查询DOM元素

防抖示例
防抖函数和搜索优化实现:

// 防抖函数实现
function debounce(func, delay) {
    let timeout;
    return function(...args) {
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            func.apply(this, args);
        }, delay);
    };
}

// 博客搜索实现(带防抖)
document.addEventListener('DOMContentLoaded', function() {
    const searchInput = document.querySelector('.blog-search input');
    
    // 使用防抖优化搜索,避免每输入一个字符就触发搜索
    const debouncedSearch = debounce(function() {
        const searchTerm = this.value.toLowerCase().trim();
        performSearch(searchTerm);
    }, 300);
    
    if (searchInput) {
        searchInput.addEventListener('input', debouncedSearch);
    }
});

五、部署方案

5.1 部署选项

可选部署平台
作为一个纯静态网站,这个博客有多种部署选择:🚀

  • GitHub Pages - 免费且集成Git工作流,是个人博客的理想选择
  • Netlify - 提供持续部署、自定义域名和HTTPS支持
  • Vercel - 针对前端项目优化,提供全球CDN加速
  • 传统Web主机 - 通过FTP上传静态文件
  • 云存储服务 - 如阿里云OSS、腾讯云COS、AWS S3等

5.2 GitHub Pages部署

部署流程
我选择使用GitHub Pages作为主要部署平台,部署流程如下:🔄

  1. 创建名为username.github.io的GitHub仓库(其中username是你的GitHub用户名)
  2. 将本地代码推送到该仓库
  3. 在仓库设置中启用GitHub Pages
  4. (可选)配置自定义域名并设置HTTPS

部署命令
GitHub Pages部署的Git命令示例:

# 初始化Git仓库(如果尚未初始化)
git init

# 添加所有文件到Git
git add .

# 提交更改
git commit -m "Initial commit for blog deployment"

# 添加GitHub远程仓库
git remote add origin https://github.com/username/username.github.io.git

# 推送代码到主分支
git push -u origin main

5.3 CI/CD实现

自动化部署
为了简化更新流程,我设置了基本的CI/CD流水线:⚙️

  • 使用GitHub Actions自动部署变更
  • 配置简单的检查确保HTML、CSS和JavaScript文件的质量
  • 实现自动化测试,验证网站各个页面是否正常加载

工作流配置
GitHub Actions工作流示例:

# GitHub Actions工作流示例 (.github/workflows/deploy.yml)
name: Deploy to GitHub Pages

on:
  push:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Validate HTML
        run: |
          npx html-validate "**/*.html"

      - name: Deploy
        uses: JamesIves/github-pages-deploy-action@4.1.4
        with:
          branch: gh-pages
          folder: .

5.4 性能监控

监控工具
部署后,我使用以下工具监控网站性能:📊

  • Google Analytics - 分析访问流量和用户行为
  • Google Search Console - 监控搜索引擎索引状态
  • Lighthouse - 定期检查性能、可访问性和SEO得分
  • PageSpeed Insights - 分析并优化页面加载速度

持续优化
基于监控结果,持续进行优化调整,包括:🔧

  • 优化图片尺寸和格式(如使用WebP)
  • 实现图片懒加载
  • 根据用户访问数据调整内容组织
  • 优化关键渲染路径,提高首屏加载速度

结语

学习收获
从零构建个人博客是一次宝贵的学习经历,它不仅强化了我对Web基础技术的理解, 也让我深入思考用户体验、性能优化和可访问性等重要方面。 通过这个项目,我实践了"简洁高效"的设计理念,打造了一个既满足功能需求又具备个性化特色的博客平台。🎓

技术总结
这个博客采用纯静态设计,优先考虑内容展示和用户体验, 同时通过模块化的JavaScript实现了主题切换、多语言支持和动态内容加载等特性。 部署在GitHub Pages上,既节省了成本,又简化了维护流程。💻

实用建议
对于有兴趣构建自己博客的读者,我的建议是:从简单开始,专注于内容而不是复杂的技术栈; 逐步迭代,根据实际需求添加功能;重视性能和用户体验,它们往往比华丽的效果更重要。💡

核心理念
最后,博客的核心永远是内容。技术只是展示内容的工具,真正吸引读者的是有价值、有见解的文章。 希望这篇技术分享能对你有所启发,欢迎在评论区交流你的想法和经验! 💻✨

— HealthJian ✍️

评论

成为第一个评论的人! 🎉