Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transpiling ES6 to ES5 with module loading and class inheritance

I'm trying find the best/working solution for transpiling my ECMA Script 6 code to ES5. I'd like to use a module loader and make use of inheritance. The closest I've got so far is by using Babel 6 with the es2015 preset, and transform-es2015-modules-systemjs plugin. Here is my .babelrc file:

{
    "presets": ["es2015"],
    "plugins": ["transform-es2015-modules-systemjs"]
}

And my files are structured like this:

- dist
    (transpiled files in the same structure as the src folder)
- src
    - classes
        - Point.js
        - ColorPoint.js
    app.js
index.html

The contents of app.js looks like this:

import ColorPoint from 'classes/ColorPoint.js';

let cp = new ColorPoint(25, 8, 'green');
console.log(cp.toString()); // '(25, 8) in green'

The definition of Point.js looks like this:

export default class Point {

And the definition of ColorPoint.js looks like this:

import Point from 'classes/Point.js';
export default class ColorPoint extends Point {

And just for completeness, the important part of index.html looks like this:

<script src="node_modules/systemjs/dist/system.js"></script>
<script>
    System.config({
        baseURL: 'dist'
    });

    System.import('app.js');
</script>

I am transpiling the whole src folder to the dist folder using the command:

babel src -d dist

The problem is that Babel adds a single line to the top of the transpiled ColorPoint.js file which breaks System.js at runtime. The error is:

Uncaught Error: Module http://localhost/es6-tutorial/dist/classes/ColorPoint.js interpreted as global module format, but called System.register.

But when I remove this line at the top of this file it works again:

function _typeof(obj) { return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj; }

I guess this might be a bug in the transpiler. I hoping to get some guidance from someone who's successfully implemented inheritance and module loading before. Or maybe point me to a current working example which I can look at.

like image 633
oxide246 Avatar asked Nov 15 '15 10:11

oxide246


People also ask

How do I convert ES6 to ES5?

Go to your package. json file where we'll create a npm build script using the babel command. The babel command takes two arguments: the path to your ES6 code and a path to where you want your ES5 code to go.

Does ES5 support classes?

class keyword In the ES5 version, there are no classes; a function is used to make an object directly.

Do you still need to Transpile ES6?

If you're using ES modules (which are ES6), you still need to transpile. Also, the thing you're calling 'ES6' may contain features that are naturally transpiled by Babel but aren't supported by Node/V8.


1 Answers

Wow, I am having the same problem! I was using traceur to transpile my code just fine and things have been running well for the past year, but traceur is not very active and there are more language features available in babel, so I decided to switch.

The process has been a bit tedious and now I am falling down on this very issue; a class that extends a base class is transpiled with a statement that preceeds the System.register call.

From the SystemJS docs on modules it states the precedence of module format identification:

Module format detection

When the module format is not set, automatic regular-expression-based detection is used. This module format detection is never completely accurate, but caters well for the majority use cases.

The module format detection happens in the following order:

  1. System.register / System.registerDynamic If the source code starts with a number of comments, followed by System.register or System.registerDynamic as the first line of code.

  2. ES modules The source is only detected as an ES module if it contains explicit module syntax - valid import or export statements.

  3. AMD modules The presence of a valid AMD define statement in the code.

  4. CommonJS modules The presence of require(...) or exports / module.exports assignments

  5. Global This is the fallback module format after all the above fail.

So, the auto detection fails with inherited classes as the babel transpiler adds the mentioned line at the head of the file.

What needs to happen is add a config to tell systemjs that those compiled js files are in register format.

I have been playing around with meta && packages in system.config.js trying to find the magic incantation to identify all '**/*.js' files in my build folder as {format: 'register'} but cannot get the glob, or path, or something quite right.

like image 134
Kendrick Burson Avatar answered Sep 23 '22 13:09

Kendrick Burson