Skip to content

RFC - babel-macros #2730

@threepointone

Description

@threepointone

Code modifiers are becoming popular in the javascript ecosystem, via babel-plugins (eg - many css-in-js libs, relay, etc). This issue is to open discussion on a generic system to include them in CRA apps, but still honouring the zero-config philosophy.

The proposal here is to have a constrained form of babel-plugins, disguised to appear like regular libraries. A short writeup on what it would look like here - https://github.com/threepointone/babel-macros/blob/master/README.md

  • modifiers/'macros' would be isolated in files with .macros.js suffixes
  • there would no real trace of them in the final bundle stripping imports of all *.macros.js
  • considering they're localised and used on demand, I expect them to have little effect on build performance, so can be enabled in both dev/prod
  • because there's no dependence on webpack, it should still work with other js tooling like jest, etc.

I'm looking for feedback on the same before I start writing code for it, as well as possible first implementations (maybe a simple css-in-js lib?)

If this doesn't belong here, feel free to close the issue. Thanks!

Activity

threepointone

threepointone commented on Jul 6, 2017

@threepointone
Author

a real world example - a theoretical, simpler port of glam would look like this -

  • npm install glam.macros
// app .js
import css from 'glam.macros'

let red = css` display: flex; color: red; `

React.render(<div className={red}>
  red text!
</div>, window.app)

would compile down to

let red = require('glam.macros/runtime')(() => 
  ['.css-7asd4a { display:flex; color: red; }']
)

React.render(<div className={red}>
  red text!
</div>, window.app)

during runtime, it would render html that looks like

<div class='css-7asd4a'>
  red text!
</div>

and add css to a stylesheet

.css-7asd4a { 
  display:flex; 
  color: red; 
}

additionally, we could also extract the css to a real .css file and automatically import them (leveraging CRA's webpack css loader automatically), and all the other goodies from glam/emotion.


another example would be relay.

instead of -

import Relay from 'relay' 
// ...

Relay.QL`...`

you'd split the two as

import Relay from 'relay'
import QL from 'relay.macros'
// ...

QL`...` 

but it would still generate code similar/same to relay's own plugin

threepointone

threepointone commented on Jul 6, 2017

@threepointone
Author

Another usecase - integrating @kentcdodds' preval lib https://github.com/kentcdodds/babel-plugin-preval to inline node.js code into client side code for easily inlining file contents, etc without using a custom webpack loader(!)

EnoahNetzach

EnoahNetzach commented on Jul 6, 2017

@EnoahNetzach
Contributor

Cool and super-useful!

A curious question: would this mechanism be enabled on npm module macros only?
I would kinda like to be able to write a macro in the project itself without having to publish it, although I know this potentially breaks the CRA philosophy.

kentcdodds

kentcdodds commented on Jul 6, 2017

@kentcdodds
Contributor

I think the point would be that you just import the macros from anywhere and it would apply itself on the file you're importing. I can definitely see how this could be accomplished using a babel plugin with 0 configuration on the part of the end user. If there's interest in this, I'll build it (because it would be SO FUN!)

suchipi

suchipi commented on Jul 6, 2017

@suchipi

So something with a name like babel-plugin-macros that looks for imports/requires of /.*\/macros/, and when it finds them, imports a babel plugin from the macros lib (eg require("glam.macros/plugin"), then applies it to the Program that contained the import/require?

Sounds awesome

kentcdodds

kentcdodds commented on Jul 6, 2017

@kentcdodds
Contributor

Yep, that's what I was thinking @suchipi 😄

threepointone

threepointone commented on Jul 6, 2017

@threepointone
Author

Not to the whole program, but to the specific call sites.

kentcdodds

kentcdodds commented on Jul 6, 2017

@kentcdodds
Contributor

The plugin would be responsible for what it does I think. Most of the time it would just find the call sites. Could make a helper to make finding call sites easier, but would want the flexibility of the whole program. I'm busy tonight, but can probably start on this tomorrow...

threepointone

threepointone commented on Jul 6, 2017

@threepointone
Author

That constraint is important, hence the proposal. Else it's pretty unrestrained and you'll have all the problems of the babel plugin ecosystem (and why this was called macros in the first place, from lisp)

This is the basic sketch https://github.com/threepointone/babel-macros/blob/master/README.md

suchipi

suchipi commented on Jul 6, 2017

@suchipi

Ah, so it would only work for function calls, tagged template strings, and JSX, and could only modify the node where it was "called". That's an important distinction.

Which "problems of the babel ecosystem" are you trying to avoid?

threepointone

threepointone commented on Jul 6, 2017

@threepointone
Author

2 big ones are plugin ordering, and implicit changes (you won't be able to tell what changes will happen on a source file just by looking at it)

threepointone

threepointone commented on Jul 6, 2017

@threepointone
Author

If you want wholesale babel plugins and/or loaders, the option to eject remains, and is likely a better option.

kentcdodds

kentcdodds commented on Jul 6, 2017

@kentcdodds
Contributor

Oh, now I finally understand your babel-macro thing. Makes total sense. I hope nobody works on this before I get a chance to tomorrow. My mind is racing with ideas 😀

kentcdodds

kentcdodds commented on Jul 6, 2017

@kentcdodds
Contributor

But if course I'm just kidding 😉 if someone else wants to build this, I can't stop you 😀

suchipi

suchipi commented on Jul 6, 2017

@suchipi

Sounds a lot like OCaml extension points, which was the result of people saying "letting them change the whole parser makes things too confusing".

Do you think @decorator support would be a good idea, too?

94 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @threepointone@mlusetti@coodoo@Timer@bjankord

        Issue actions

          RFC - babel-macros · Issue #2730 · facebook/create-react-app