8 ms·
This is how I move fast and break nothing. By having fullstack type-safety from database all the way to the frontend with auto-completion. My current stack: +
by hu3 4y ago
This is how I move fast and break nothing. By having fullstack type-safety from database all the way to the frontend with auto-completion. My current stack:
+ SvelteKit (could be Next, Nuxt, Solid or any other TypeScript framework)
+ tRPC (typed calls between frontend and backend, https://trpc.io https://trpc.io)
+ trpc-sveltekit (glues SvelteKit and tRPC, https://github.com/icflorescu/trpc-sveltekit https://github.com/icflorescu/trpc-sveltekit)
+ Prisma (ORM, https://www.prisma.io https://www.prisma.io)
- mitch3x3 4y agoHow are you liking Prisma compared to a pure SQL approach?
- qudat 4y agoWhen I used prisma a few years ago I was not impressed and it couldn't do a lot of what I needed so I had to dump into raw sql queries anyway. It was easier for me to use knex and get the types mostly right.
- Trufa 4y agoA lot has changed in the past years of Prisma, it's a really great tool, to be honest, "raw sql" escape hatches to do anything raw when you need it, if you haven't tried it in years, I'd recommend you to try again since if you tried it years ago, it was a very different maturity level.
- abraxas 4y agoDo they (Prisma) still rely on a Rust sidecar? This caused multiple issues with container deployment and the CI/CD pipeline of my employer.
- braden-lk 4y agoI believe the sidecar is optional now, and I think even the one that exists comes in the form of their paid service called Prisma Proxy. It doesn’t seem necessary for most use cases.
- lf-non 4y agoYou should take a look at ts-sql-query [1] - it is not as popular as the older alternatives that have been around for a while, but it is a very feature rich query builder that takes type safety very seriously and supports most mainstream databases. [1] https://ts-sql-query.readthedocs.io https://ts-sql-query.readthedocs.io
- devjab 4y agoI'm not the person you ask, but we use fullstack Typescript in our dev department. We're a weird mix of a green energy company and an investment bank, so inhouse development is very small-scale, and this means you share resources. Using one language for everything helps with this, since the one person who is really good at React can take a vacation or a sickday without being glued to a laptop since everyone else can also work on the front-end even though it's not their daily thing (and vice versa). More than that though it lets us do things like code reviews, troubleshoot solutions and generally work together really well, even though we're working on very different projects. It also lets us build libraries that can be used for everything. One example is our ODATA query and client library, which makes it incredibly easy to debug issues related to it, because everyone uses it. Anyway, the one place where Typescript isn't great in the fullstack approach is the Database stuff. We used Prismo for the better part of a year, until we eventually moved on to Mikro-orm which has been great so far. I'm personally not a big fan of OOP or "over architecture", because I've seen how bad it can go too many times. Instead I favour functional programming and keeping things as simple as possible, even having "almost duplicate" code once in a while. So with this in mind, it may strike you as odd that we moved from Prisma to Mirko-orm, but Prisma just clashes with the way we want an ORM to work in so many ways. Maybe this is by design. Prisma doesn't want to be a "real" ORM after all, but things like having to put everything in a single schema file is bothersome. Yes, you can put it in different files and then cat them together, but that leads to other issues. Like the VSC Prisma extension highlights not working outside the main Prisma.Schema file. More than that though. We like to have "ID, UpdatedAt, UpdatedBy, CreatedAt" sort of things on basically all our models, and since Prisma doesn't have the inheritance I almost never use, that means you need to duplicate it soooo many times. It's also hard to write generic methods for basic CRUD stuff because of the way Prisma uses the Prisma Client Classes it auto-generates to operate. On top of that, migrations can't go backwards in Prisma. Some of these issues are on the Prisma road map, others aren't, and you're always going to bang heads with an ORM, but Prisma just didn't feel as mature as it's extremely excellent documentation (and marketing) might lead you to believe in my experience. I can certainly see myself using it again, once their roadmap is a little further ahead though.
- ravenstine 4y agoDuplicate code is one of the biggest near-non-problems programmers waste a ton of time trying to address. Sure, duplication isn't a goal, but DRY shouldn't hold back work as long as it has no meaningful consequence on performance. In some cases, duplication is a good thing, but your average programmer will address duplication by making a routing more complicated and further away from where it's being used. This is often a mistake. Worse yet is when programmers DRY up tests. Tests are the worst place to be applying DRY. The point of testing isn't to write an entirely new application on top of your actual application. If you're DRYing up your tests a lot, you're probably writing a second application and should probably stop doing that.
- bottlepalm 4y agoI'm using prisma with postgres. It's pretty nice. You define all your tables in their custom schema format which has VS Code integration and lots of type checks so it will tell you if there's a problem with the schema. You can generate types from the schema file automatically and also a statically typed ORM layer that will let you write queries against those tables with full code completion. It also will generate migration scripts for you when your schema changes. It's not as good as EF by a long shot (nothing really is), but for most queries it works fine. You can also use SQL or stored procs for the exception cases which no ORM ever fully replaces anyways.
- kennethh 4y agoVery interesting to hear some feedback on how Prisma is compared to like EF. Perhaps better to use EF + graphql layer?
- rahimnathwani 4y agoI'd love to browse a sample codebase. Do you know of any non-trivial open source projects using this stack?
- mattwoodnyc 4y agohttps://trpc.io/docs/example-apps https://trpc.io/docs/example-apps
- rahimnathwani 4y agoThanks. Here's the SvelteKit example linked on that page: https://github.com/icflorescu/trpc-sveltekit-example https://github.com/icflorescu/trpc-sveltekit-example
- whycombagator 4y agoHow do you typically deploy such a stack?
- jmull 4y agoPersonally, I'd remove tRPC on down (and choose a database). It's nice there's type-safety between layers, but that's a bunch of layers that you don't even need. (A layer that doesn't exist takes is 100% type-safe and takes 0 hours to develop and maintain).
- kekkidy 4y ago
- deepsun 4y agoIn Mongo you don't need to manage a schema, because it's SCHEMALESS! /s
- shepherdjerred 4y ago> A layer that doesn't exist takes is 100% type-safe How are you ensuring your database accesses are type-safe in this case?
- jmull 4y agoThat's fair... I do typically have a layer that sits at the level of an ORM, whose purpose is to reduce boilerplate and handle/verify types. So I can't really claim I have nothing at the ORM level... However... In my experience, when you pull in an off-the-shelf ORM and an off-the-shelf RPC framework you end up building app-level wrappers anyway to deal with the complexity and impedance mismatch between what you want your app to use for data access code and what layer provides. So I think you might as well put your app-level database wrapper as directly around the database as you can manage (that probably means using the common, unopinionated client for your db... e.g., node-postgres for server-side javascript and postgres, or whatever the equivalent is for your backend/database).
- bearjaws 4y agoAnyone know a good way to solve Prisma memory usage? We use a database per customer and each one adds 50-80mb of RAM. Our backend currently consumes 2-3GiB of RAM to host less than 100 customers... App server has GC pauses of 50-80ms as a result of the memory usage.
- meowtimemania 4y agohow many customers do you have?
- 5Qn8mNbc2FNCiVV 4y agoIf you use a database per customer you should also run a node process per customer. I don't know what exactly you're selling, but that bit of RAM should be in budget alone for the reason that you don't want the requests of customers slowing each other down I recently jumped over that "trying to minimize resources" hurdle myself because it's just not economically correct for me to spend even an hour of my time when I can host a few months worth of servers for that money
- gmaster1440 4y agoCurious how you handle `request.formData()` in Form Actions and ensuring type safety there.
- naasking 4y ago> Curious how you handle `request.formData()` in Form Actions and ensuring type safety there. Hopefully the same way typed programming languages do it: parsing and type checking.
- hu3 4y agoWe use and recommend Zod for that: https://github.com/colinhacks/zod#error-handling https://github.com/colinhacks/zod#error-handling
- harunurhan 4y agoLike any user input, you do runtime type-checking and validation. TypeScript is especially great for that because it has type narrowing [0]. [0] - https://www.typescriptlang.org/docs/handbook/2/narrowing.html https://www.typescriptlang.org/docs/handbook/2/narrowing.htm...
- 5e92cb50239222b 4y agoSame, but with ASP.NET (which produces an OpenAPI specification) + Entity Framework on the server, React + TypeScript on the client (which consume that specification through openapi-generator). https://github.com/OpenAPITools/openapi-generator https://github.com/OpenAPITools/openapi-generator I chuckle every time I read claims about Go (or whatever) being amazingly productive. I don't think it's possible to beat this stack with regards to both productivity and ease of long-term support, at least without going to very niche technologies where you'll have other problems. Database schema is generated from models described in C# (or reverse-engineered from an existing schema). You don't have to compromise your schema to satisfy the ORM (another claim I often read on HN), as it's very adaptable to your needs. Migrations are generated automatically — change your models, ask it to generate migration code in C# + a SQL migration script, review the generated SQL, and apply. The vast majority of database queries (pretty much everything besides reports) is written in type-safe LINQ, which makes it easy to refactor code, and also construct & combine queries at runtime. Unlike that specification abomination JPA expects you to use, LINQ queries look something like this: var latestOrders = _db.Orders .Where(ord => ord.CreatedAt >= DateTime.Today) .Where(ord => !ord.Deleted) .OrderByDescending(ord => ord.CreatedAt) .Take(25) .Select(ord => new { OrderId = ord.Id, Customer = ord.Customer.Name, CreatedAt = ord.CreatedAt, Products = ord.Products.Select(prod => new { ProductId = prod.Id, Title = prod.Title, }) }) .ToList(); If you change your schema and forget to update one of the queries accordingly (although using an IDE makes this pretty much impossible), your code won't even compile.
- jakub_jo 4y agoThat sounds impressive.
- melony 4y agoDo you still need to pass around "Data Transfer Objects" to do simple parameter binding?
- jeremycarter 4y agoThey form the type safety
- gavinray 4y agoI use the same, but with Hasura and Next.js with GraphQL + Next.js + GraphQL Zeus / GraphQL Code Generator (typed calls between frontend/backend) + Hasura (generates GraphQL API for database)
- wildermuthn 4y agoWe do something similar. GraphQL type generation is pretty amazing, especially with heavy use of co-located queries on the FE and a typed ORM like prisma on the BE.
- deathemperor 4y agoSame here. I use Apollo Client. React. Hasura
- capableweb 4y ago> This is how I move fast and break nothing Absolutely impressive how you are one of the first to find a approach that leads to a 100% bug-free development methodology. Or, you still have bugs right, so sometimes things break? Maybe you meant something like: This is how I move fast and don't have a certain section of bugs anymore?
- throwaway39048 4y agoI bet they don't even move "fast" since that's relative and we haven't determined any baseline paramters. Very misleading. The comment should be "This is how I move (metaphorically speaking, not physically e.g. increased typing speed) with what I perceive to be faster than alternative stacks that I have explored and that doesn't have a certain section of bugs anymore".
- jherdman 4y agoI'd love to hear about your testing story with Prisma. I recently looked into it but was disappointed to see the recommended approach was more or less to nuke the contents of the DB (https://www.prisma.io/docs/guides/testing/integration-testing https://www.prisma.io/docs/guides/testing/integration-testin...) instead of just rolling back a named transaction at the end of a test (a la https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.Sandbox.html https://hexdocs.pm/ecto_sql/Ecto.Adapters.SQL.Sandbox.html, or just about every other framework I've used with Ruby or Elixir).
- marmada 4y agoI wonder if with Next.JS server components, we can just get rid of tRPC + trpc-sveltekit.
- JoeyJoJoJr 4y agoYou should also mention Zod, which acts as the type safe glue between the different boundaries. I have been using Google Sheets as a kind of hacky database. By defining the schemas in Zod I am able to automatically validate my sheets data and coerce the string cell values into their proper types. Zod schemas can be used all over the stack, imported for form validation, and avoid heaps of duplication and tests.
- mccorrinall 4y agoWhile Zod is hyped by Next.ja developers (I think mostly because Theo Brown has such a huge reach), I think Ajv is better, because it lets you generate OpenAPI documentation and it fully json schema compliant. I really like nextjs for its opinions on the frontend part, but it is lacking these strong, but great opinions on the backend. Wish love to see some design decisions from fastify adopted here. Matteo did really do some great stuff.
- intelekshual 4y agoZod has plugins that let you generate OpenAPI specs (and TS types, and JSON Schema, etc.) from your Zod schemas, so if that's the only reason you think Ajv is better, then it might be time to take another look at Zod? It really is great, especially if you buy into the "parse, don't validate" principle that it's built around.
- pier25 4y agoFastify is excellent. I wish these new full stack frameworks were closer to that.
- bdougherty 4y agoWhat is the benefit of tRPC over built-in SvelteKit data loading?
- yamtaddle 4y agoI prefer static types all the way, but my looser rule I've come up with in order to play nicely with others is that you're not allowed to interface something with poor type definitions/enforcement with another thing that's also bad at that. Including transport/wire formats, so if you're presenting JSON you'd better be able to tell me a good story about type safety on both the sender and receiver. That at least keeps the blast radius of type-related bugs very limited, and makes it easier to figure out where the problem is.
- trillic 4y agoMight I recommend https://jawj.github.io/zapatos/ https://jawj.github.io/zapatos/ to remove the last 3 lines of your stack.
- tommica 4y agoNice share!
- rapind 4y agoPostgresql > PostgREST > Elm
- topicseed 4y agoOpenapi, then codegen on both ends — frontend (orval) with TS and react-query, and backend with golang (openapi codegen) for the server's request and response objects. Works a treat.
- httgp 4y agoHow well does tRPC work if the API consumer isn’t built with TypeScript?
- hu3 4y agoI haven't used this, but check: https://github.com/jlalmes/trpc-openapi https://github.com/jlalmes/trpc-openapi