VulcanJS / vulcan-next

The Next starter for GraphQL developers
http://vulcan-docs.vercel.app
MIT License
393 stars 29 forks source link

Demeteorizing Vulcan and how you can help #1

Open eric-burel opened 4 years ago

eric-burel commented 4 years ago

Goal

Progressively transition from Meteor to Next app.

Some code will be specific to Next, however this transition will also allow to reuse Vulcan code in other type of React frameworks (eg Gatsby), at least for the frontend.

Things to get sorted out

Multi-environment NPM packages

For Storybook I've created a specific Webpack handler, but it would be better to have some out-of-the-box pattern.

Usually NPM expect you to define a unique main field that points to your package built code (eg dist/index.js). Instead, we may want to point a directory (related SO question), maybe with `exports: { ".": "./dist"}. We could also put built file directly at the project root.

We probably will need to define Webpack loaders/config at least for client side imports, that can differentiate environments.

Mongo

Others

Things to do

Steps to go from Meteor packages to NPM packages

The goal is to both allow to use Vulcan outside Meteor, in Next, and keep maintaining the Meteor version with a minimal amount of code. To be done for most existing package, however note that packages may exist in Next already. Eg handling styled components. In this case no additional work is needed, it's user responsibility to install relevant packages.

Specific demeteorization tasks

Documentation of equivalent patterns

Coming from Meteor, we need to get a grasp of equivalent patterns in Next.

Tooling

Feature-wise goals

In order to make the process easier, here are some intermediate goals. Each may need some of tasks listed above to be achieved beforehand.

Use case idea

Working on a simple business use case would allow us to create example more easily. We could for example develop a Job board, or an app similar to "Awesome Vulcan" to publish vulcan ressources.

[This document is a Work in Progress. It will be updated with additional questions, answers, and process to move from Meteor to Next]

Ressources

Contribute

Post a comment on this issue if you want to help or take care of one of the tasks.

comus commented 4 years ago

hello, something i tried to do it last year, but i didn't have time to finish it. really.

i just share what i did, for the "How to create npm packages that works differently on the client and the server?"

it s easier with webpack config. it's good to wrap it with next.config.js, such as withVulcan

config.resolve.mainFiles

for example https://github.com/comus/react-vulcan-proposal/blob/master/src/withVulcan.js https://github.com/comus/react-vulcan-proposal/blob/master/examples/simple/next.config.js

and "Mongo database", i am not use mongodb now. but i have a solution for local development.

there is a node js library called 'mongodb-prebuilt', it can download the mongodb binary and run it.

i have a bin script: https://github.com/comus/react-vulcan-proposal/blob/master/src/bin/react-vulcan.js

with the bin, people can just type npx @vulcan/anyname mongo to launch a mongodb for development.

eric-burel commented 4 years ago

Thanks for the withVulcan helper. So it seems that you went for a specific loader (edit: resolver not loader) too in order to handle both client and server. Maybe that's the only solution indeed.

For reference of "mainFiles" webpack config: https://webpack.js.org/configuration/resolve/#resolvemainfiles

eric-burel commented 4 years ago

I've made a first update of the monorepo to show how it could work: https://github.com/VulcanJS/vulcan-npm

I've only added Typescript, but we would also need to use Webpack in order to have transparent usage between server and client. It's not tested yet.

@comus I have reused your idea of using mainFiles to make a more generic helper in @vulcan/webpack package. It may be used in Next like you did but also in any kind of app that uses Webpack.

Since Node servers use Webpack less often, we could also consider that index.js is the default server export. So that you can still do const whatever = require('@vulcan/core') in a server that do not use Webpack, it would be equivalent to const whatever = require('@vulcan/core/index.server').

We can safely consider that client side the developer is able to setup Webpack to import Vulcan, or explicitely call const whatever = require('@vulcan/core/index.client).

Don't know if I am clear but I think we will figure this out correctly.

One pain point though is that we usually use package.json main field to tell NPM that the built JS file is the root of the package (eg dist/index.js), while here we have multiple files. We may need to put built files at the root of the package.

eric-burel commented 4 years ago

@comus I've pushed a new test, sadly I could'nt have "multi-env" import to work. I have pushed a new commit with a demonstration (see _app.ts, it loads @vulcan/multi-env-demo). It is weird because the "log" is correct, but I still have a build error, very weird.

Also, I made a test with Webpack in the monorepo and build did work. However we face a big problem: the text editor can't understand our index.client/index.server thing. It says that it does not find the package if you just type @vulcan/multi-env-demo, because it looks for an index, even when the build work. There is no way for VS code to tell whether you are editing client code or server code. Note that it explains poor support of Meteor in text editors.

This may end up being too complicated. In which case we would be forced to do import '@vulcan/core/server and import '@vulcan/core/client depending on the environment, without relying on Weback.

To sum it up:

I don't think it's a big deal in the end.

The experiment with resolve.mainFiles try to be a bit smarter and select the right code automatically but it may raise too many issues with tooling .

eric-burel commented 4 years ago

It also means that we will lose the pattern of having 2 components with same name but different implementation in server and client, eg to handle components that do not support SSR. But again not a big deal, it was seldom used and very Vulcan specific, we have other alternatives in Next (using NoSSR components for example, dynamic imports and so on)