-
-
Notifications
You must be signed in to change notification settings - Fork 803
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[legacy-framework] [RFC] Blitz App Architecture #73
Conversation
Very exciting! I'm interested as to how Blitz compares to RedwoodJS? They seem to have similar approaches: serverless, minimize boiler-plate, monorepo etc. |
@fmcintosh the single biggest difference is that you develop Blitz apps without building or using an API. Blitz handles all that for you. Whereas Redwood requires you to use GraphQL and everything that GraphQL requires like manually defining resolver input and output types and defining GQL queries for your client. And if you want to use Typescript you need a whole other layer of complexity and boilerplate to get all the TS types you need. |
In a direct conversation with me, someone was pushing back on our decision to not use GraphQL, saying we can solve the cold-start/code-size issue by deploying query and resolvers independently. I decided to answer it here for public benefit: I definitely considered splitting up graphql queries into multiple functions. This solves the serverless graphql problem, but only for your own app. Third-parties still have to use the monolith endpoint. Unless you add a separate gateway to front everything, but then we are back to a bunch of complexity which we are trying to eliminate in the first place. All of the boilerplate and ceremony for using Typescript with Graphql is also a huge reason we aren’t using it. Again, probably solvable, but for what end? See following points. For your own app, you’d primarily use graphql to get a fully typed end-to-end data layer and flexible queries from the frontend. With the Blitz approach, you get both of these without the graphql ceremony. So the only other thing you need a graphql API for is third-parties. But only if your app actually needs a third-party API — many apps don't. For when you actually do need a third-party API, it’s usually better to design and build a separate graphql API than trying to reuse your own internal graphql api. Especially if you are taking the Blitz & Redwood approach where queries and mutations are created explicitly based on the use cases of your own app. Third-parties are going to have different use cases and they need an API designed for those. Your third-party API will probably also have unique requirements around authentication, authorization, rate limiting, etc. That said, we might could still be persuaded to switch to GraphQL if we could find a way to use it while still having a similar framework API as described in this RFC and full static Typescript types without a compiler. |
I really like the manifesto and the technical direction this project has. I have a suggestion: Currently I'm building a Next.js-based server-rendered webapp and I made a decision early on for it to mostly work without JS enabled. To achieve this for mutations, every action is wrapped with an HTML form. I built a custom form component to handle submit event without full page refreshes but if JS is disabled it gracefully degrades. The component is not ready for prime time yet and relies heavily on server response conventions (e.g. Location header) but with an integrated solution like Blitz it would work seamlessly. Another approach could've been to use the API in the current RFC and silently wrap the component with a form to achieve graceful degradation. I don't know if it's possible or feasible but that would be the best of both worlds. |
@frontsideair that's an interesting approach! I think trying to support disabled JS for Blitz would add too much complexity for too little benefit. I.e. most apps are going to need some fancy JS stuff and there's too few people with a requirement to support JS disabled. |
@flybayer I can definitely understand that, I don't imagine anyone actually using the browser with JS disabled. It was a fun experiment to be a good citizen of the web. 😄 |
I love this! One thing though, in Auto Generated HTTP API you say that every query and mutation gets exposed as an URL but, what if I don't want it exposed? |
Well, they have to be exposed at a URL so that you can use them from your React components. How else would you envision it working? |
@lorenzorapetti If you didn’t want people to be able to access your api from outside the app, you could probably add some cors middleware. Check out an example of a next app with api middleware here. |
@merelinguist CORS only affects requests from web browsers. It doesn't affect requests from anywhere outside a browser, such as another server. |
Sorry, true! |
Yeah that might be a dumb question, I didn't think about RPC. I guess it's fine if we'll provide a way to authorize the requests. Just to be sure, the generated URLs and RPC will still be used even if i don't want the app to be serverless? |
@lorenzorapetti yes, we'll for sure have authorization. And yes, RPC will be used for traditional server deployment too. |
For middlewares, we should allow for the following:
One use case of this is for authorisation. We can create a middleware that takes Now even if the above example is not how authorisation will work in Blitz, there could be other use cases for this kind of behaviour. NodeJS allows for this level of control as well. |
We should define what the various default properties are in the If a user is creating a middleware, how should they decide is something should go in the req object, or Context? |
We should also define how the user can do database transactions. This is important since any serious app will require many transactions in them. One more important aspect of transactions is to also be able to specify the isolation level on a per transaction basis (the default one works for most cases). |
Will new features added to Prisma 2 Client become available to use immediately in the Blitz app or will we need to wait for those new Prisma features to be built into the Blitz core first? In other words, is the Blitz core built on top of Prisma 2? Will we be able to use the Prisma Client directly? |
@rishabhpoddar I'm not sure if you are referring to transactions generally like any read/write from the DB, or if you are referring to the explicit transactions that transactional DBs support where all operations within a transaction must succeed or they all fail. I'm assuming you are referring to the later. Blitz doesn't have any opinions about how you talk to your database. The only opinion Blitz has is that you should use Prisma 2. However, you can freely ignore that and use any other Node.js DB client such as Knex. So you will get whatever db transaction support your DB client has.
@cr101 Prisma 2 will be in the package.json of your Blitz app, so you get everything Prisma 2 provides. Blitz doesn't abstract this in any way. |
Regarding middleware. @rishabhpoddar
Yes, I think we'll need that. I'd like to wait to define how to do this until we have a better sense of what middleware people will use.
My take is that things like authorization should not happen in http middleware. Blitz middleware should exist only for the very few things that need raw access to the http objects. Authentication needs this to access cookies, for example. But then authentication adds the session object to context so it can be used in the query/mutation itself. Put another way, business logic shouldn't live in http middleware. For example, let's say your authorization is in middleware. Then you need to import a query and use it server side somewhere (not via RPC). You can do that, but your authorization is no longer enforced since it's not going through the http middleware. Make sense?
Any output from middleware should go in context. Queries and mutations will only have access to context, not |
@cr101, yes something like that! Authn & authz are both TBD. Keep an eye on the #dev-auth channel and Slack. We'll also post RFCs for both of these at some point. |
So session management will be a middleware, however, authorisation (seeing if an authenticated user has access to the API) will not be via a middleware. Is my understanding correct? |
@rishabhpoddar yes, I think that is the best way to do it, but I'm certainly open to hearing arguments for a different approach. |
Update y'all! I've opened two new issues for defining more details of Blitz queries and mutations:
Please check them out and provide any feedback you have! |
@flybayer how Blitz would go about serving content to native mobile apps without an API? |
@IGassmann it would do it via an HTTP API, just like how we are doing it with Blitz web apps. There actually is an API, but as a developer you don't have to know or think about it. |
Now documented at blitzjs.com |
Very interesting. Is that based on your own experience? I wonder how common that experience is? Since I have (perhaps naively?) assumed that the big benefit of GraphQL was precisely that third parties might reuse your own GraphQL API (which you in that case would be dogfooding, of course, so it will be naturally kept up-to-date). Do you have some sources that led you to your conclusion? I'd like to read up on it, because if it is a general phenomenon, then it would look like a good argument in favour of BlitzJS over RedwoodJS. |
The purpose of this RFC (Request For Comments) is to gather as much feedback as possible before building everything outlined in it.
We welcome all feedback, whether good or bad! This is your chance to ensure Blitz meets the needs for your company or project.
👉 View the Rendered RFC 👈
Also, there are now two other open issues for defining more details on Blitz queries and mutations:
Please also check those out and provide any feedback!