January 6th, 2016 | code quality, editor, es6, javascript, nodejs, react |

This post is an extract of a github repo I’m working on chtefi/react-stack-step-by-step to explain step-by-step from scratch a full reactjs stack

The answer is : by applying some linting on your source code.

Code linting is a set of rules to apply, to enforce some styles and rules into the code, and even check if you’re writing bugs (due to typos mostly).

By applying the same rules on the whole source code, you can, for instance, make sure that everywhere there is no missing semicolons (or that there is not semicolons at all if you don’t like them), that the variables are properly named, that the order of methods to override is fixed, that the constructor is the first method, that the depth of the functions is not more than 4 etc. etc.

Hopefully, we can use some presets created by big tech companies to avoid to set them all manually.
Moreover, if they follow those styles, it’s a good opportunity to follow the same ones.!

Let’s see what is needed in order to apply this linting and configure it as you expect.
Moreoever, we will add some special packages to deal with Reactjs code, because that needs more.

What packages to install to do linting ?

We have multiple choices.

  • JSLint : original project
  • JSHint : fork of JSLint
  • ESLint : new recent alternative (2013), pluggable

We are going to stick with ESLint because it supports Reactjs special linting rules through a plugin eslint-plugin-react.

And because the linting is only necessary for the developers, the npm dependency is installed with --save-dev.

$ npm i -D eslint

How to use it

eslint gives us the command of the same name in ./node_modules/.bin/eslint.
It just takes in parameter a folder or a file on which we want to apply some linting such as :

$ ./node_modules/.bin/eslint src

For instance, if we have some ES6 code in there, doing that could lead to some errors :

src\components\App.js
  1:2  error  Parsing error: Illegal import declaration

src\components\Product.js
  1:2  error  Parsing error: Illegal import declaration

It’s because by default, ESLint does not understand ES6.

Before fixing that, let’s simplify our life, and create a npm script command to run this command quickly.

Add a npm script

To avoid to type the eslint command each time, let’s add a simple npm script :

