You need to enable JavaScript to run this app. 如何在SvelteKit中集成sqlite3?
优惠活动
大模型
产品
解决方案
定价
更多

如何在SvelteKit中集成sqlite3?

SvelteKit 集成 SQLite3 落地实现方案

核心前提:SQLite 是嵌入式服务端数据库,所有数据库操作仅能在 SvelteKit 服务端代码(+page.server.js/ts、+server.js/ts、hooks、src/lib/server/ 目录)运行,绝对禁止在浏览器前端代码中导入相关模块,否则会触发原生模块加载报错。

依赖选型

  • 稳定生产场景优先选 better-sqlite3:同步API风格、性能优异、不需要写冗余的异步回调,和轻量全栈项目的匹配度最高
  • Node 22及以上版本可直接使用内置的 node:sqlite 模块,无需安装第三方依赖,仅适配新Node版本的运行环境
  • 不推荐传统的 sqlite3 npm包:异步回调风格写起来繁琐,性能和同步API版本差距明显

初始化全局数据库连接

SvelteKit开发模式下会频繁热更新模块,如果每次请求都新建数据库连接,很快会触发系统文件句柄耗尽报错,因此需要把连接实例挂到全局对象上做缓存。

  1. 新建 src/lib/server/db/index.js 文件(SvelteKit会自动给server目录下的代码加服务端边界,不会打包到前端产物)
  2. 写入连接初始化逻辑:
// src/lib/server/db/index.js
import Database from 'better-sqlite3';
import { dev } from '$app/environments';

// 全局缓存实例,避免热更新重复建连
const globalForDb = globalThis;
// 数据库文件存储路径
const dbPath = dev ? './data/dev.db' : './data/prod.db';

// 初始化连接
const db = globalForDb.db ?? new Database(dbPath);
// 开启WAL模式提升读写并发性能,打开外键约束
db.pragma('journal_mode = WAL');
db.pragma('foreign_keys = ON');

// 开发环境下把实例挂到全局
if (dev) globalForDb.db = db;

// 项目表结构初始化逻辑直接在这里执行,示例:
db.exec(`
  CREATE TABLE IF NOT EXISTS posts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    content TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
  )
`);

// 封装常用的操作方法,减少重复写prepare的代码
export const get = (sql, params = []) => db.prepare(sql).get(...params);
export const query = (sql, params = []) => db.prepare(sql).all(...params);
export const run = (sql, params = []) => db.prepare(sql).run(...params);
  1. 配套配置:
  • 项目根目录新建 data 文件夹,用于存放数据库文件
  • 在 .gitignore 中加入 *.db、*.db-wal、*.db-shm,避免把数据库文件提交到代码仓库
  • 确保运行SvelteKit的系统账号对 data 目录有读写权限

构建配置调整

因为 better-sqlite3 是原生Node模块,不能被Vite打包到bundle里,需要在 svelte.config.js 中标记为外置依赖:

// svelte.config.js
const config = {
  kit: {
    // 适配你选的部署适配器
    adapter: YourAdapter,
    // 原生模块不参与打包
    external: ['better-sqlite3']
  }
};
export default config;

路由层调用示例

页面服务端加载(+page.server.js)

// src/routes/posts/+page.server.js
import { query, run } from '$lib/server/db';
import { error } from '@sveltejs/kit';

// 页面加载时直接查数据库拿数据
export async function load() {
  const postList = query('SELECT id, title, created_at FROM posts ORDER BY created_at DESC');
  return { postList };
}

// 处理表单提交动作
export const actions = {
  createPost: async ({ request }) => {
    const formData = await request.formData();
    const title = formData.get('title');
    const content = formData.get('content');
    if (!title?.trim() || !content?.trim()) throw error(400, '标题和内容不能为空');
    run(
      'INSERT INTO posts (title, content) VALUES (?, ?)',
      [title, content]
    );
  }
}

独立API路由(+server.js)

// src/routes/api/posts/+server.js
import { json } from '@sveltejs/kit';
import { query } from '$lib/server/db';

export function GET() {
  const postList = query('SELECT id, title, created_at FROM posts');
  return json(postList);
}

常见踩坑说明

  • 开发模式频繁热更新导致的文件句柄泄露:只要按全局实例缓存的方案配置,就不会出现重复建连的问题
  • 生产构建报错“找不到better-sqlite3模块”:90%的原因是把数据库相关代码导入到了非服务端上下文(比如放了src/lib/下而不是src/lib/server/),检查所有导入db的文件位置,确保所有调用都在服务端边界内
  • 部署到只读文件系统的云平台(比如部分Serverless平台)时,本地磁盘目录没有写权限,需要把数据库文件路径临时改到系统指定的临时可写目录(比如Linux下的/tmp),这种场景其实更推荐用专门的云数据库,SQLite的体验会打折扣

内容的提问来源于stack exchange,提问作者Anil Bhattarai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 07:06:03