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

Relay without babel in 2021: Where do we stand with next-gen JS bundlers? #3319

Open
tony opened this issue Jan 13, 2021 · 21 comments
Open

Relay without babel in 2021: Where do we stand with next-gen JS bundlers? #3319

tony opened this issue Jan 13, 2021 · 21 comments

Comments

@tony
Copy link

tony commented Jan 13, 2021

Last thread #828, closed in Jan 2017 by @wincent with oppurtunity to reopen again.

In my projects, relay is the reason I'm sticking to babel at the moment, because I haven't been able to find any documented integrations of a babel-free setup where I could run relay, then have it go through a compiler.

In 2021, there is a growing assortment of alternatives to the babel+webpack setup such as sucrase, esbuild, rome, parcel, swc and snowpack *. Also, what about plain-old tsc?

The issue is, these bundlers often don't accept custom transformations, so I imagine there'd need to be a process happen where relay could run and the resulting code would be left in a state where it could be consumed by these bundlers that want very "Vanilla" code: They'll do TypeScript and JSX.

Where relay fits into the big picture of a project is still over my head (excuse me if I'm drastically misunderstanding and/or oversimplifying relay!) It would be helpful to illuminate what relay and the tools supported by facebook/relay ingest, what they produce for us in terms of code generation, and any official supported ways interoperate with compilers/build systems/toolchains.

Questions:

  • What would it take to get relay working with tools like vanilla tsc, sucrase, esbuild, rome, and swc?
  • How much of the way does this project get us currently?
  • Is there anything the maintainers could do to facilitate / document to make things clearer for us?
  • What would be left for the community need to do to get relay working with next-gen bundlers?
@thezjy
Copy link

thezjy commented Jan 14, 2021

@tony Hi, I've setup snowpack 3.0 + relay successfully following samwightt's demo repo. Below is his quote on how it works:

The issue you’re facing is that relay requires a Babel plugin in order to function, but the Babel plugin will use CommonJS modules and not ES modules. I wrote a quick custom snowpack plugin that fixes this (check out the relay.snowpack.js file) and that should help you out :)

@n1ru4l
Copy link
Contributor

n1ru4l commented Feb 10, 2021

You can actually compile as es modules: FredKSchott/snowpack#824 (comment)

@n1ru4l
Copy link
Contributor

n1ru4l commented Feb 11, 2021

I opened #3354 for a specific case where relay-compiler is generating require calls

@sciyoshi
Copy link

For anyone else finding this thread while looking for getting Relay to work with esbuild, I wrote a very hacky plugin to mimic babel-plugin-relay's transformation: https://gist.github.com/sciyoshi/34e5865f2523848f0d60b4cdd49382ee (it doesn't check the hash and probably will need to be tweaked)

@wyattjoh
Copy link
Contributor

With Next.js adopting SWC as the default compiler going forward, is the Relay team interested in producing a compatible plugin/replacement for the babel-plugin-relay?

@hanford
Copy link
Contributor

hanford commented Sep 21, 2021

To validate what @sciyoshi shared works on a fundamental level, I rewrote the code into a new babel plugin and was delighted to find out it worked.

image

And the babel plugin:
https://gist.github.com/hanford/10401629eb7d82d47b275f59356d86f5

....

I plan on writing a Rust based SWC plugin as soon as there is more information/documentation around how the SWC V2 plugin system will work. (atm there is no documentation as far as I can tell), but apparently will be similar to babel macros

I'm happy to share the source here / open source whatever I end up writing!

@richardguerre
Copy link

richardguerre commented Oct 20, 2021

I wrote a very hacky plugin to mimic babel-plugin-relay's transformation: https://gist.github.com/sciyoshi/34e5865f2523848f0d60b4cdd49382ee (it doesn't check the hash and probably will need to be tweaked)

@sciyoshi, if you don't mind me asking, what is the hash used for? Is it possible to use that transformation to build for production, or should it only be used for a dev server?

@madebyherzblut
Copy link