"scripts": {
  "lint": "eslint src"
  ...

Remember: when npm executes the scripts, it has access to the ./node_modules/.bin folder automatically eslint refers to. No need to add the path in the script.

Now, let’s fix our ESLint.

ESLint + ES6 + JSX

As the documentation states, we need to create a file .eslintrc at the root of the project to set the configuration.

First of all, let’s make it understand imports.

{
  "ecmaFeatures": {
    "modules": true
  }
}
6:2  error  Parsing error: Unexpected token const

Now, it does not understand const. Let’s make it understand ES6.

{
  "ecmaFeatures": {
    "modules": true
  },
+ "env": {
+   "es6": true
+ }
}
25:8  error  Parsing error: Unexpected token <

Now, it does not understand JSX it seems. Let’s make it understand JSX.

{
  "ecmaFeatures": {
+   "jsx": true,
    "modules": true
  },
  "env": {
    "es6": true
  }
}

Boom, it passes without error !
That means it could parse it properly at least.

There is no error, not because the code is already perfect, but because : All rules are disabled by default.

But there are a ton of rules, let’s see how to extend some existing defaults. We are not the first person who want to use it right ?

Extends some default ESLint configuration

It’s recommanded to extend the eslint:recommanded set of rules, to begin with.

But we can also extend some other known ones, such as :

  • : want to work at airbnb ? Learn their styles.
  • : a nice style overriding some properties of eslint:recommanded. I’m not fan because it forbids semicolons, commas on the last array item, all those useless things I like to write.

To extends those rules, npm i them or use the eslint:recommanded one directly :

{
+ "extends": "eslint:recommended",
  "ecmaFeatures": {
    "jsx": true,
    "modules": true
  },
  "env": {
    "es6": true
  }
}
3:8     error  "Toolbar" is defined but never used      no-unused-vars
19:378  error  Unexpected trailing comma                comma-dangle

Now we have some linting issues.
But it seems ESLint does not understand yet this kind of program :

import Toolbar from './Toolbar.js';
...

The variable Toolbar is used by (translated to React.createElement(Toolbar)), so the no-unused-vars error is not a true error.

To make it understand that the imported components are used in JSX, we need to install the plugin eslint-plugin-react and add a special rule jsx-uses-react from this plugin, that will remove this ESLint false error.

$ npm i -D eslint-plugin-react
{
  "extends": "eslint:recommended",
  "ecmaFeatures": {
    "jsx": true,
    "modules": true
  },
  "env": {
    "es6": true
  },
+ "plugins": [
+   "react"
+ ],
+ "rules": {
+   "react/jsx-uses-react": 1
+ }
}

Tada, we are left with some true linting errors such as :

19:378  error  Unexpected trailing comma  comma-dangle

This one states that you have a line finishing by a trailing comma in object literal and that you should not (because you have a rule that forbids it).

You can also see this kind of error :

6:19  error  "document" is not defined  no-undef

Javascript environments

ESLint doesn’t know what is document, it didn’t found it in the scope. By default, it does not assume the environment is a browser (because it can be a pure nodejs program, where document does not exist). Therefore, we have to specify we are dealing with javascript that’s going to be used in the browser, and that will have access to document, window, console.log and so on.

{
  "extends": "eslint:recommended",
  "ecmaFeatures": {
    "jsx": true,
    "modules": true
  },
  "env": {
    "es6": true,
+   "browser": true
  },
  "plugins": [
    "react"
  ],
  "rules": {
    "react/jsx-uses-react": 1,
  }
}

There are a lot of different environments, you can find them here http://eslint.org/docs/user-guide/configuring.html.

Examples :

  • node
  • worker
  • mocha
  • jquery

Each of them exposes certain globals (that ESLint will assume they exist) that you don’t need to specify.
You can find the list here https://github.com/sindresorhus/globals/blob/master/globals.json.

Overriding rules

If I want to allow trailing commas, I can override the rule :

"rules": {
  "react/jsx-uses-react": 1,
+ "comma-dangle": 0
}

For comma-dangle rule :

  • 0 means : you don’t care (disabled).
  • 1 means : you get a warning if that happens, it’s tolerated (ESLint will still succeed)
  • 2 means : ESLint is going to fail if that happens

Some rules accept some options to change their behavior.

For instance, if I want to force trailing commas for multilines, it’s possible :

"rules": {
  "react/jsx-uses-react": 1,
+ "comma-dangle": [ 2, "always-multiline" ]
}

This will generate errors if there is a missing trailing comma on arrays or objects that span multiple lines.

The option has no effect if the code is 0 (disabled).
The available options (if there is) depend on the rule, check http://eslint.org/docs/rules/comma-dangle for instance.

Personally, I like those dangle-commas because that means I can switch the lines order without playing with the end-of-lines.

Anyway, as you saw, it’s very configurable and anybody can match its code style and force it everywhere in it source code.
But that’s not useful only for that, but can help to find bugs before runtime.

Bug finding

The biggest issues when typing Javascript are the typos. Because we often lack a good auto-completion, or we are used to type everything, we do typos. And we find them at runtime, not funny eh?

Linting your code to find those typos is a big win :

38:34  error  "decription" is not defined              no-undef

Typo !

It’s never a good idea to disable the rule no-undef, you can understand why.

More Babel syntax available thanks to babel-eslint

ESLint uses espree to parse ES6.
But we are using Babel, and Babel handles some features such as the spread notation that are not handled by espree :

const obj = { a: 1, ...{ b: 2, c: 3 } };

ESLint won’t be able to parse that :

19:18  error  Parsing error: Unexpected token ..

Meaning we need to plug the Babel parser to make it understand.
Hopefully, it’s planned and pretty straightforward, just install this package :

$ npm i -D 

We install the latest beta because it is using Babel 6

And define Babel as the parser of ESLint (that will be our last update to .eslintrc) :

{
  "extends": "eslint:recommended",
  "ecmaFeatures": {
    "jsx": true,
    "modules": true
  },
  "parser": "babel-eslint",
  "env": {
    "es6": true,
    "browser": true
  },
  "plugins": [
    "react"
  ],
  "rules": {
    "react/jsx-uses-react": 1,
    "comma-dangle": 0
  }
}

No more syntax error.

It’s quite standard to use this plugin nowadays, because most Javascript projects are using Babel, thus, you always want to parse your code source with Babel, for any third-party app working with it.

Now, you have a proper ESLint configuration, you can code properly and invite people to code with you. You are sure they will follow the style and conventions you enforced.

It’s often a good opportunity to check the linting when building or publishing your package, for instance, in package.json‘s "scripts":

  "compile": "npm run lint && webpack",

If an error occurs, webpack won’t be executed.

Some common errors

Let’s quickly go through some classic linting errors :

  • "Toolbar" is defined but never used | no-unused-vars : if you’re using it won’t find it unless you are using react plugin in ESLint.
  • "items" is defined but never used | no-unused-vars : a plain js variable you are not using, remove it
  • Unexpected var, use let or const instead | no-var : var is evil
  • Strings must use singlequote | quotes : prefer ' over "
  • Unexpected trailing comma | comma-dangle : the famous trailing comma at the end of multilines
  • Extra semicolon | semi : if you want or don’t want semicolon at the end of statements

As you understood, the keyword on the right is the code you want to look for to understand what it means or to override it as you wish.

In-code ESLint hints

We only deal with a single file .eslintrc for now, meaning it’s global to all our source code.

But sometimes, you want to make some exception, mostly because you added a hack somewhere.
That generates you a linting warning or error and you just want ESLint to ignore it.

You can add special comment in your code to talk to ESLint :

// eslint-disable-line

/*eslint-disable */
... ugl-, err, hacky code ...
/*eslint-enable */

Your text editor / IDE supports linting on-the-fly

Last but not least, every good text-editors or IDEs have a plugin to automatically apply linting to your code when typing, and display a marker next to the line if something is wrong : because you don’t want to check back your console and re-execute the full linting each time you write some lines.

Check your IDE doc for more info.

  • Sublime Text plugin
  • Atom
  • WebStorm
  • Visual Studio

In my case, I’m using the best text editor aka Sublime Text, you need to install :

This is what you can see in your editor :

Have fun !

Générer des classes css avec un nom unique

May 23rd, 2015 | es6, javascript, react, webpack |

A l’heure où l’on parle de micro-services, où on cherche à tout modulariser, et à créer des systèmes à base de dépendances explicites, à ne plus rien mettre dans le scope global et à utiliser le scope local uniquement, histoire de maîtriser ce à quoi on a accès et d’éviter des effets de bord : on utilise encore un moteur CSS où on balance tous les sélecteurs à sa racine, qui utilise donc un scope global. Heureusement, pour ceux qui utilise le shadow DOM, ce problème est résolu. Mais quid de ceux qui ne l’utilise pas ?

Une partie de ce problème peut être évité en adoptant des normes d’écriture et de nommage telle que la norme BEM qui peuvent malgré tout ne pas suffir ou être délicate à utiliser.

Enfin, surtout avec BEM, les noms de classes peuvent être à rallonge, on aimerait bien généraliser le process de minification qu’on utilise sur le contenu des .js et des .css, sur le nom des classes elles-même ! Mais cela oblige à modifier d’une part le nom de la classe dans le fichier .css et également le code js qui l’utilise.

Il est même maintenant possible de complétement se passer de fichier .css et d’utiliser uniquement du style inline (quid des performances ?). Par exemple, avec React, le style peut être défini directement dans les composants javascript, et avec des outils tel que Radium on peut même utiliser les sélecteurs spéciaux css tel que :hover, ou les média queries.

Facebook et le CSS

Facebook a déjà résolu ce problème. Sans doute avez-vous vu la présentation de  où il évoque comment Facebook s’assure qu’il n’y a aucun conflit de nom de classe css, que le scope global n’est pas pollué, et que les développeurs peuvent facilement rajouter du style sans avoir peur d’avoir des effets de bord et de modifier le layout quelque part, sans le savoir.

Ils ont étendu le langage css en rajoutant une syntaxe spéciale pour les sélecteurs : button/container qui ne peut être utilisé que dans le fichier button.css qui a son tour est référence dans un composant React button.js, qui enfin, fait référence à className={cx('button/container')} pour définir la classe d’un élément.

Le process de build vérifie ces références et génére un nom de classe unique à partir de button/container (qui n’est pas valide en CSS) par quelque-chose comme ._f8z qui fera parti du scope css global mais qui n’entrera jamais en conflit avec quoi que ce soit vu que le nom est généré aléatoirement (et est unique), personne ne pouvant le deviner à l’avance. Tout le monde doit donc utiliser ce système pour travailler et styler son contenu.

Moi aussi j’aimerai faire ça. Ca tombe bien, webpack est là.

webpack et css-loader

webpack, et en particulier le plugin css-loader combiné à extract-text-webpack-plugin, permet de former un (ou des) bundle css à partir de fichiers .css .less ou .sass (avec les loaders qui vont bien) qui sont eux-même importés dans des fichiers .js :

import React from 'react';
import './App.less';

export default class extends React.Component {
  render() {
    return 
} }

Avec une configuration webpack de ce genre :

var ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  entry: './src/app.js',
  output: {
    path: __dirname + '/dist',
    filename: 'bundle.js'
  },
  loaders: [
     {
       test: /\.js$/,
       exclude: /node_modules/,
       loaders: [ 'babel-loader' ],
     },
     { // we can do: import './Component.css';
       test: /\.css$/,
       loader: ExtractTextPlugin.extract('style-loader', 'css-loader')
     },
     { // we can do: import './Component.less';
       test: /\.less$/,
       loader: ExtractTextPlugin.extract('style-loader', 'css-loader!less-loader')
     }
   ]
 },
 plugins: [
   new ExtractTextPlugin('[name].css')
 ]
};

