graphiql icon indicating copy to clipboard operation
graphiql copied to clipboard

DRAFT: Migrate graphiql package to vite

Open jonathanawesome opened this issue 2 years ago • 14 comments

This PR is the latest attempt to move away from Webpack and into Vite.

The Vite config turned out to be much more non-standard that I'd expected. Because we need to prep a minified bundle and a non-minified bundle (for the Netlify deployments), and because Vite's library build mode doesn't allow processing of the required index.html file, there's some hacky bits regarding the Vite configs that I'm not particularly fond of. That said, it mostly works.

I've left all of the webpack-related code in for now, except the build scripts, for reference.

Here are the important notes for reviewers:

Broken subscriptions/e2e

Most critical is an error originating from createFetcher and the usage of require for providing a user-friendly error when graphql-ws is not installed as a dependency (introduced in #2407). This will die in the browser when attempting to execute a subscription (screenshot below) and, most importantly, causes the e2e test run to fail. I haven't thought of a fix nor was I interested in cramming a fix into this PR without first reviewing as a group.

Screen Shot 2022-11-29 at 5 47 20 PM

Removal of graphiql.min.css.map

I struggled for a short while to get Vite to cough up a minified css source map without a plugin, then decided to abandon. I don't think removing the css source map on the development Netlify build is that big of a deal, but I'm happy to be wrong upon review and find a solution.

Bundle file target directory

I've changed the target directory for the bundled files, moving them from the root of the package to /build. If this interferes with packaging it can be changed, but we'll need to perform some additional Vite magic because Vite expects an index.html to live in the root and we can't have the bundler overwriting it. The new index.html is a template that is used in development mode and to produce the dev.html and index.html files that are used for the Netlify deployments...the bulk of this PR deals with hacking around this file and Vite's requirements for it. Happy to be wrong about my implementation and adjust upon review, but I think I've got it as clean as could be.

Non ideal dev mode

The script for dev mode starts the e2e server, starts a Vite build mode to watch for changes to /components/GraphiQL.tsx and rebuild the bundle, and starts the Vite dev server. It's complicated and not as lightning fast as you might expect with Vite, but necessary unless we want to jump through hoops to adhere to the "standard" Vite library mode setup. Early on in this work I had Ladle running and pointed directly at the GraphiQL component file, and that worked great, but it seemed even more awkward than the current state without a more well thought out approach to UI development throughout the repository. Ideally, we'll bring back Ladle or Storybook at some point in the near future to cover all of the UI development needs for UI-related packages and leave those packages to just handle bundling. @thomasheyenbrock has the most recent experience here and, I assume, was dev'ing /graphiql-react via graphiql...is that assumption correct?


Here's what I've got for a punch list:

  • [ ] Find a solution for the createFetcher/require situation
  • [ ] Come to a decision about the removal of graphiql.min.css.map
  • [ ] Come to a decision about the modified bundle target directory
  • [ ] Remove unused Webpack-related code
  • [ ] Optional: use this opportunity to remove other old and unused build/tooling related code

jonathanawesome avatar Nov 30 '22 00:11 jonathanawesome

⚠️ No Changeset found

Latest commit: cf7b137056a70ee2d49d034351aefccea73c0f3e

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

changeset-bot[bot] avatar Nov 30 '22 00:11 changeset-bot[bot]

The latest changes of this PR are not available as canary, since there are no linked changesets for this PR.

github-actions[bot] avatar Nov 30 '22 00:11 github-actions[bot]

this gets us so much closer to fixing the build vs build-bundles issue! now, i'm going to just rename some of these plugins to use build-bundles with wsrun -s so it executes in order of dependencies.

then build can be back to pure tsc --build project references, for all the type checks I see for underlying graphiql plugins etc

acao avatar Dec 02 '22 22:12 acao

@jonathanawesome in fact... thanks to this PR, I've figured out how to consolidate all of the graphiql packages & plugins into one consolidated vite config for the entire monorepo, by automatically resolving rollupOptions.entry and rollupOptions.output and/or with lib.entry https://github.com/vitejs/vite/discussions/1736#discussioncomment-3812904. We can generate all of the entry/output config from the package names at build time.

I built a bunch of esbuild plugins at work to build our own dev server because our monorepo was too complex for vite, but this is a case where we have multiple options to push vite further and make it more monorepo friendly.

acao avatar Dec 02 '22 22:12 acao

@jonathanawesome in fact... thanks to this PR, I've figured out how to consolidate all of the graphiql packages & plugins into one consolidated vite config for the entire monorepo, by automatically resolving rollupOptions.entry and rollupOptions.output and/or with lib.entry vitejs/vite#1736 (comment). We can generate all of the entry/output config from the package names at build time.

That's fantastic!

jonathanawesome avatar Dec 02 '22 22:12 jonathanawesome

Oof. So it may be that this pattern for dev/prod builds will need to continue. Worth noting this is possible in webpack 5, technically it's also possible in webpack 4 by returning two configs as an array, but I have the env flag split approach there as well. Also this is possible with rollup. Oh... and it might be possible with turbopack as well! 🤔

this issue prevents what I was hoping to achieve, as well as how minify works globally like you said image

However everything else - harmony between the build and build-bundles and monorepo wide dev server will still be doable!

acao avatar Dec 03 '22 10:12 acao

i think this could be our happy place... 😻 this would be a deus ex machina if it can work for us... it would solve the build vs build-bundles riddle transparently, and is sufficient enough for me to replace typescript project references. turborepo runs up against some of my preferences (per-workspace scripts for example) but we can add some plop generators for adding new workspaces (graphiql plugin or generic for starters)

https://github.com/vercel/turbo/blob/b7bcfc312e41367e2ec7f5fb37a6ee88a6b6545a/examples/kitchen-sink/package.json#L6

we have many options for self-hosting turborepo remote caches now (if we need that? i think we would benefit). for example: https://github.com/cometkim/turbocache (@cometkim is so prolific! hello there! 👋🏻 )

i think turborepo/turbopack/tsup could even perhaps replace esbuild for bundling our vscode extensions as well, and if we ever ship a standalone executable for the lsp cli, then turbprepo could even perhaps help with cacheing for that?

acao avatar Dec 03 '22 11:12 acao

Heya! :wave: @acao turbocache is a very simple demo project showing how to host a turborepo remote cache on Cloudflare Workers, so depending on your use case you may need to customize it, but it's very easy!

If you're looking for a bundler for libraries/binary that doesn't use css or html entries, you can keep watching at nanobundle. Very similar to microbundle, but uses esbuild. I'm are working on adding multi-entry support.

cometkim avatar Dec 03 '22 12:12 cometkim

turborepo uses tsup in many examples which uses both swc and esbuild?

really, anywhere that tsup is used we could nanobundle, and the options are almost the same? for example --dts flag. haha interesting

we can also still use vite library mode with turborepo as well!

acao avatar Dec 03 '22 12:12 acao

@cometkim I don't think we need multi-entrypoint support actually if we can use turborepo. i think we can use per-workspace builds if we just use nx or turborepo or something similar to orchestrate per-workspace build and dev scripts more intelligently than we are now, and then replace tsc --build with cross-monorepo watch build.

i think nanobundle will suit us just fine as is for many cases (except for the few with css)! It has dts support, and support for multiple output formats, and many configuration options for the cases where we might need them, which is all we really need.

one note: to replace what tsup would do for us here, we would need to add --watch flag to nanobundle - I recently worked on an internal project where we made a custom watcher for esbuild if that is necessary! this doesn't need to be an all out dev server, just replace tsc --watch

acao avatar Dec 03 '22 12:12 acao

i hope to return to this effort next week!

acao avatar Jan 11 '23 16:01 acao

I've got it working again on a new branch by plucking these changes onto the current main with git checkout. vite has since released a 4.x

Vite expects an index.html to live in the root and we can't have the bundler overwriting it.

agreed! this is how graphiql has always worked as well, at least in terms of where the index.html is always written to. The source being there is funky. we can publish the demo from any directory, netlify isn't required to publish packages/graphiql as the root, but we do need to make sure graphiql.min.js and .css and such are still at least aliased to the root import paths for unpkg/jsdelivr etc

one issue I've found is that @graphiql/react is using vite@2 and graphiql itself is using [email protected]! going to rectify all of these versions and create some harmony :))

acao avatar Feb 08 '23 17:02 acao

I've managed to address the require() issue in toolkit, bundling the library itself in a compatible way. Now something is causing vite to not encode this unicode character properly in reach ui, have you seen this before?

https://github.com/reach/reach-ui/blob/43f450db7bcb25a743121fe31355f2294065a049/packages/popover/src/reach-popover.tsx#L338

acao avatar Feb 08 '23 20:02 acao

I've managed to address the require() issue in toolkit, bundling the library itself in a compatible way. Now something is causing vite to not encode this unicode character properly in reach ui, have you seen this before?

https://github.com/reach/reach-ui/blob/43f450db7bcb25a743121fe31355f2294065a049/packages/popover/src/reach-popover.tsx#L338

@acao Just to clarify: is the issue that something does not get rendered or that the variable name, restoreTabIndexTuplés, contains a unicode character?

If the first: do you have a link to a error message? If the latter, is a normal 'e' not usable?

malte-behrendt-gr avatar Feb 23 '23 08:02 malte-behrendt-gr

What there ever a fix for the require, I am trying to use the package and its PITA

EDIT: Found a way! Add the following to your vite config.

build: {
    commonjsOptions: {
      transformMixedEsModules: true,
    },
  },

Sytten avatar Jul 03 '24 16:07 Sytten

closed by https://github.com/graphql/graphiql/pull/3679

dimaMachina avatar Aug 07 '24 14:08 dimaMachina