alephjs / aleph.js

The Full-stack Framework in Deno.
https://aleph.deno.dev/
MIT License
5.26k stars 168 forks source link

[RFCs] Alef Component Concept #53

Open ije opened 3 years ago

ije commented 3 years ago

A new component system will ship as part of v0.4, I want to try some new ideas to write components with JSX which should be simple, fast and typed. Those ideas are inspired by React and Svelte, it's standard JSX syntax, and with high performance AOT compiler in Rust. Core features include:

import Logo from './Logo.alef'

const name: Prop<string> = 'World' // prop

let n: number = 0 // state
const double: Memo<number> = 2 * n // memo

// effect
$: () => {
  console.log('mounted')
  return () => console.log('unmounted')
}

function increase() {
  n++ // eq `setN(n => n+1)`
}

// elements
$t:
<div>
  <Logo />
  <h1>Hello {name}!</h1>
  <p onClick={increase}>double is {double}</p>
</div>

// styling
$style: `
  /* unused h1 (tree-shaking) */
  h1 {
    font-size: 200%;
  }
  p {
    color: ${Math.abs(n) >= 10 ? 'red' : 'green'}    
  }
`

Please star https://github.com/alephjs/alef-component to get project progress.

shadowtime2000 commented 3 years ago

I like how it uses more implicit sections like Marko instead of explicitly being separated into different parts. @ije Do you have an idea of what the compiler output may look like for it? With no runtime, would it just compile into some variable declarations and some document manipulations?

shadowtime2000 commented 3 years ago

@ije I'd recommend you create the compiler and such in a different repo called alef or something to allow others to more easily use it without Aleph.

shadowtime2000 commented 3 years ago

I like it's conciness though compare it with React

import { useState } from "react";

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment!</button>
    </>
  );
}
let count = 0;

<>
    <p>Count: {count}</p>
    <button onClick={() => count++}>Increment!</button>
</>
ije commented 3 years ago

@shadowtime2000 yes, i will create a repo to implement this.

ije commented 3 years ago

@shadowtime2000 or no fragment

let count = 0;

<p>Count: {count}</p>;
<button onClick={() => count++}>Increment!</button>
shadowtime2000 commented 3 years ago

@shadowtime2000 or no fragment

let count = 0;

<p>Count: {count}</p>;
<button onClick={() => count++}>Increment!</button>

Wow, even better!

shadowtime2000 commented 3 years ago

@ije I am not an expert on web performance and bundle size, but wouldn't having no runtime cause a big bundle size with stuff like reactivity, actually rendering stuff, and memoization?

ije commented 3 years ago

huge application may have this issue, most applications should be lighter than react, we will see

iFwu commented 3 years ago

I think https://github.com/BuilderIO/jsx-lite and https://github.com/ryansolid/solid can be considered.

shadowtime2000 commented 3 years ago

@iFwu What exactly do you mean by that? The compiler I believe will already use something like what SolidJS does, except I think in some cases it won't even do that.

ije commented 3 years ago

hey @iFwu, as @shadowtime2000 mentioned, the AOT compiler will transpile JSX to native Dom operations, no need to compile template in browser like solid do

iFwu commented 3 years ago

Thanks for replying. I got the difference now. At first look, I thought the concept is fairly alike to SolidJS. But I didn't see how the reactivity will be like in an AOT compiler. I will check Svelte for the details. If fine-grained reactivity with JSX can be implemented without templates, I'll be very excited.

shadowtime2000 commented 3 years ago

@ije After v0.3.0 will we start slowly dropping React support or something? Or will React still be supported?

ije commented 3 years ago

@shadowtime2000 React is ever the first framework in Aleph.js, and i wish we can import react component in Alef Component in the future.

shadowtime2000 commented 3 years ago

Will we add a feature like automatic selection of components depending on usage of Alef or React? Like if we import deno.land/x/aleph/link.ts, will it automatically import a deno.land/x/aleph/link/react.ts or a deno.land/x/aleph/link/alef.alef depending on what is importing it?

shinspiegel commented 3 years ago

I was wondering, we already have a lot of frameworks and ways to implement reactive (and non-reactive) web interfaces, do we need another one?

I think, should be better to implement other frameworks like Vue and Angular, which would fit best? Or I'm missing something?

ije commented 3 years ago

@shinspiegel i agree with you, the next stage(0.4) the most important idea i guess is to bring Vue to alephjs. Angular i'm not sure since i'm not the user of it.

ije commented 3 years ago

however, the alef component is an experience feature i want to try.

shadowtime2000 commented 3 years ago

I think Angular may not be fit for this because it has a ton of tooling that needs to be set up for it to work. Vue would be pretty nice in setting it up.