Ce build permet de créer un bundle css qui contiendra tout le contenu référencé par les imports de fichiers .css ou .less dans les fichiers javascript.

import './App.less';

css-loader local scope

La nouveauté (d’avril 2015) est une nouvelle syntaxe au niveau des fichiers css pas encore transformés, mais prise en compte par css-loader :

:local(.container) {
  font-size: 30px;
}

Se transforme en :

._3ImWIJ65ktg-PxiyA_aFIC {
  font-size: 30px;
}

Cela signifie que vous ne pouvez plus utiliser simplement className="container", cette classe css n’existe plus. Et vous ne pouvez pas mettre className="_3ImWIJ65ktg-PxiyA_aFIC" quand même ! Il faut importer différemment le fichier .css ou .less :

import AppStyles from './App.less';
...

Les classes définies dans le fichier css seront accessibles via leur nom (si :local(.my-class) alors via my-class) dans l’objet importé, qu’on peut alors utiliser pour indiquer la className. Au niveau HTML, on aura ce rendu :

Autre exemple avec un autre sélecteur css à l’intérieur :

:local(.container) {
  font-size: 31px;
  span {
    letter-spacing: 5px;
  }
}

Cela génère bien :

._3ImWIJ65ktg-PxiyA_aFIC {
  font-size: 31px;
}
._3ImWIJ65ktg-PxiyA_aFIC span {
  letter-spacing: 5px;
}