@richardguerre The hash is used to warn you about outdated definitions (e.g. when you forgot to run the Relay compiler after changing your GraphQL operation). Normally, this is only available in development.

Hopefully next week I have the time to finish our esbuild-plugin-relay and publish it to NPM. It is based on @sciyoshi Gist 🙂

@ivosabev
Copy link

+1 for SWC compatibility

@montogeek
Copy link

Interested in this feature after spending several hours trying to make a Relay app work inside a Phoenix Framework using esbuild, then Parcel, Vite, SWC.

@hanford
Copy link
Contributor

hanford commented Nov 1, 2021

The current plugin API for SWC (the JS one) is deprecated. For Relay to work with next-swc the plugin will need to be committed to next-swc in the vercel/next.js repo, (until there is an official plugin/macro API). https://github.com/vercel/next.js/tree/canary/packages/next/build/swc/src

I've talked with some contributors and they're planning on adding it (relay support) themselves given how trivial the plugin is, but there isn't really a timeline AFAIK.

I'd be happy to help review / game plan / test a community based plugin and try to get it merged into Next.js rather than waiting

Edit: Looks like they're tracking this in a Github issue now: vercel/next.js#30805

@sofly
Copy link

sofly commented Nov 28, 2021

Interested in this feature after spending several hours trying to make a Relay app work inside a Phoenix Framework using esbuild, then Parcel, Vite, SWC.

@montogeek Hello. Could you tell me please, did you do it?

@hanford
Copy link
Contributor

hanford commented Jan 13, 2022

A community member opened a PR for Relay support w/ SWC

vercel/next.js#33240

@hanford
Copy link
Contributor

hanford commented Feb 1, 2022

Next.js (12.0.11-canary.0) now supports Relay with it's Rust compiler, SWC

refs vercel/next.js#33702

@tony
Copy link
Author

tony commented Feb 4, 2022

@hanford Will these be accessible to vanilla-swc outside of next.js?

The reason I ask is not all SPA projects are next.js candidates, but some could be for swc.

@hanford
Copy link
Contributor

hanford commented Feb 8, 2022

I'm not sure @tony, I don't think it extracting the plugin would be impossible b/c it's a pretty trivial set of operations, but there are some Next.js specific bits around loading configuration

@wasd171
Copy link
Contributor

wasd171 commented Feb 9, 2022

@hanford Perhaps using the next-swc-loader with minimal experimental Next.js config would work in a webpack-without-next setup?

@beaumontjonathan
Copy link
Contributor

With the release of Vite 4 & official support for SWC, I've been looking into this.

I'm not sure @tony, I don't think it extracting the plugin would be impossible b/c it's a pretty trivial set of operations, but there are some Next.js specific bits around loading configuration

@hanford It seems this work has been done now & released under @swc/plugin-relay github/swc-project/plugins/relay.

@mikeldking
Copy link
Contributor

Heads up for those trying to use esbuild-plugin-relay - it only works for older versions of relay that used relay-config (see relay-config)

The gist above works for my simple use-case so far.

export const relay = {
    name: "relay",
    setup: (build) => {
        build.onLoad({ filter: /\.tsx$/, namespace: "" }, async (args) => {
            let contents = await promises.readFile(args.path, "utf8");

            if (contents.includes("graphql`")) {
                let imports = [];

                contents = contents.replaceAll(
                    /graphql`([\s\S]*?)`/gm,
                    (match, query) => {
                        const formatted = print(parse(query));
                        const name = /(fragment|mutation|query) (\w+)/.exec(
                            formatted
                        )[2];
                        let id = `graphql__${crypto
                            .randomBytes(10)
                            .toString("hex")}`;
                        imports.push(
                            `import ${id} from "./__generated__/${name}.graphql.ts";`
                        );
                        return id;
                    }
                );

                contents = imports.join("\n") + contents;
            }

            return {
                contents: contents,
                loader: "tsx",
            };
        });
    },
};

@sibelius
Copy link
Contributor

should we have examples of using relay with esbuild, swc, nextjs and others?

@sibelius
Copy link
Contributor

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

No branches or pull requests