Skip to content
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

RFC: Teach compiler --persist option #1846

Closed
wants to merge 3 commits into from
Closed

RFC: Teach compiler --persist option #1846

wants to merge 3 commits into from

Conversation

wincent
Copy link
Contributor

@wincent wincent commented May 31, 2017

Sample usage:

relay-compiler --src ./src --schema schema.graphql --persist scripts/persistQuery.js

Where persistQuery.js looks like this:

function persistQuery(text) {
  var id = someLogicToPersistQueryText(text);
  return Promise.resolve(id);
}

The alternative in the absence of this option is to copy-paste the entire RelayCompilerBin implementation just to override that bit.

Note that webpack makes this ghastly — necessitating the use of eval — because it wants to rewrite the require of the passed in module, which of course fails because it is dynamic. Google search turns up a bunch of results like this one lamenting the situation:

https://stackoverflow.com/questions/30575060/require-js-files-dynamically-on-runtime-using-webpack

Apparently it's better in webpack 2.

@wincent
Copy link
Contributor Author

wincent commented May 31, 2017

This is ugly as hell, but throwing it up there as an RFC anyway. In my own side-project, I went down the path of forking RelayCompilerBin, but it seems pretty limiting not to be able to use the relay-compiler executable for anything but very simple use cases.

@wincent wincent changed the title Teach compiler --persist option RFC: Teach compiler --persist option May 31, 2017
// Using eval here to prevent webpack from trying to rewrite the require and
// failing.
const persistQuery = persistModule &&
eval(`require(${JSON.stringify(persistModule)})`);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't there something like require.actual()? Or maybe alias require to something else?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In vanilla node, there is not (that's a Jest thing). I looked on the interwebs, but I couldn't find anything. Moving to webpack 2 would provide us with some more options, I think, but that's obviously a bigger change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about aliasing require so webpack doesn't transform it? Or shell out to a separate process?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. Let me see if aliasing works.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like it does work (at least, build runs without blowing up); webpack lets the line in question through as:

var persistQuery = persistModule && global['require'](persistModule);

in the built output.

@josephsavona
Copy link
Contributor

I was going to send a PR for this too, definitely something we should add.

@wincent
Copy link
Contributor Author

wincent commented Jun 1, 2017

Gonna import this to run Flow tests internally (my local set-up is borked right now).

@wincent
Copy link
Contributor Author

wincent commented Jun 1, 2017

Gonna import this to run Flow tests internally (my local set-up is borked right now).

Heh, or I could just look at Travis...

@kassens
Copy link
Member

kassens commented Jun 1, 2017

Webpack actually aliases global, I also couldn't find a way to do this and resorted to eval in a similar situation.
Do you have a pointer how this works in webpack 2? It might help in my situation.

@wincent
Copy link
Contributor Author

wincent commented Jun 1, 2017

Webpack actually aliases global, I also couldn't find a way to do this and resorted to eval in a similar situation.

I was hopeful that this would work because the built output looks like this:

            var persistModule = options.persist && __webpack_require__(5).resolve(process.cwd(), options.persist);
            if (persistModule && !__webpack_require__(6).existsSync(persistModule)) {
              throw new Error('--persist path does not exist: ' + persistModule + '.');
            }
            // Need to hide the `require` here to prevent webpack from rewriting
            // it and failing.
            var persistQuery = persistModule && global['require'](persistModule);

Note how it hasn't mangled global['require']. I also couldn't see any direct messing with global, at least inside the relay-compiler bin file, although be getting messed with somewhere else. I haven't tested this separately yet, but I will to confirm.

Do you have a pointer how this works in webpack 2? It might help in my situation.

(Whoops submitted too soon).

I just found a few mentions in my Google searches to "dynamic requires" not being enabled by default in v2. (Example).

@robrichard
Copy link
Contributor

Do you need to run the relay-compiler bin through webpack at all? Since it's a node command line script, couldn't you leave all the requires intact?

@wincent
Copy link
Contributor Author

wincent commented Jun 6, 2017

Cross-referencing: #1710 (review)

@robrichard:

Do you need to run the relay-compiler bin through webpack at all? Since it's a node command line script, couldn't you leave all the requires intact?