Au niveau du bundle

AppStyles est en fait simplement un dictionnaire généré et injecté à la volée de la forme :

module.exports = {
  "container":"_3ImWIJ65ktg-PxiyA_aFIC"
};

className et pas style

Attention à bien utiliser className={ AppStyle.container } et pas style={ AppStyle.container } sans quoi l’erreur suivante se produirait :

Uncaught Error: Invariant Violation: The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + 'em'}} when using JSX.

Le nom des classes générées

On peut modifier la manière dont le nom des classes sont générés. Par défaut, il s’agit d’un hash comme on peut voir, mais on peut le modifier de la sorte (via webpack.config.js) :

css-loader?localIdentName=[hash:base64]
_3ImWIJ65ktg-PxiyA_aFIC
css-loader?localIdentName=[path]-[name]-[local]-[hash:base64:5]
.src--App-container-3ImWI
  • path: le path du fichier javascript
  • name: le nom du fichier javascript
  • local: le nom utilisé dans le fichier css :local(.container)

Il n’y a malheureusement pas de méthodes (pour l’instant) pour générer des noms du genre ._a, ._b, … ._az histoire de rester ultra court et unique (étant un simple compteur).

La gestion de cet identifiant provient du module webpack loader-utils.

Plusieurs imports

Si un fichier Javascript dépend de plusieurs fichiers de styles et qu’un, il faut simplement concaténer le nom des classes provenant des 2 imports :

import AppStyle from './App.less';
import GlobalStyle from './Global.less';
...  
className={GlobalStyle.container + ' ' + AppStyle.container}

