Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ This article is part of a series of [live streams](https://www.youtube.com/playl

<Youtube videoId="SvtXgRA7KsE" />

:::note[Part one of four]
This is the first article in the **Backend with TypeScript, PostgreSQL & Prisma** series:

1. **Data modeling & CRUD** (you're here)
2. [REST, validation & tests](/backend-prisma-typescript-orm-with-postgresql-rest-api-validation-dcba1ps7kip3)
3. [Authentication & authorization](/backend-prisma-typescript-orm-with-postgresql-auth-mngp1ps7kip4)
4. [CI & deployment](/backend-prisma-typescript-orm-with-postgresql-deployment-bbba1ps7kip5)
:::

## Introduction

The goal of the series is to explore and demonstrate different patterns, problems, and architectures for a modern backend by solving a concrete problem: **a grading system for online courses.** This is a good example because it features diverse relations types and is complex enough to represent a real-world use-case.
Expand Down Expand Up @@ -69,6 +78,10 @@ If you're using Visual Studio Code, the [Prisma extension](https://marketplace.v

> **Note**: If you don't want to use Docker, you can set up a [local PostgreSQL database](https://www.prisma.io/dataguide/postgresql/setting-up-a-local-postgresql-database) or a [hosted PostgreSQL database on Heroku](https://dev.to/prisma/how-to-setup-a-free-postgresql-database-on-heroku-1dc1).

:::ppg[Don't want to run Docker?]
You don't need a local container to follow along. For a database in one command, run [`npx create-db`](https://www.prisma.io/docs/postgres/introduction/npx-create-db): it spins up a [Prisma Postgres](https://www.prisma.io/postgres) instance with no signup and prints a connection string you can drop straight into `DATABASE_URL`. The instance is yours for 24 hours, and you can claim it to your account to keep it. If you'd rather stay fully offline, [run Prisma Postgres locally](https://www.prisma.io/docs/postgres/database/local-development) instead. Every schema, migration, and query step below works the same with any of these.
:::

## Clone the repository

The source code for the series can be found on [GitHub](https://github.com/2color/real-world-grading-app).
Expand Down Expand Up @@ -861,3 +874,9 @@ In the next parts of the series, you'll learn more about:
- Deployment

**Join for the [the next live stream](https://youtu.be/d9v7umfMNkM) which will be streamed live on YouTube at 6:00 PM CEST August 12th.**

:::tip[A note on versions]
This series uses an older version of Prisma ORM. The data modeling and query patterns still hold, but the tooling has moved on. [Prisma Next](https://www.prisma.io/blog/the-next-evolution-of-prisma-orm) is where the ORM is going: you describe your data in one contract file, and it generates the client and migrations from there. For the database, [Prisma Postgres](https://www.prisma.io/postgres) gives you a managed instance you can spin up with [`npx create-db`](https://www.prisma.io/docs/postgres/introduction/npx-create-db). And when you reach deployment in part four, [Prisma Compute](https://www.prisma.io/compute) (public beta) is serverless TypeScript hosting that runs this backend on the same infrastructure as that database, so the app and its database stay in one place.

Next in the series: [REST, validation & tests](/backend-prisma-typescript-orm-with-postgresql-rest-api-validation-dcba1ps7kip3), then [authentication & authorization](/backend-prisma-typescript-orm-with-postgresql-auth-mngp1ps7kip4) and [CI & deployment](/backend-prisma-typescript-orm-with-postgresql-deployment-bbba1ps7kip5).
:::
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ tags:

Prisma ORM historically generated its database client code to `node_modules`. But why does it do this? Let's look at why this decision was made and why we're changing this in the future.

Since its initial release, Prisma ORM has been using _code generation_ to generate a database client (called "Prisma Client") that's tailored to a database schema. The Prisma Client library is auto-generated based on the Prisma schema so that it's aware of their structure and can provide custom, type-safe queries for them.
Since its initial release, Prisma ORM has used _code generation_ to produce a database client (called "Prisma Client") that's tailored to your schema. Because Prisma Client is generated from your Prisma schema, it knows the exact shape of your models and gives you custom, type-safe queries for them.

Code generation isn't the most conventional method in the TypeScript ecosystem and Prisma ORM was one of the first popular libraries to rely on it. To keep things familiar with develoeprs, we decided to generate Prisma Client into the `node_modules` folder by default because that's typically how they're used to integrate third party libraries in their applications.
Code generation isn't a common approach in the TypeScript ecosystem, and Prisma ORM was one of the first popular libraries to rely on it. To keep things familiar, we generate Prisma Client into the `node_modules` folder by default, since that's how developers are used to integrating third-party libraries into their applications.

While it was possible from the beginning to choose a custom location for the generated code via the [`output`](https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path) field, this default gave us a unified behavior across various frameworks and usage contexts of Prisma ORM:

Expand All @@ -34,9 +34,9 @@ Generating Prisma Client into `node_modules` by default ultimately led to a magi

## Why and how are we changing the location of Prisma Client in v7

Since then, developers encountered problems due to the generated code in `node_modules`. Many tools across the JS/TS ecosystem operate under the assumption that the `node_modules` directory won't be modified—except by your package manager (`npm`, `pnpm`, `yarn` etc).
Over time, that default caused problems. Many tools across the JS/TS ecosystem assume the `node_modules` directory is only ever modified by your package manager (`npm`, `pnpm`, `yarn`, and so on).

However, with Prisma ORM, you need to re-generate Prisma Client after every database schema change so that the generated code reflects the latest state of your database. This requirement along with the default choice of putting generated code into `node_modules` violated the assumption of many tools in the ecosystem.
Prisma ORM breaks that assumption. You re-generate Prisma Client after every schema change so the generated code matches your database, which means something other than the package manager is writing to `node_modules`. That is exactly what many tools don't expect.

### Required workarounds when putting generated code into `node_modules`

Expand All @@ -48,9 +48,9 @@ Workarounds for the core issue of the generated code living in `node_modules` ex

### What is changing going forward?

While the initial decision of generating Prisma Client into `node_modules` helped a lot of developers getting started and provided a smooth, unified DX, we also saw that this kind of "magical" behavior often led to unexpected problems when developers were using Prisma ORM.
Generating into `node_modules` helped a lot of developers get started and gave us a smooth, unified DX. But the same "magical" behavior often led to unexpected problems in real projects.

We are currently in the process of [making the DX of using Prisma ORM simpler and more predictable](https://www.prisma.io/blog/prisma-orm-manifesto) by removing magical behavior or unnecessary abstraction layers.
So we're [making Prisma ORM simpler and more predictable](https://www.prisma.io/blog/prisma-orm-manifesto) by removing magical behavior and unnecessary abstraction layers.

As part of this initiative, **we are going to remove the option to generate code into `node_modules` by always requiring an `output` path**.

Expand All @@ -62,6 +62,10 @@ This change will come later this year as part of Prisma ORM v7 and only affect t
- More predictability and no more workarounds due to magical behavior.
- Compliance with the assumption that `node_modules` can only be modified by package managers.

:::note[Where this is heading]
Requiring an `output` path is one step toward a larger goal: treating the generated client as ordinary source code in your project instead of something hidden in `node_modules`. The same principle carries into [Prisma Next](https://www.prisma.io/blog/the-next-evolution-of-prisma-orm), the next major version of Prisma ORM, where generated code lives in your codebase by default so you can read it, commit it, and bundle it like the rest of your app.
:::

### `prisma-client` vs `prisma-client-js` generators

If you've followed our releases, you know that in [v6.6.0](https://github.com/prisma/prisma/releases/tag/6.6.0) we released a new generator, called simply [`prisma-client`](https://www.prisma.io/docs/orm/prisma-schema/overview/generators#prisma-client-early-access):
Expand Down Expand Up @@ -91,7 +95,7 @@ We also changed the default generated Prisma schema that was generated when runn

While we expected this nudge to only have positive effects due to the removal of unpredictable, problematic behaviors and giving more control to developers, a lot of people actually reported issues after they saw the deprecation warning and switched to using a custom `output` path with the `prisma-client-js` generator.

Users started reporting linting failures in `src/generated/prisma`, particularly problematic with e.g. the Next.js dev server which halts operations if linting errors are detected. Since the code is generated, linting errors don't really matter, but users didn't by default have `src/generated` excluded from their linting config.
Users started reporting linting failures in `src/generated/prisma`, which is especially disruptive with the Next.js dev server since it halts when it detects linting errors. The code is generated, so those lint errors don't really matter, but `src/generated` wasn't excluded from their linting config by default.

Other users reported issues with their bundlers, relative path resolution, and a host of other unintended side effects. Overall, we saw a lot of confusion around where to generate Prisma Client and how to bundle it.

Expand All @@ -108,3 +112,7 @@ Here's a TLDR for what all of this means for you today:
- **If you experience issues with an `output` path** (regardless of whether you use the new `prisma-client` or the current `prisma-client-js` generator), please [open a new issue](https://github.com/prisma/prisma/issues) so we can help you resolve the problem.

As always, [reach out to us on X](https://pris.ly/x) or [join our Discord](https://pris.ly/discord) if you have any feedback or questions!

:::ppg[Setting up a new project?]
If you're starting fresh and setting an `output` path as recommended above, you still need a database for `DATABASE_URL` to point at. The quickest option is [`npx create-db`](https://www.prisma.io/docs/postgres/introduction/npx-create-db), which gives you a Prisma Postgres instance with no signup. When you're ready to deploy, [Prisma Compute](https://www.prisma.io/compute) (public beta) is serverless TypeScript hosting that runs your app on the same infrastructure as that database, so you don't manage a separate hosting vendor. And to see where the ORM goes after v7, follow [Prisma Next](https://www.prisma.io/blog/the-next-evolution-of-prisma-orm).
:::
Loading