⚗️ Experiments: github.com/vikejs/research/issues.
research's Introduction
research's People
research's Issues
A new kind of database: event-based + computed props + full-stack reactive + solid business model
Someone shares an image on Facebook:
- Database saves
event
"User X shared image https://example.org/image.jpg". - Facebook defined a
computed
prop that downloads the image and meta data.
Someone clicks on the like button of the image:
- Database saves
event
"User Y likes image". - Facebook defined a
computed
prop "total amount of likes" (the computed prop is just a JavaScript function that runsMath.sum()
over the array of "User like" events) => the databse automatically re-runs the computed prop function => the computed prop is automatically updated. - Row-level permissions:
// Read export async function read({ row, context }) { if (context.user.role === 'admin') { return true } if( row.rolesAllowed.includes('public')) { return true } // Forbidden return false } // Mutations export async function write({ row, rowBefore, context }) { if (row.authorId === context.user.id) { return true } // `rowBefore` is `null` if mutation is `INSERT` if (rowBefore === null) { return true } return false }
- The database has a built-in ORM with deep UI framework (React, Vue, ...) integrations.
Everything is done automaticallly, e.g. the database automaticallly creates a socket connection to the server in order to listen to the corresponding database updates.
import { useDb } from '@new-kind-of-database/react' function Image({ id }) { // `useDb.findOne()` is a React Hook (=> works with Suspense parent loader component) const { src, totalLikes } = useDb.findOne(id, select: { src: true, // We mark `totalLikes` as reactive => when `totalLikes` changes, the ORM // automaticallly updates the component (using React's hook system) totalLikes: 'reactive' }) return <> <img src="{src}" /> <p> Number of likes: {totalLikes} </p> </> }
This leads to many drastic DX improvement, especially for user-centric highly-reactive apps such as Twitter or Facebook.
Solid business model: offer a SaaS with all bell and whistles (automatic scale, automatic backup, etc.). That said it's of paramount importance to fully support self-hosted, and open sourcing the entire source code (include of the SaaS). We are not afraid of AWS doing a SaaS clone; users will prefer the original over the AWS copy-cat.
If you feel drawn to work on this, let me know. Also, I'm ok with you being the CEO and me only being the "master mind" behind the whole thing.
Vite Server RFC
Authors: @cyco130, @brillout. (Let us know if you want to join us in writting this RFC.)
Structure of this RFC:
- Motivation: why this RFC is important.
- High-Level Goal: the future this RFC enables.
- Plan: strategy of progressively implementing this RFC.
Motivation
Vite's native SSR API has enabled deep collaboration between SSR frameworks.
This RFC enables the same for deploy: there are an increasing number of deploy targets (Deno Edge, Supabase Functions, Netlify Functions, Vercel, Cloudflare Workers, AWS Lamda, AWS EC2, ...) and, instead of having each SSR framework reinventing the wheel, this RFC enables a common ecosystem of deploy integrations.
Deploy integration is deeply intertwined with the topic of how Vite should handle the server.
That's why this RFC is called Vite Server RFC
. But the most important consequence of this RFC is a shared ecosystem of deploy integrations.
Vite is becoming the "Web Compiler Commons" that powers a flourishing ecosystem of tools and frameworks. This RFC spurs that.
High-Level Goal
The goal is to enable the following DX.
In this section, we intentionally skip middle- and low-level details. We discuss potential problems in comments to this RFC, and RFC related tickets (see Plan).
We show an example for Express.js and Cloudflare Workers.
Express.js Example
// vite.config.js
import { svelteKit } from 'sveltekit/plugin'
/* Or:
import { marko } from 'marko/plugin'
import { rakkas } from 'rakkas/plugin'
import { ssr } from 'vite-plugin-ssr/plugin'
*/
export default {
// Note the new config `vite.config.js#server`
server: './server.js'
plugins: [
svelteKit(),
],
}
Note that all these SSR frameworks (SvelteKit, Marko, Rakkas,
vite-plugin-ssr
) have shown intereset in such RFC.
// server.js
import express from 'express'
import { viteMiddleware } from 'vite/server/dev' // Vite's middleware for development
import { stripeMiddleware } from 'stripe/server'
import { expressAdapter } from 'vavite/express'
startServer()
async function startServer() {
const app = express()
app.use(expressAdapter([
// `viteMiddleware` includes:
// - Vite's dev server
// - The middleware of Vite plugins, e.g. the SSR middleware of SevleteKit / ...
viteMiddleware,
stripeMiddleware,
// ...
]))
app.listen(3000)
console.log(`Server running at http://localhost:3000`)
}
Vavite is a collection of adapters developed by @cyco130. Note that there is no lock-in here: both sides of adapters follow an open specification.
The server.js
file above showcases Middleware Mode: the user manually sets up and controls the server. Middleware Mode is needed for advanced integrations such as Stripe. (This example makes Stripe integration seem easy, but a real world integration is more complex and warrants the need for Middleware Mode.)
The goal of this RFC is to also support Server Mode: the user uses Vite's built-in dev server. This means that, with Server Mode, the user doesn't have to write the server.js
file.
Server Mode is the default but the user can opt-in Middleware Mode by setting vite.config.js#server
.
If SSR frameworks show interests for it, we can develop a possibility for plugins (e.g. the SvelteKit plugin) to provide a custom built-in server for Server Mode, in replacement of Vite's built-in server.
CLI integration:
$ vite
The CLI command $ vite
executes the server entry defined at vite.config.js#server
(or, if missing, Vite's built-in server). It would support server HMR.
$ vite build
The CLI command $ vite build
builds not only the browser-side JavaScript, but also the server entry defined at vite.config.js#server
. (The user can then, for example, use the server production build for a production server on AWS EC2.)
Cloudflare Workers Example
// vite.config.js
import { cloudflareWorkers } from 'vite-plugin-cloudflare-workers'
import { svelteKit } from 'svleteKit/plugin'
/* Or:
import { marko } from 'marko/plugin'
import { rakkas } from 'rakkas/plugin'
import { ssr } from 'vite-plugin-ssr/plugin'
*/
export default {
plugins: [
svelteKit(),
cloudflareWorkers({
worker: './worker.js'
})
]
}
// worker.js
// A Cloudflare Worker for production
import { viteMiddleware } from 'vite/server/prod' // Vite's middleware for production
import { stripeMiddleware } from 'stripe/server'
import { cloudflareAdapter } from 'vavite/cloudflare-workers'
const handler = cloudflareAdapter([
// `viteMiddleware` includes the middlewares of all Vite plugins, e.g. the SSR middleware of SvelteKit
viteMiddleware,
stripeMiddleware,
// ...
])
addEventListener('fetch', handler)
Here again, Middleware Mode is indispensable for advanced use cases. (FYI Stripe is actually showing interest in supporting Cloudflare Workers.) That said,
vite-plugin-cloudflare-workers
can provide a built-in worker to enable Server Mode for Cloudflare Workers.
CLI integration:
$ vite build
The CLI vite build
takes care of everything, including bundling worker.js
into a single file. (Plugins, such as vite-plugin-cloudflare-workers
, can add a custom build step.)
$ vite deploy
Plugins, such as vite-plugin-cloudflare-workers
, can provide a $ vite deploy
implementation.
Vite's dev server assumes a filesystem, but no filesystem exists in the context of a Cloudflare worker. This means that
$ vite
uses Vite's built-in dev server instead of usingworker.js
.
Plan
We progressively implement parts of this RFC.
For example, we can start by implementing:
- vitejs/vite#5936
- vitejs/vite#6394
- TODO: create ticket for allowing plugins to provide a deploy implementation for
$ vite deploy
. - TODO: create ticket for allowing plugins to add server middleware.
- TODO: create tickets for vavite (e.g. ticket for dual support for connect-compatible middlewares as well as non-connect-compatible middlewares)
- TODO: create ticket for implementing vavite-compatible Vite dev middleware.
- ...
We progressively include implemented RFC parts into Vite releases. We don't foresee any breaking changes; we can hook into but not disrupt Vite's release lifecycle.
Stem
@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:
- Extend vps
- Extend Rakkas (@cyco130 if you want?)
- Modify the Vite config
- Add middlewares to HatTip
- Add scripts to the client-side
- Wrap the root view component
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. 😀.)
Imperative TypeScript alternative (drastically simpler than TypeScript)
The idea is to allow types to be defined imperatively:
type SomeType<T> = {
if (T is string)
return boolean
if (T is SomeOtherType)
return string
return never
}
To-do:
- Create a better example that showcases both how much simpler and how much more powerful imperatively defined types would be.
- Create a new TypeScript feature request for it https://github.com/microsoft/TypeScript/issues. Ideally it is the TypeScript team that would add such feature to TypeScript. Otherwise, someone else will eventually create such imperative TypeScript alternative.
Contribution welcome to work on the to-do list above or even create a simple prototype.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.