Plus loin

D’autres fonctionnalités sont disponibles, comme l’héritage de règles ou la définition de règle globale via :global, je vous conseille donc d’aller lire la page du projet : https://github.com/webpack/css-loader

Tout cela est encore récent et en développement (allant même à provoquer des breaking changes, des changements de syntaxe), ce qui la rend instable à utiliser pour l’instant, attention!

React server-side with ES6 syntax

February 26th, 2015 | es6, javascript, nodejs, react |

ES6 aka ES.next aka Harmony is already there

Even if it’s not fully standardized (last draft) and should get out mid-2015, ES6 is already there. We can already find several transpilers (a compiler that translates a language to another one) that translate ES6 to ES5 for our browsers or Node to run normally with the old known syntax.

Soon, it will be even useless to transpile with Node because ES6 is already on its way. For instance, Node has already implemented those features :

--harmony_scoping (enable harmony block scoping)
--harmony_modules (enable harmony modules (implies block scoping))
--harmony_proxies (enable harmony proxies)
--harmony_generators (enable harmony generators)
--harmony_numeric_literals (enable harmony numeric literals (0o77, 0b11))
--harmony_strings (enable harmony string)
--harmony_arrays (enable harmony arrays)
--harmony_arrow_functions (enable harmony arrow functions)
--harmony (enable all harmony features (except proxies))

And when using react-tools with the jsx tool (and reactify), you can have access too to some ES6 features.

For instance, with Browserify and Reactify :

browserify('app.jsx').transform({ es6: true }, reactify)

 
If you are not aware of all the new features, or just want to have a look again, check this page that resume clearly with examples what is available in ES6.

Babel FTW

But the best transpiler, the one that implements most of the features is Babel (formerly es5to6, they changed their name because they planned to go further than ES6 certainly, ES7 already being on its way !).

You can take a look at the compatibility table from kangax (awesome job!) to see what are the supported features for all of them : Traceur from Google, Babel, es6-transpiler, jsx.

On the 25/02/2015, Babel is already 78% compatible with the ES6 syntax. That’s pretty neat. Jsx being far at 16% ({harmony: true}), Node at 25% (--harmony).

Let’s not forget about the client side, Chrome being around 50% and Firefox 65%.

Before talking about React with ES6 in Node, I’m going to quickly present the most important and confortable features I think to not revamp our code later (with React at least). You can skip this part if you already know what features ES6 provide.

object literals

var name = "henry";
var phone = "+333456789"
var person = { name, phone };

Just sugar to avoid retyping the variable name and to be consistent.

templates

var what = "awesome";
console.log(`it's so ${what}`);

You just use backquotes and you have a basic template engine where you can evaluate any javascript inside.
No more unreadable “my name is ” + name + ” and I’m ” + yearOld + ” year” + (yearOld > 1 ? “s” : “”) + ” old”.

arrow functions

arr.map(item => item.value)

this being automatically passed to the function, no more need of ugly var self = this;

For instance:

class Math {
multiplyBy(i) { return 2*i; }
compute() { return [1, 2, 3].map(value => { return this.multiplyBy(value); }); }
}

class

