Skip to content

Handlebars syntax is not bad at all, we can make it faster than React, Vue, or Svelte #361

@trusktr

Description

@trusktr

Summary

The new component system Solid.js looks like React (because it uses JSX syntax), but it compiles to something way better using dependency-tracking reactivity just like Meteor's reactive variables and tracker autoruns (called "signals" and "effects" in Solid).

This makes Solid.js an excellent pairing for Meteor because the paradigms match perfectly.

I believe we can use a package like https://www.npmjs.com/package/handlebars-to-jsx to compile Blaze templates into super fast Solid.js runtime equivalent to what Solid.js compiles JSX to.

Background

To give a brief example, here's how to use Solid inside of Meteor:

import {createEffect, createSignal} from 'solid-js'
import {ReactiveVar} from 'meteor/reactive-var'
import {Tracker} from 'meteor/tracker'

const meteorCount = new ReactiveVar(0)

setInterval(() => meteorCount.set(meteorCount.get() + 1), 1000)

// Solid's createSignal is the equivalent of Meteor's ReactiveVar
const [solidCount, setSolidCount] = createSignal(0)

Tracker.autorun(() => {
  console.log('meteor count is: ', meteorCount.get())

  // map the Meteor reactive var to the Solid signal
  setSolidCount(meteorCount.get())
})

// Solid's createEffect is the equivalent of Meteor's Tracker.autorun, any used signals become dependencies of the effect.
createEffect(() => {
  console.log('solid count is: ', solidCount())
})

function MySolidComponent() {
  // Solid's JSX
  return <div>The count is {solidCount()}</div>
}

MySolidComponent compiles to something like the following (simplified, this hand written version is less optimized):

function MySolidComponent() {
  // Solid's JSX (looks like React)
  const div = document.createElement('div')
  const staticText = new Text('The count is ')
  const dynamicText = new Text('')

  div.append(staticText)
  div.append(dynamicText)
  
  createEffect(() => {
    // Update the specific part of DOM any time the solidCount signal changes
    dynamicText.nodeValue = solidCount()
  })

  return div
}

How

To make this work, the best way would be to replace internals of Meteor Tracker with Solid reactivity in a backwards-compatible way. Then, with a handlebars-to-JSX transformation convert HTML to the JSX output (possibly optimized to avoid a JSX step, and just go straight to equivalent output).

Why

Solid has gained popularity because of its simplicity, and performance. It beats well-known libs in some benchmarks, without sacrificing dev experience (actually improving it in various cases, for example compared to React). The JS Framework Benchmark is one example benchmark.

(@ryansolid @edemaine)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions