在 Next.js 项目中使用 SQLite

无论你是做一个MVP,还是完整的 Web 应用,存储和读取数据都至关重要。SQLite 是一款可移植、零配置的轻型数据库,能让你快速上手。

1. 为什么要在 Next.js 中使用 SQLite?

  • Next.js 是构建服务端器 React 框架,自动处理路由、SSR、代码分割等。
  • SQLite 是一款文件型 SQL 数据库引擎,轻量、快速且零配置。

Next.js + SQLite 的优势:

  • 简单设置:SQLite 只是普通文件存储,无需运行复杂的数据库服务器。
  • 客户端查询:可直接在 Next.js 应用中执行查询,无需额外后端。
  • 离线持久化:用户短暂离线后数据依然存在。
  • 可移植性:数据库文件可在不同环境与平台间轻松迁移。
  • 可扩展性:SQLite 足够应付大多数简单查询需求,后期可平滑迁移到 Postgres、MySQL 等。

在快速原型阶段,SQLite 让你无需搭建独立数据库服务器即可验证核心功能。

2. 安装依赖

在 Next.js 中使用 SQLite,需安装以下依赖:

js 复制代码
npm install sqlite3
npm install @mapbox/node-sqlite3
npm install sqlite

3. 创建数据库

pages/api 目录下新建 db.js

js 复制代码
// pages/api/db.js
import sqlite3 from 'sqlite3'
import { open } from 'sqlite'

// 打开 SQLite 数据库连接
export async function openDb() {
  return open({
    filename: './mydb.db',
    driver: sqlite3.Database
  })
}

该文件会在项目根目录创建名为 mydb.db 的 SQLite 文件。若文件不存在,首次连接时会自动创建。

4. 定义表结构

pages/api 目录下创建 seed.js,用于初始化数据库表:

js 复制代码
// pages/api/seed.js
import { openDb } from './db'

async function setup() {
  const db = await openDb()

  // 创建 posts 表
  await db.exec(`
    CREATE TABLE posts (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      title TEXT,
      content TEXT
    );
  `)

  // 插入示例数据
  await db.run(
    'INSERT INTO posts (title, content) VALUES (?, ?)',
    'Hello World',
    'My first blog post!'
  )

  await db.close()
}

setup().catch(err => console.error(err.message))

运行脚本:

js 复制代码
node pages/api/seed.js

至此,数据库与表已准备就绪。

5. 获取数据(服务端渲染)

pages/index.js 中利用 getServerSideProps 查询数据并传给组件:

js 复制代码
// pages/index.js
import { openDb } from './api/db'

export async function getServerSideProps() {
  const db = await openDb()
  const posts = await db.all('SELECT * FROM posts')
  await db.close()

  return {
    props: { posts }
  }
}

function Home({ posts }) {
  // 在 UI 中渲染 posts
  return (
    <div>
      <h1>Posts</h1>
      <ul>
        {posts.map(p => (
          <li key={p.id}>
            <h2>{p.title}</h2>
            <p>{p.content}</p>
          </li>
        ))}
      </ul>
    </div>
  )
}

export default Home

6. 实现 CRUD 操作

6.1 创建(Create)

pages/api/posts/create.js

js 复制代码
import { openDb } from '../db'

export default async function handler(req, res) {
  const { title, content } = req.body
  const db = await openDb()
  const result = await db.run(
    'INSERT INTO posts (title, content) VALUES (?, ?)',
    [title, content]
  )
  await db.close()
  res.status(201).json(result)
}

6.2 读取(Read)

pages/api/posts/[id].js

js 复制代码
import { openDb } from '../../db'

export default async function handler(req, res) {
  const id = req.query.id
  const db = await openDb()
  const post = await db.get('SELECT * FROM posts WHERE id = ?', [id])
  await db.close()
  res.status(200).json(post)
}

6.3 更新(Update)

pages/api/posts/update.js

js 复制代码
import { openDb } from '../db'

export default async function handler(req, res) {
  const { id, title, content } = req.body
  const db = await openDb()
  await db.run(
    `UPDATE posts SET title = ?, content = ? WHERE id = ?`,
    [title, content, id]
  )
  await db.close()
  res.status(200).json({ message: 'Post updated' })
}

6.4 删除(Delete)

pages/api/posts/delete.js

js 复制代码
import { openDb } from '../db'

export default async function handler(req, res) {
  const { id } = req.body
  const db = await openDb()
  await db.run('DELETE FROM posts WHERE id = ?', [id])
  await db.close()
  res.status(200).json({ message: 'Post deleted' })
}

7. 客户端数据获取(SWR/React Query)

暴露统一的 /api/posts 端点:

js 复制代码
// pages/api/posts.js
import { openDb } from './db'

export default async function handler(req, res) {
  const db = await openDb()
  const posts = await db.all('SELECT * FROM posts')
  await db.close()
  res.status(200).json(posts)
}

在客户端组件中:

js 复制代码
useEffect(() => {
  async function fetchPosts() {
    const res = await fetch('/api/posts')
    const posts = await res.json()
    // 更新组件状态
  }
  fetchPosts()
}, [])

sqldocs.org/sqlite-data...

相关推荐
Q_Q5110082854 小时前
python+django/flask+uniapp基于微信小程序的瑜伽体验课预约系统
spring boot·python·django·flask·uni-app·node.js·php
该用户已不存在8 小时前
PHP、Python、Node.js,谁能称霸2025?
python·node.js·php
Q_Q51100828512 小时前
python+nodejs+springboot在线车辆租赁信息管理信息可视化系统
spring boot·python·信息可视化·django·flask·node.js·php
濮水大叔14 小时前
VonaJS多租户🔥居然可以同时支持共享模式和独立模式,太牛了🚀
typescript·node.js·nestjs
前端伪大叔18 小时前
第12篇|🔌 Freqtrade 交易所接入全解:API、WebSocket、限频配置详解
python·node.js
Q_Q51100828519 小时前
python+django/flask哈利波特书影音互动科普网站
spring boot·python·django·flask·node.js·php
Q_Q196328847520 小时前
python+springboot+uniapp基于微信小程序的巴马旅居养老系统 旅游养老小程序
spring boot·python·小程序·django·flask·uni-app·node.js
小白64021 天前
前端梳理体系从常问问题去完善-工程篇(webpack,vite)
前端·webpack·node.js
寒山李白1 天前
npm镜像源配置指南
前端·npm·node.js
Q_Q19632884751 天前
python+django/flask+springboot个性化旅游推荐系统(数据可视化) 景点推荐 路线匹配 用户画像建模 智能搜索筛选 图文展示系统
spring boot·python·django·flask·node.js