class TopBarComponent extends React.Component {
  constructor() {
    super(props); // can be useful sometimes!
    this.state = { value: props.initialValue };
  }
  ...

Finally, a class keyword with its extends. No more prototype to play with and other module pattern, no more React.createClass, no more getInitialState(), you have a true constructor, let’s make some nice OO. No multiple inheritance through. Notice that the React props are now available in the constructor arguments.

short functions notations in classes

render() { return 
No function keyword
; }

And no comma between the functions or that’s not valid.

destructuring

(function({ name, age }) { // auto-associate the args
  console.log(`hi ${name} ${age}`);
})({ age: 12, name: 'henry', phone: '+333456789' });
// auto-associate the function result into the left member
var { name } = (() => { return { name: "toto", age: 30 } })();
console.log(name);

This is super useful and avoid to create manually bunch of variables.

module

import React from 'react';

basically that replaces var React = require('react');
you could also import several items at the same time using the destructuring :

import { React, cx } from 'react';

But it doesn’t work for now in Babel at least.
Those were the most useful features to know, and to run some React in Node.

Check out the others features, such as the promises, the generators, the spread parameters, the default arguments, let, const, symbol, iterators, and the new data structures (Map Set WeakMap, WeakSet), new functions on String, Math, Number…! So much to talk about. You can check out the Babel website to know what it’s all about.

React ES6 style

Let’s focus on React server-side now, using Node. We are going to use Babel to have the latest available features, and because it’s pretty straightforward to make it work.

– Install Babel globally, to have access to the babel executables npm install -g babel.

– Install react. You must have at least react>=0.13 otherwise Babel is going to fail with this error :

TypeError: Super expression must either be null or a function, not undefined

If the 0.13 is not yet available (it’s not yet at this time), force the installation using : npm install

Babel has an executable babel-node, that starts node with all its es6 features: babel-node app.jsx

Here is a program sample full ES6 style that just renders as a string (we are server side!) a component in another file:

App.jsx

import React from 'react';
import MyComponent from './MyComponent.jsx';

console.log(React.renderToString());

MyComponent.jsx

import React from 'react';

export class MyComponent extends React.Component {
  constructor(props) {
    this.state = { value: props.initialValue };
  }
  render() {
    var items = [ 1, , 3 ].map(x => {x * this.state.value});
    return 
{items}
; } }

You will have this result as expected:

3 9

We are already using the class, module, destructuring and arrow features in this tiny example.

So, this is the base template if you want to start playing with React in Node being full ES6 compliant. It took some time for me to find this result. I tested a lot of things, other frameworks and techniques to get my full ES6 working, and I found this one with Babel simple enough. So, it’s time to refactor our stuff now and combine this with some client side !

 

Check out the React post about this version 0.13 for more details: http://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html

 

What does it look like in ES5 ?

Instead of using babel-node, you can use the executable babel to get the transpiled output. It’s pretty interesting to see how Babel translates ES6 to ES5.

For instance, our previous sample, if you do babel app.jsx, that gives us :

"use strict";

var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
var React = _interopRequire(require("react"));
var MyComponent = _interopRequire(require("./MyComponent.jsx"));

console.log(React.renderToString(React.createElement(MyComponent, { initialValue: "3" })));

The import feature is automatically replaced by an _interopRequire + require function. If we babel MyComponent.jsx, that’s WAY more verbose :

"use strict";

var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); };
var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; };
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
var React = _interopRequire(require("react"));

var MyComponent = (function (_React$Component) {
        function MyComponent(props) {
                _classCallCheck(this, MyComponent);

                this.state = { value: props.initialValue };
        }

        _inherits(MyComponent, _React$Component);

        _prototypeProperties(MyComponent, null, {
                render: {
                        value: function render() {
                                var _this = this;

                                var items = [1,, 3].map(function (x) {
                                        return React.createElement(
                                                "span",
                                                { key: x },
                                                x * _this.state.value
                                        );
                                });
                                return React.createElement(
                                        "div",
                                        null,
                                        items
                                );
                        },
                        writable: true,
                        configurable: true
                }
        });

        return MyComponent;
})(React.Component);

module.exports = MyComponent;

We can see a bit how it’s translated :

– Class, superclass, and inheritance.
– Everything being a true ES5 object property value/writable/configurable using Object.defineProperties
– module.exports = MyComponent

 

You may have noticed the default keyword when we defined our React component:
export default class MyComponent {

If we omit it, the end of the generated file will be :

Object.defineProperty(exports, "__esModule", {
  value: true
});

instead of module.exports = MyComponent;

But we want this CommonJS syntax to work with Node, so we need this default keyword. If you don’t use it, you will get this error :

Warning: React.createElement: type should not be null or undefined. It should be a string (for DOM elements) or a ReactClass (for composite components).
Warning: Only functions or strings can be mounted as React components.

C:\test\node_modules\react\lib\ReactDefaultInjection.js:53
    tagName: type.toUpperCase(),
                 ^
TypeError: Cannot read property 'toUpperCase' of undefined

ES6 is not enough, we want ES7 !

It’s just getting started but Traceur, Babel and Firefox are already full steam ahead !
Check the kangax table : http://kangax.github.io/compat-table/es7/

You can use babel-node with the experimental flag : babel-node --experimental app.jsx to give a try to the already implemented ES7 features of Babel if you want.