Closed simenbrekken closed 8 years ago
I've been thinking about this too. Right now, we have a npm run
hook that looks like this:
"build:gqlschema": "cashay-schema src/server/graphql/rootSchema.js build/graphqlSchema.json --oncomplete src/server/database/rethinkExit.js",
Then, we're pulling it into our client using webpack's JSON loader.
I suppose we could write a cashay-schema-loader
for webpack that would take the same parameters as cashay-schema
to build and inject the schema into the client. It'd be wonderful to not have to remember to run cashay-schema manually!
😳 This is so beautifully obvious I don't know why I never thought to perform it in the loader. Crap. Guess I have to learn how to write loaders!
This is gonna take some learning on my part so I can't promise a fast turnaround since subscriptions
and multi-part queries are next up in my sprints, but if you took a crack at it I'd be more than happy to review & accept!
@mattkrick Shazam! #51 💫
Oops, should have added comments here, rather than on #51.
See #52. Very similar to @simenbrekken's implementation. Considering we did this independently, must only be a few ways of doing it.
Here's how it is using in the client:
// Create the store:
const store = makeStore(initialState);
// Create the Cashay singleton:
const cashaySchema = require('raw!cashay!../server/utils/getCashaySchema.babel.js');
/// ^^^ note the loader string
const cashayHttpTransport = new HTTPTransport(...);
const cashayParams = {
store,
schema: cashaySchema,
getToState: reduxStore => reduxStore.getState().get('cashay'),
transport: cashayHttpTransport
};
// export the Cashay singleton:
export const cashay = new Cashay(cashayParams);
In order to user the loader, the user must provide a javascript file that, when executed, returns a Promise for a schema. I figured this would be even more flexible than cashay-schema
as folks can pull their schema from their local runtime, an Internet URL, from morse code, or anything other source.
The one I've put into Action, getCashaySchema.babel.js
, looks like this:
require('babel-register');
require('babel-polyfill');
module.exports = require('./getCashaySchema')();
It's friend getCashaySchema.js
looks like this:
import rootSchema from '../graphql/rootSchema';
import {transformSchema} from 'cashay';
import rethinkExit from './rethinkExit';
// side-step 'Error: Schema must be an instance of GraphQLSchema.'
const graphql = require('graphql').graphql;
export default async () => {
const schema = await transformSchema(rootSchema, graphql);
rethinkExit();
return schema;
};
One very small difference between my implementation and @simenbrekken's is I'm using the raw loader, which avoids a transform to JSON.
@jordanh Interesting with the raw
loader, is it any way explicitly requiring that loader in project dependencies could be avoided?
raw!
that they didn't install.We could, but I think it'd be less webpack-y to eliminate the explicit requirement for raw-loader
. Consider the myriad CSS loaders that explicitly depend on one another.
AFAIK, there isn't any way to call another loader raw
from a custom loader implementation, so we'd have to literally copy the functionality of raw (which is quite small) into cashay-loader
.
My preferences:
raw
as an explicit requirementcashay-loader
in cashay
If issues are opened by others (e.g. "eliminate dependancy on raw-loader"), then we revisit the implementation at that time.
I say we integrate raw loader. Oh, and by integrate, i mean write 2 lines of code: https://github.com/webpack/raw-loader/blob/master/index.js#L7-L8
I know, right? It's a pretty simple little animal.
Ok, done! Updated #52.
i'll rewrite the test that is causing the fail & push to npm shortly
I still think it's a bit clunky having to import both babel-register
and babel-polyfill
just to use the loader, IMHO the loader should work without any of these as package.json does not list any of these dependencies.
Could we perhaps include the polyfill when building the library or the loader itself?
A note here: it's the user's code which is driving the requirement to babel-register
and babel-polyfill
not Cashay. Cashay itself has already been transpiled.
The usage of babel-register
and babel-polyfill
in the example I gave was mine for the babel application we're writing, not a requirement of Cashay.
Ah, I take it back. @mattkrick points out that babel-polyfill
is required due to Cashay's usage of async await. In which case, @simenbrekken you're completely correct. Be nice not to require that of the end user...
During development it would be very nice if one could load the client schema using a webpack loader: