brillout / research

5 stars 0 forks source link

Stem #4

Open brillout opened 2 years ago

brillout commented 2 years ago

@cyco130 the new idea I was mentioning:

// package.json
{
  "dependencies": {
    "stem-react": "0.1.0",
    // For GraphQL users, instead of `stem-react`:
    "stem-react-relay": "0.1.0",
    "stem-react-apollo": "0.1.0",

    // For Vue users
    "stem-vue": "0.1.0",
    // Or:
    "stem-vue-relay": "0.1.0",

    "stem-zustand": "0.1.0",
    // Or:
    "stem-pinia": "0.1.0",

    "stem-tailwind": "0.1.0",
    "stem-sentry": "0.1.0",
    "stem-telefunc": "0.1.0",
    "stem-google-analytics": "0.1.0",
    "stem-sitemap": "0.1.0",
    // I don't think Prisma would need this, but you get the idea
    "stem-prisma": "0.1.0"
  }
}
// .env
GOOGLE_ANALYTICS=GA-12345
SENTRY=678910

Everything is zero-config, there is not even a need to import 'stem-react'. It's auto-loaded.

A stem.config.js for configuration is optional; the hope is that it's not needed most of the times.

All the user has to do is to write his components, data models, and telefunctions (or GraphQL queries).

Stem plugins can:

Stem is only a thin layer of automatic integrations on top of do-one-thing-do-it-well tools that are independent of each other.

Neat thing: there is no proprietary lock-in. It may seem like there is, but it's actually not the case. Let me elaborate.

// node_modules/stem-react/vite-plugin-ssr/_default.page.client.jsx

// The directory `stem-react/vite-plugin-ssr/` implements the integration with vps

export { render }

import React from 'react'
import { hydrateRoot } from 'react-dom/client'
import { PageShell } from './PageShell'

async function render(pageContext) {
  const { Page, pageProps } = pageContext
  hydrateRoot(
    document.getElementById('page-view'),
    <PageShell>
      <Page {...pageProps} />
    </PageShell>,
  )
}
// node_modules/stem-react/rakkas/client.jsx

// The directory `stem-react/rakkas/` implements the integration with Rakkas

// ...

