一、为什么是 Remix/Prisma/Sqlite ?

最主要的一个原因就是轻量级别,轻量级体现在只需要一个 Remix 服务即可。

  • Remix 轻量级 React 全栈框架
  • Prisma 轻量级 ORM 库
  • Sqlite 嵌入式无需启动服务的数据库

二、Prisma 命令提前看

如果你还不熟悉 Prisma 的常用命令,那么下面盘点的常用命令,提前熟悉,后面会用到:

命令 说明
prisma init 初始化一个新的Prisma项目
prisma migrate dev 将数据模型应用于数据库
prisma migrate reset 回滚数据库到最初状态
prisma studio 启动一个Web界面,用于查看和修改数据库中的数据
prisma generate 生成Prisma客户端代码,用于连接和操作数据库
prisma format 格式化Prisma模型文件
prisma validate 验证Prisma模型文件的正确性
prisma db seed 开发环境将种子数据添加到数据库中
npx prisma migrate reset 重置您的数据库并将其恢复到迁移历史中的最初状态

三、在 Remix 中添加 Sqlite 和 Prisma 的流程如下:

快速初始化一个 Remix 项目:

pnpm dlx create-remix@latest <app_name>

1、安装依赖

pnpm install prisma -g # 全局安装

2、用 sqlite 初始化 prisma

prisma init --datasource-provider sqlite

命令自动生成文件如下:

  • .env 文件
DATABASE_URL="file:./dev.db"
  • prisma/schema.prisma 文件
generator client {
  provider = "prisma-client-js"
}
datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

3、在 Schema 文件中添加模型

model User {
  id    Int     @id @default(autoincrement())
  name  String
  email String  @unique
  posts Post[]
}
model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String
  author    User?    @relation(fields: [authorId], references: [id])
  authorId  Int?
}

4、生成客户端代码

"prisma generate" 根据 Prisma schema 文件生成 Prisma Client 代码,该代码提供了一种类型安全的方法来访问数据库,简化了应用程序与数据库交互的过程,减少了手动编写重复代码的工作量。

5、使用迁移命令

npx prisma migrate dev --name init

每一次 Schema 发生变化的时候,都要调用此命令生成新的迁移文件(生成 sql 文件,数据文件件,安装包)

生成文件:

├── dev.db
├── dev.db-journal
├── migrations
│   ├── 2x23x42x1x3x4x_init
│   │   └── migration.sql
│   └── migration_lock.toml

同时自动安装了 npm 包:

  • prisma
  • @prisma/client

6、在 studio 中查看

npx prisma studio

会启动一个 web 服务,在浏览器中操作数据库,不需要一个单独的客户端。

  • 初始界面

  • 模型中

在 stdio 也可以对数据库进行相应的增删改查工作。

7、在 Remix 中使用

①. 对外暴露 db

  • db.server.ts 文件
import { PrismaClient } from "@prisma/client";
let prisma: PrismaClient;
declare global {
  var __db__: PrismaClient;
}
if (process.env.NODE_ENV === "production") {
  prisma = new PrismaClient();
} else {
  if (!global.__db__) {
    global.__db__ = new PrismaClient();
  }
  prisma = global.__db__;
  prisma.$connect();
}
export { prisma };

②. 抽象模型层

在 app/models 下面定义模型,以是一个示例:

import { prisma } from "~/db.server";
export async function getUserById(id: User["id"]) {
  return prisma.user.findUnique({ where: { id } });
}
export async function getUserByEmail(email: User["email"]) {
  return prisma.user.findUnique({ where: { email } });
}

③. 在 action/loader 中使用模型层操作数据库

import { createUser, getUserByEmail } from "~/models/user.server";
export const action = async ({ request }: ActionArgs) => {
    // ...
    const existingUser = await getUserByEmail(email);
    // ...
    const user = await createUser(email, password);
}

④. 额外的 seed 初始化

如果需要在初始化的时候,初始化一些数据,那么可以定义 prisma/seed.ts 文件。

import { PrismaClient } from "@prisma/client";
const db = new PrismaClient();
async function seed() {
    // use db write data ...
}
seed();

然后在 package.json 中定义 seed 字段

{
  "name": "my-project",
  "version": "1.0.0",
  "prisma": {
    "seed": "ts-node prisma/seed.ts"
  },
  "devDependencies": {
    "@types/node": "^14.14.21",
    "ts-node": "^9.1.1",
    "typescript": "^4.1.3"
  }
}

然后配合命令: npx prisma db seed 初始出初始化数据

四、流程总结

  • prisma init --source-provider sqlite
  • 添加 model
  • 生成客户端
  • prisma migrate dev --name init
  • npx prisma studio
  • 使用客户端操作
  • 外额的 seed 初始化

五、小结

prisma 能提供了新的 ORM 操作数据库,cli 命令生成的内容相对较多。熟悉之后会变得简单容易。并且提供 studio 在浏览器中访问数据库,而不需要安装多余的客户端,对前端友好,是轻量级全栈开发很好选择。