top | item 8265945

JSX: XML-like syntax extension to ECMAScript – Draft specification

76 points| peterhunt | 11 years ago |facebook.github.io

43 comments

order
[+] jonchang|11 years ago|reply
Facebook has been doing a lot of work in this area, initially implemented in PHP by Marcel Laverdet in 2010, called XHP[1]. Not only does it permit you to embed conformant HTML into your PHP code without inadvertently introducing XSS vectors, but it also allows you to compose HTML primitives into high-level markup. Stefan Parker has been regularly blogging since 2011 about how Facebook uses XHP in its UI design; one of the best posts on the topic is here[2]. You may also recall the now-defunct "Facebook Lite" which was written completely in XHP.

Laverdet also implemented something similar for node.js called js-xml-literals[3], which I don't think has gained much traction. As for how it's different from E4X, refer to this page[4], which makes the argument that parsing and producing XML are two different tasks; E4X attempts to do both while all of these other approaches focus on producing XML.

(I don't think that this perspective on the history of react.js/jsx has been well-publicized before, hence the post.)

[1]: https://www.facebook.com/notes/facebook-engineering/xhp-a-ne...

[2]: http://codebeforethehorse.tumblr.com/post/52824249342/buildi...

[3]: https://github.com/laverdet/js-xml-literal

[4]: https://github.com/laverdet/js-xml-literal/wiki/Differences-...

[+] kiyoto|11 years ago|reply
My only quip about this JSX is nomenclature: Oku et. al. at DeNA open-sourced a typed variant of ECMAScript under the exact same name a couple of years earlier: http://jsx.github.io/

With Facebook's brand and recognition, I am sure this JSX will eclipse the other JSX, which is rather unfortunate.

[+] marcuswestin|11 years ago|reply
I think this is a great and well intended effort.

One of the biggest use cases for Javascript is to manipulate and create DOMs. jQuery solved the manipulation part beautifully, but DOM creation remained a hassle. Lots of templating solutions have been attempted, but none of them seem to hit the sweet spot just right (that's a primary reason why there are so many).

JSX is a novel contender that may be just right - even if it's not, it will hopefully push us as a community towards a better solution by offering a very new approach with its own benefits and problems.

Thanks to the peeps at fb for taking the time and effort to make JSX bigger than just reactjs!

[+] cdata|11 years ago|reply
The example used to demonstrate template literal "syntax noise" in this proposal is an unfair exaggeration, in my opinion.

JSX is handy because it allows authors to think about the hierarchical relationship of components in terms of how they would be laid out in something like HTML. Template literals may not be ideally suited to the JSX case, but they represent a promising "native" solution to the problem JSX tries to solve. I'm always happier when I can leverage something that is native to the language I'm using to solve a problem.

[+] jlongster|11 years ago|reply
Really surprised this doesn't mention my project that implements JSX as a sweet.js reader. It's a much better sweet integration than the one list that forces you to use a very different syntax to use JSX.

https://github.com/jlongster/jsx-reader

(Hey React guys... I know you know of my project, what's up with that?)

[+] spicyj|11 years ago|reply
This is a mistake; I think we got it confused with andreypopp's sweet-jsx by mistake.
[+] mambodog|11 years ago|reply
It's not an exhaustive list of JSX implementations.
[+] themartorana|11 years ago|reply
I can't quite see the logic behind a markup syntax for a transpiler to output code that builds other markup.

Can someone with a better understanding explain what the benefit is here? It doesn't seem easier than JS or HTML so I don't understand the point of the abstraction. But I haven't built much on the browser-side in a few years so I am certain I am missing something.

[+] hcarvalhoalves|11 years ago|reply
In the "perfect world", we would be using LISP, and our code would be data and our data would be code.

We're stuck with JS, so it's convenient to have a declarative syntax that compiles to JS, because nested function calls suck. As the doc states:

> The purpose of this specification is to define a concise and familiar syntax for defining tree structures with attributes.

This can be used for anything, it has nothing to do with HTML actually. Just like there are many languages and frameworks where you describe UIs with some flavor of XML that compile behind the scenes to API calls to create windows, append buttons, etc.

[+] tracker1|11 years ago|reply
First, your markup for the component lives with the JS handling for that component... you can require in child components and render them in the same manner.. using harmony/es6 syntax...

    var React = require('react')
    var other = require('../other-control')
    var { div, h2 } = React.DOM;
    
    module.exports = React.createClass({
      render: function(){
        return div({className="foo"}, [
          h2(null,'My playa'),
          other()  
        ]);
      }
    });
I don't use the JSX syntax, for testability, coffee-script can be a lot cleaner... With multiple components in a larger application and webpack it gets really nice.
[+] hderms|11 years ago|reply
I think it's mostly to avoid the whole mess of having Javascript arbitrarily selecting DOM elements that are declared elsewhere and then manipulating them/cloning them to create some new DOM. If you were creating some DOM/code component intended to act as a black box, it may be conceptually simpler to have the DOM part of it created via code and explicitly referenced by the code. YMMV
[+] bastawhiz|11 years ago|reply
So..uh...this was a thing. And nobody wanted it. So it was deprecated and killed. See the "Prior Art" section at the bottom of the page.

http://en.wikipedia.org/wiki/ECMAScript_for_XML

Brendan Eich was quoted as saying something along the lines of "E4X is crazyland". Parsing it is hard as hell to do right. Think of all the tooling that's out there for JavaScript right now that will either a.) not support JSX code or b.) bloat up beyond belief as it takes into account the suddenly absurd requirements necessary to deal with a similar-but-not-quite-XML-or-even-HTML-for-that-matter syntax. Oh, you want to lint that JavaScript? Bless your heart! You want to add syntax highlighting? Love will find a way. You want to use other static analysis tools, sweet.js macros, or anything else non-trivial? How cute!

So essentially, it's a great way for Facebook to push React.js without making React.js a standard.

[+] grrowl|11 years ago|reply
JSXHint exists[1] and works well, and highlighting libraries exist[2]. Have you actually tried the syntax? It makes sense when used with React.js (which is quite lovely), as almost all of the new syntax exists within a render() function. It's also leaner syntactically than EMCAScript for XML, without introducing additional weirdness like "object.@items" selectors.

Work with both JSX and regular JS in React and you'll see why they're doing this.

[1]: https://github.com/STRML/JSXHint

[2]: https://github.com/reactjs/sublime-react

[+] nnethercote|11 years ago|reply
> So it was deprecated and killed.

I had the pleasure of being the person who removed support for it from Mozilla's codebase: https://bugzilla.mozilla.org/show_bug.cgi?id=788293. Over 11,000 lines of code removed. Everyone on Mozilla's JS team was happy to see that code gone, because it had caused endless problems over the years.

I gained even more joy when I discovered that this removal had temporarily inconvenienced the NSA: https://bugzilla.mozilla.org/show_bug.cgi?id=788293#c74.

[+] coldtea|11 years ago|reply
>So..uh...this was a thing. And nobody wanted it. So it was deprecated and killed.

So was Harmony. And then it was ressurected.

>Brendan Eich was quoted as saying something along the lines of "E4X is crazyland"

I don't think Brendan Eich has his finger in the pulse of the modern web, so to speak.

[+] MichaelGG|11 years ago|reply
>Balanced named tags is a critical syntactic feature of the XML-style notation.

I guess there's an argument for everything. But I thought in general, people usually found XML's verbose endings to be noisy and useless. It could always be opt-in, so you only need to add them where needed.

  <start><item>something</>...</start> 

  Or you could just add a comment.
[+] Skywing|11 years ago|reply
So, yea I think this is a great thing and I don't mind JSX. It has been a pleasure to use ... I think. I can't help but be reminded about original PHP, though. When PHP was new, you could write PHP but then you could also write your markup in the same file. The end result was a bunch of bad PHP and markup. JSX is not quite is liberal, but it's along the same vein. You kind of have markup in your Javascript, now (I say now, but I guess you did before in some cases where you built DOM elements with JS). Especially with components that also have HTML-literal content in them, like labels and text and stuff. Like, to literally change the text in a form or something, you might have to go edit your Javascript file ... no wait, your JSX file to change that. Javascript is also already enough of a pandoras box, in regards to common patterns and "how to do X or Y." I don't really know how to articulate my thoughts on it yet, but I feel like I lean towards rather not having to look at code with JSX in it than having to do so.
[+] pistle|11 years ago|reply
Where's the transformation language JSXT? O.o

Why are nearly all the examples pushing literal UI concerns into the code, if not tightly weaving it with the controller?

I see what it is, but I see nothing about why it is - I'm open for understanding. Someone please help.

[+] thomasfoster96|11 years ago|reply
As much as Facebook's efforts to fix the tools they are forced to use are valliant, this is a little bit ugly. Still, points for trying.
[+] aeosynth|11 years ago|reply
[+] twfarland|11 years ago|reply
I have found it easy enough to just use json-serializable literals to represent html, e.g:

    ['div', {id: 'main'}, 
        ['h1', 'Some title'],
        ['p', 'Some text']]
I wrote a little function to turn this kind of thing into an html string (https://github.com/twfarland/don), but it could also be used as the view descriptor for some kind of view component ala React. Might work on that...
[+] kijin|11 years ago|reply
Somebody please enlighten me as to why this is better than good ol' JSON or XML/SGML/HTML, especially if it's meant to be processed into something else anyway?
[+] kansface|11 years ago|reply
JSX is transpiled into Javascript (which generates HTML at runtime)- its function in React is basically that of a templating language. JSX also allows inlining Javascript in a limited fashion. I could not imagine a sane implementation using JSON. As for XML and friends, you would have to shoehorn in supporting JS.
[+] k__|11 years ago|reply
Some IDE plugin for this would be nice.

JSX -> JS -> JSX

Just JS gets committed into the repository.

When the developer likes/needs JSX he just uses the JSX like an overlay for a specific code part.

[+] tgriesser|11 years ago|reply
Many of the comments seem to be along the lines of "why create a markup syntax to build more markup and throw it in JavaScript" - In my opinion that's not the real benefit of JSX, but just one use case.

The great thing about JSX is that it doesn't build markup. It doesn't even need to be used for markup, it can be used for anything. It's frequently associated with markup because it has been used alongside React, but JSX standalone is a simple syntactic transform for XML-ish notation to JavaScript.

This is quite convenient in some cases, as you can elegantly write DSL's, where each of the tag names are JavaScript functions - and writing the equivalent JavaScript would look something closer to a lisp (moving the function name to the right of the paren).

This:

  <Database name="business">
    <Table name="user">
      <Column name="id" type='int' length={10} />
      <Column name="first_name" type='string' length={255} />
      <Column name="last_name" type='string' length={255} />
      <Column name="choice" type='enum' values={['a', 'b', 'c']} />
    </Table>
    <Table name="account">
      <Column name="id" type='int' length={10} />
      <Column name="first_name" type='string' length={255} />
      <Column name="last_name" type='string' length={255} />
      <Column name="choice" type='enum' values={['a', 'b', 'c']} />
    </Table>
  </Database>
run through the compiler[1] becomes this:

  Database({name: "business"}, 
    Table({name: "user"}, 
      Column({name: "id", type: "int", length: 10}), 
      Column({name: "first_name", type: "string", length: 255}), 
      Column({name: "last_name", type: "string", length: 255}), 
      Column({name: "choice", type: "enum", values: ['a', 'b', 'c']})
    ), 
    Table({name: "account"}, 
      Column({name: "id", type: "int", length: 10}), 
      Column({name: "first_name", type: "string", length: 255}), 
      Column({name: "last_name", type: "string", length: 255}), 
      Column({name: "choice", type: "enum", values: ['a', 'b', 'c']})
    )
  )
I find the first easier to read / reorganize in blocks, which can be useful in lots of situations... definitely not all situations - but having declarative markup while being able to imagine it executing as the latter, constructing actual JS objects with specific logic built in - rather than needing to "parse" the XML tree and deal with an extra step of execution, etc, etc.

[1]: http://facebook.github.io/react/jsx-compiler.html

[+] lucian1900|11 years ago|reply
I find the first to be much worse, if for no other reason because of the redundant closing tags.
[+] roryokane|11 years ago|reply
> JSX standalone is a simple syntactic transform for XML-ish notation to JavaScript

But not necessarily the same translation as in your example (that is, tags to function calls and attributes to first arguments). Perhaps all existing implementations work like that, but the spec leaves the JavaScript representation undefined. The spec draws attention to this intentional ambiguity when it lists “a set of transpilers that all conform to the JSX syntax but use different semantics on the output”.

[+] Hytosys|11 years ago|reply
It's always odd to see such an effort against the value of separation of concerns. Facebook's team is heavily invested in the doctrine of PHP of course, so JSX is no surprise.
[+] peterhunt|11 years ago|reply
What concerns are you separating exactly?