This means stem-react can include integrations for both vps and rakkas. The only thing that is slightly "proprietary" is the stem- namespace (because we'll have the de-facto authority of what these stem- packages should or should not include). But anyone is free to introduce a new namespace. Bottom line: vps's extension mechanism is completly independent of HatTip's extension mechanism. This means anyone is free to ship an npm package that extends HatTip while also extending a new vps/Rakkas "competitor".

The no lock-in part is really neat, but it's going to be tricky to explain succinctly and clearly: at first sight, Stem will seem like "yet another monstrous monolith full of lock-in, doom to fail like Meteor". But I've idea for how to communicate that part.

Similarly to to Vite: there are Stem pugins and there are also Stem wrappers.

This means frameworks like Wind can still completely wrap things while using Stem plugins. Alternatively, Wind can use vps without Stem like it does today.

I'm thinking Vilay could be a stem-react-relay package. (We can still keep its name vilay though — I like that name. Just seeing that it now has a logo btw. :grinning:.)

CC @aleclarson @thetre97 @XiNiHa @Sajad-Sharhani

aleclarson commented 2 years ago

Turnkey solutions are great as long as there's a configuration escape hatch. Maybe each package could also export a Vite plugin that overrides the auto-loaded defaults?

Apologies, I missed this line: 😅

A stem.config.js for configuration is optional; the hope is that it's not needed most of the times.

How would that configuration look?

aleclarson commented 2 years ago

Would Stem work as well as a Vite plugin that auto-loads stem- prefixed packages?

import stem from 'vite-plugin-stem'

export default {
  plugins: [
    // Auto-load stem packages with a ./saus/ integration
    stem({ framework: 'saus' }),
  ]
}
aleclarson commented 2 years ago

This reminds me of the Unplugin initiative, but for Vite-based frameworks.

It's a little wonky that I have to download integrations I don't need (but that can't be known at install time, of course). This means the barrier for an integration to be accepted into a Stem package is higher than publishing a framework-specific package to NPM.

As I understand it, Stem developers are basically managing multiple packages in one, where all integrations share the same configuration and features. It still remains that one framework will always have more Stem integrations than the rest, but I suppose there's still a chance that all Stem packages in a project happen to have an integration for a new sexy framework that one may wish to migrate to.

Maybe each integration could be downloaded separately from its Stem package (on demand, when the dev server runs). You're trading install weight for dev server startup time, but only when a new Stem package is added. Is it faster to install a Stem package with many integrations than installing a single integration on-demand? Stem could manage a global integration cache (like PNPM in a way), so only one copy of each integration would ever exist on a single machine.

aleclarson commented 2 years ago

What if a Stem package could have its various integrations maintained in separate repositories and even by different users, no collaboration required (except for config schema)?

Similar to DefinitelyTyped's automated approach, the Stem package registry would let anyone contribute a Stem integration for a new or existing Stem plugin. This package registry is really a pointer map, where a plugin name (eg: @stem/react-relay) and framework name (eg: saus) would map to a NPM package that would be downloaded on-demand (instead of jamming all integrations of a Stem plugin into one NPM package).

So when @stem/react-relay is installed, the user is just getting a slice of the package registry for that specific Stem plugin.

// ./node_modules/@stem/react-relay/index.json
{
    "rakkas": "@rakkas/react-relay",
    "saus": "@saus/react-relay",
    "vps": "vite-plugin-react-relay"
}

To reiterate, each of those packages could have their own maintainer (or not). They all share the same config schema and expected behavior. The config typings of each Stem plugin would be maintained in the Stem plugin repository and then consumed by each integration (in the above example, by importing { Config } from "@stem/react-relay").

brillout commented 2 years ago

I renamed this to Stem:

I'm not sure about the marketing implications of this naming; I may change it again.

brillout commented 2 years ago

@aleclarson I like your idea. A lot.

How about the following approach. (At first it will appear contradictory, but it actually isn't.)

stem-* packages are only for a specific stack: Vite + vps + HatTip.

saus-* packages are the same but for: Saus + HatTip.

stem-* and saus-* packages have zero code; all they do is include dependencies:

// node_modules/saus-telefunc/package.json
{
  "dependencies": {
    "hattip-telefunc": "0.1.0",
    "saus-telefunc": "0.1.0",
  }
}
// node_modules/stem-telefunc/package.json
{
  "dependencies": {
    "hattip-telefunc": "0.1.0",
    "vps-telefunc": "0.1.0",
  }
}

That way, hattip-telefunc is shared.

Actually, I see Telefunc's HatTip integration to live directly in telefunc's monorepo. So, instead, it could be:

// node_modules/saus-telefunc/package.json
{
  "dependencies": {
    "@telefunc/hattip": "0.1.0",
    "@saus/telefunc": "0.1.0",
  }
}
// node_modules/stem-telefunc/package.json
{
  "dependencies": {
    "@telefunc/hattip": "0.1.0",
    "@vite-plugin-ssr/telefunc": "0.1.0",
  }
}

Turnkey solutions are great as long as there's a configuration escape hatch

Yes, that's the plan: 1. the user can completely remove the Stem/Saus layer, 2. Ideally, the Stem/Saus layer can be ejected (let's see if we can find a simple solution for this).

brillout commented 2 years ago

Also, we'll need to define new specs:

I'd say we first develop integrations then write these specs at some later point. The neat thing here is that these integration points are shared between vps and Saus.

louwers commented 1 year ago

Might be good to mention here that stem-react is a thing now.

Would it make sense to have a 'Stem boilerplate' example repo? I'm interested in stem-vue.

brillout commented 1 year ago

👍 I've been finalizing the new Extensions API which I'll release once I process gajus's feedback (pretty important, he's a gold sponsor). The plan after that is to further experiment and then promote Stem.

So, yes, now is a good time to start working on stem-vue! (The latest Extensions API lives at main — it isn't release yet.)

Would it make sense to have a 'Stem boilerplate' example repo?

At the moment, the Stem React example is living at: https://github.com/brillout/vite-plugin-ssr/tree/main/examples/stem-react.