Remix.run Logo
apatheticonion 18 hours ago

One of the issues I find is that JavaScript itself holds back the ability of tool makers to experiment with practical novel alternatives.

TypeScript's tsx macro is designed with React-like libraries in mind and alternative frameworks need to create custom file types and LSPs just to get off the ground.

I'd love to see the JavaScript spec define a generic macro system to enable experimentation (with IDE support) for alternative frameworks.

For example, jsx/tsx could be expressed with an inline macro

    export App() {
      return jsx!(<div>Hello World</div>)
    }
While something like Vue or Svelte could implement their own inline macros rather than investing in tooling for their custom file types

   export class App {
      #[onChange]    // <- makes the prop a getter/setter
      value = Hello World
      
      constructor() {
        setTimeout(() => {this.value = "updated"}, 1000)
      }

      render() {
        return vue!(<div>{{this.value}}</div>)
      }
   }
If it's part of the spec, the browser could interpret it without a preprocessor and compilers like tsc/swc etc could precalculate the transformations and ship the transformed JavaScript (like we do today with tsx)
b_e_n_t_o_n 17 hours ago | parent [-]

Js has decorators for class fields so you wouldn't even need a macro for that. `@state accessor value = "hello world"` works.

I do like the idea of macros in general though.

apatheticonion 17 hours ago | parent [-]

I explored JS decorators in the past but decorators are different in that they are a runtime operation that can't be statically compiled and can't be used on non-class properties.

You probably know this already but macros on the other hand are just dumb expansions/computations of syntax transformed at compile time, like

    let result = add!(1 + 2);
Would compile into

    let result = 3;
Including macros into the JavaScript spec is a bit weird because it's an interpreted language so compile-time concepts don't really make sense (which is probably why decorators were proposed).

But JavaScript is compiled more frequently than it isn't and we apply a crazy amount of transformations to it (typescript, tsx, path manipulation, styled-components, etc). IMO standardized compile-time manipulation with LSP integration would go a long way for language ergonomics.

That would also mean transformations for things like jsx could be run _in the browser_ allowing people who don't want to use a bundler to run their code without one.

    // Removed by the bundler, can also be used in the browser
    import jsx from "react/jsx" 

    const App = () => jsx!(<div>>Foo</div>)
Projects like this : https://github.com/developit/htm are an expression/symptom of that need
b_e_n_t_o_n 15 hours ago | parent [-]

Oh yeah I agree it would be useful.