True. My recollection is that we're doing this as an optimization to minimize cold-start time.

Sample usage:

    relay-compiler --src ./src --schema schema.graphql --persist scripts/persistQuery.js

Where `persistQuery.js` looks like this:

```
function persistQuery(text) {
  var id = someLogicToPersistQueryText(text);
  return Promise.resolve(id);
}
```

The alternative in the absence of this option is to copy-paste the
entire `RelayCompilerBin` implementation just to override that bit.

Note that webpack makes this ghastly — necessitating the use of
`eval` — because it wants to rewrite the `require` of the passed
in module, which of course fails because it is dynamic. Google search
turns up a bunch of results like this one lamenting the situation:

https://stackoverflow.com/questions/30575060/require-js-files-dynamically-on-runtime-using-webpack

Apparently it's better in webpack 2.
This time actually tested it and confirmed that it works.
@josephsavona
Copy link
Contributor

Ship it!

@facebook-github-bot
Copy link
Contributor

@wincent has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@josephsavona
Copy link
Contributor

josephsavona commented Aug 14, 2017

@unirey No idea. cc @leebyron

@wincent
Copy link
Contributor Author

wincent commented Aug 14, 2017

I imported it but it has since grown stale. I need to dust it off and rebase it. A question was raised into whether the change as I had made it is would work everywhere, and I haven't had time to (re-)validate that myself yet.

@wincent
Copy link
Contributor Author

wincent commented Aug 22, 2017

I would also prefer not take a slippery slope of creating, maintaining my own version of Relay.

@unirey: not to dismiss your point (I'd like to see this option merged, obviously), but note that it's not really creating your own version of Relay: you just need to fork a single file (and in fact, internally at Facebook we do exactly that: we have a custom "compiler" executable that is configured to suit our specific needs). I did this for a side-project of mine, for instance: compile.js.

@robrichard
Copy link
Contributor

@wincent forking that file using a version of relay newer than 1.0.0 requires formatGeneratedModule which is not publicly exported. See #1927

@wincent
Copy link
Contributor Author

wincent commented Aug 22, 2017

@wincent forking that file using a version of relay newer than 1.0.0 requires formatGeneratedModule which is not publicly exported.

I think it's probably reasonable to expose that, although we've historically been very conservative and minimal in terms of what we include in the public API. The main question is whether this stuff should be exposed at the relay-compiler level, or rather just the building blocks for it lower down, in the graphql-compiler.

facebook-github-bot pushed a commit that referenced this pull request Aug 24, 2017
Summary:
Fixes #1927

wincent This will export `formatGeneratedModule` as discussed in #1846 (comment). I exported it in `relay-compiler` (as opposed to `graphql-compiler`) since that is where it is currently located.
Closes #2054

Reviewed By: kassens

Differential Revision: D5690522

Pulled By: wincent

fbshipit-source-id: bc7fd24152d1a1f62e28432fe3e7e1d6b7fef158
@GrigoryPtashko
Copy link

Hello, everyone. Is this going to be merged actually? That's a nice option I'd like to use instead of forking..

@schickling
Copy link
Contributor

:shipit:

@yusinto
Copy link
Contributor

yusinto commented Jan 17, 2018

I published my own package relay-compiler-plus which supports persisted queries and compiles graphql-js schema as well. Hope that helps for now.

@jwb
Copy link

jwb commented Jan 26, 2018

It would be really great to have support from the core to proceed with this!

@sibelius
Copy link
Contributor

@jstejada any plans for this feature?

@devknoll
Copy link
Contributor

I haven't spoken to the team yet, but my hunch is that if someone wanted to update this diff to make persist a command that is executed, rather than a JS module, we might be willing to merge it.

@sibelius
Copy link
Contributor

@yusinto can u send a PR making persist a command?

@yusinto
Copy link
Contributor

yusinto commented Feb 19, 2018

Yes I will submit a pr soon. Thanks for the suggestion @sibelius

@yusinto
Copy link
Contributor

yusinto commented Feb 28, 2018

Done. Here it is.

@alloy alloy mentioned this pull request Feb 28, 2018
@alloy
Copy link
Contributor

alloy commented Feb 28, 2018

To avoid confusion, I’ll close this PR for now in favour of #2354.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.