You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe the problem you want to solve or enhancement you want to bring
Ability to write full-stack "feature-oriented" packages with both server and client features, in NPM, as we are used to do in Meteor.
@vulcanjs/graphql is a good example of this, as it generates the graphql backend, the client fragments, and both are very tied.
Define relevant concepts
Full-stack package: A package that export server-specific code and client-specific code. But it could apply to any package that expose different code depending on various environment (server, mobile, client).
Meteor packages are example of fullstack package with their client and server logic.
This is different from just having code that works everywhere, like a low-level library. We are talking about code that is actually specific to the env (calling window on the client for instance).
We should be able to do something like import createServer from "@vulcanjs/graphql/server", import someHook from "@vulcanjs/graphql/client"and import someSharedCode from "@vulcanjs/graphql"
Isomorphic import: Using a fullstack package transparently.
Example: a full-stack package could expose @vulcanjs/graphql/server and @vulcanjs/graphql/client. An isomorphic import would be import foobar from "@vulcanjs/graphql" and let the the build system add /client or /server depending on the context.
Meteor is also doing that.
Limitation: the text editor can't know the environment where the code is run. So, for static typing, you have to explose a generic version. Meteor is subject to this limitation.
Blitz.js has something similar, but with "unbalanced isomorphism", limited to how they consume the server using a custom query system. The typing is coming from the server, that contains the actual logic, as the client version is just a dull wrapper that does an HTTP call.
True isomorphism: you write a single piece of code and let the build system modify it depending on the execution environment. Next pages fall into this category. getServerSideProps and getStaticProps functions exported in a page are server-only methods. The rest React (so client but also compatible with server-side rendering). At build time, those methods are removed from the client bundle.
This is something we would want to achieve for Vulcan model's:
constFoo=createModel({schema: {foobar: {type: string;// both client and server, to render form, generate the gql schema etc.resolver : ()=>{...}// field resolver, server-onlyonCreate: ()=>{...}// server-only}},queries: { ... },mutations: { ... }// CRUD operations, server-only})
In this example, the schema mixes shared elements, like the type for "Foo.foobar", and server only methods like the graphql resolver.
The power of Vulcan is to let you write only one schema with everything. The limitation is that you don't want the client bundle to contain server code, and sometimes vice-versa. You can bypass this with ugly require or playing around with GraphQL context, but only so much.
Related
RFC for Vulcan Package Format usable on any any app. It is focused on the actual content of the package, the what, (how we export graphql stuff etc.), while this RFC is focused on how we deliver such fullstack package, regarding build system, import tec. RFC: Vulcan Package Format vulcan-next#9
Then isomorphic import could be kept as a "magic" helper specific to Vulcan. But it is not mandatory (like if you create an Express server and don't use weback, you just do import foobar from "@vulcanjs/graphql/server" as usual). This feature is more comfort for people used to Meteor.
Questions to the community:
For full-stack package: Multi entry Webpack export/TypeScript. It should not be too hard, but I've never done that before, there are a lot of moving pieces. So help welcome!
For isomorphic import: there is a demo package multi-env that does exactly this. The way it works, it imports either index.server or index.client, using Webpack magic.
For the text editor autocompletion, or common code, we can also add an index that exports both. That's a prototype so again help and feedback welcome.
A good example to get started is the graphql package, that contains both server and client logic.
For true isomorphism: it's not easy at all to mix server and client stuff at the same place.
is it even a good idea? MVC architecture would basically force you to explode your model in multiple pieces and bypass this issue.
it could be easier to have multiple named exports with a convention, like Next does.
For example, in foobar.ts:
export const schema = { foobar: {...} } // the common part
export const fieldResolvers = {foobar: {...}} // server-only. We have to repeat the field names
export const resolvers = {... } // server-only
// etc.
And then you create the full model using some build time magic. This is still a bit blurry, that's the part that require the most thinking.
The text was updated successfully, but these errors were encountered:
Next.js has it's own tree shaking function for removing SSR code from the client bundle: vercel/next.js#27552
We could do something similar to remove resolver field from schemas client-side.
Describe the problem you want to solve or enhancement you want to bring
Ability to write full-stack "feature-oriented" packages with both server and client features, in NPM, as we are used to do in Meteor.
@vulcanjs/graphql
is a good example of this, as it generates the graphql backend, the client fragments, and both are very tied.Define relevant concepts
Full-stack package: A package that export server-specific code and client-specific code. But it could apply to any package that expose different code depending on various environment (server, mobile, client).
Meteor packages are example of fullstack package with their
client
andserver
logic.This is different from just having code that works everywhere, like a low-level library. We are talking about code that is actually specific to the env (calling
window
on the client for instance).We should be able to do something like
import createServer from "@vulcanjs/graphql/server"
,import someHook from "@vulcanjs/graphql/client"
andimport someSharedCode from "@vulcanjs/graphql"
Isomorphic import: Using a fullstack package transparently.
Example: a full-stack package could expose
@vulcanjs/graphql/server
and@vulcanjs/graphql/client
. An isomorphic import would beimport foobar from "@vulcanjs/graphql"
and let the the build system add/client
or/server
depending on the context.Meteor is also doing that.
Limitation: the text editor can't know the environment where the code is run. So, for static typing, you have to explose a generic version. Meteor is subject to this limitation.
Blitz.js has something similar, but with "unbalanced isomorphism", limited to how they consume the server using a custom
query
system. The typing is coming from the server, that contains the actual logic, as the client version is just a dull wrapper that does an HTTP call.True isomorphism: you write a single piece of code and let the build system modify it depending on the execution environment. Next
pages
fall into this category.getServerSideProps
andgetStaticProps
functions exported in a page are server-only methods. The rest React (so client but also compatible with server-side rendering). At build time, those methods are removed from the client bundle.This is something we would want to achieve for Vulcan model's:
In this example, the schema mixes shared elements, like the type for "Foo.foobar", and server only methods like the graphql resolver.
The power of Vulcan is to let you write only one schema with everything. The limitation is that you don't want the client bundle to contain server code, and sometimes vice-versa. You can bypass this with ugly
require
or playing around with GraphQL context, but only so much.Related
Describe your solution
First step is implementing full-stack packages.
Then isomorphic import could be kept as a "magic" helper specific to Vulcan. But it is not mandatory (like if you create an Express server and don't use weback, you just do
import foobar from "@vulcanjs/graphql/server"
as usual). This feature is more comfort for people used to Meteor.Questions to the community:
For full-stack package: Multi entry Webpack export/TypeScript. It should not be too hard, but I've never done that before, there are a lot of moving pieces. So help welcome!
For isomorphic import: there is a demo package
multi-env
that does exactly this. The way it works, it imports eitherindex.server
orindex.client
, using Webpack magic.For the text editor autocompletion, or common code, we can also add an
index
that exports both. That's a prototype so again help and feedback welcome.A good example to get started is the
graphql
package, that contains both server and client logic.For true isomorphism: it's not easy at all to mix server and client stuff at the same place.
For example, in
foobar.ts
:And then you create the full model using some build time magic. This is still a bit blurry, that's the part that require the most thinking.
The text was updated successfully, but these errors were encountered: