Babel fails to compile ES6 object cloning with spread operator - javascript

I use grunt-babel to compile my ES6 code. But it returns Warning: dist/app.js: Unexpected token (321:9) Use --force to continue. when I try to use {...obj} to copy and extend object. Following code is working perfect in console of Chrome v61 but Babel doesn't like it. What is the problem?
let a = { a: 12 };
let b = { ...a, b: 15 };
I am using env preset. (babel-core v.6.26.0 and babel-preset-env v.1.6.1)

The spread property for objects is not part of ES6. Currently, as of Dec 2017, it is part of the stage 3 proposal for ECMAScript. You can have a look at the proposal here.
You need a babel preset that includes features not yet officially in the language. The babel-preset-env does not include those features.
To solve your problem, you could use something like babel-preset-stage-3 and add "stage-3" to the list of presets in your .babelrc.
Side note:
An alternative to the spread syntax for objects in ES6 is to use Object.assign
let b = Object.assign({}, a, { b: 15 });

You probably would want to add these plugins to your .babelrc. This Github issue has a lot of solutions unexpected token (rest spread operator). I am trying these out now.
{
"presets": ["react", "es2015"],
"plugins": ["transform-es2015-destructuring", "transform-object-rest-spread"]
}
npm install --save-dev babel-plugin-transform-es2015-destructuring
npm install --save-dev babel-plugin-transform-object-rest-spread

Related

Unexpected token => in Javascript for chrome v41 and ie11

What is the quick way to fix the error
Unexpected token => .
I wrote below code and it only runs in higher version of chrome but not on lower version and ie11.
var result = aIndice.filter(obj => {
return obj.Type === "E"
})
You are using an arrow function obj => { } which will not work in Internet Explorer 11. You need to either use tools like Babel to compile your ES6 code to ES5, or simply avoid using any modern features.
You can also write your function like this:
var result = aIndice.filter(function(obj) {
return obj.Type === "E"
})
Arrow functions are an es2015 feature, therefore they will not run on older browsers.
Some features can be implemented by using different polyfills like modernizr, but arrow functions are a language expression and thus can't be polyfilled.
You can tell what features are available in what browsers by using caniuse.
The solution to this problem is transpiling the code with a tool like babel.
To transpile your script with babel, you will need to install npm and node.js, and then initiate an npm project:
$ npm init
And install the dependencies we need, the babel-cli and a preset for it to use babel-preset-env.
$ npm install --save-dev babel-cli babel-preset-env
Now you need a settings file for babel, you can define your target browsers there using browserlist, so create a file named ".babelrc" and in it write:
{
"presets": [
["env", {
"targets": {
"ie": "11",
"chrome": 41
}
}]
]
}
Add a new npm script to package.json (created by calling npm init)
"script.js" is the source script, and "script-transpiled.js" is the output script.
"scripts": {
"transpile": "babel script.js --o script-transpiled.js"
}
And call
npm run transpile
Now your script will be transpiled into a new file script-transpiled.js and you can run it the targeted browsers.
To work with a large scale project it is recommended to use babel-loader with webpack.

Spread syntax gives error when copying react component properties

I'm using react and I'm trying to use the spread syntax. For some reason it doesn't work and it gives an error:
const { className, children, ...otherprops } = this.props;
Any idea what I'm doing wrong?
You are getting Unexpected token because you are missing one babel preset, stage-0
With stage-0, it works
Without stage-0, it doesn't work
In order to add it, you have to
1º Install it
npm install --save-dev babel-preset-stage-0
2º Add it to .babelrc
{
"presets": ["react","es2015","stage-0"]
}

ESLint and This-Bind operator

The This-Bind operator is a proposal for convenient this method-binding syntax for ES7:
// this-bind via '::'
$(".some-link").on("click", ::view.reset);
// oldschool .bind(this, ...)
$(".some-link").on("click", view.reset.bind(view))
// or even longer...
$(".some-link").on("click", function () {
return view.reset.apply(view, Array.prototype.slice.call(arguments));
})
// and even ES6 while is more handy, but still leaves some redundancy
$(".some-link").on("click", (...args) => view.reset(...args));
The problem is, well, it still in proposal stage for future (7) version of ES, so it wasn't yet included in standart and thus not supported by ESLint, while can be still used via tanspiling (with Babel, f.e.).
The question is, is there any modules/plugins/options for ESLint to support function-bind operator (or whole set of ES7 experimental features) syntax?
Well, while I surfed net in preparation of this question, I found, that Babel has implementation of it's own custom parser for ESLint, which allows to lint any valid Babel code.
In order to use it you should:
Instal babel-eslint parser first via npm:
$ npm install eslint babel-eslint --save-dev
Configure ESLint to use custom parser, by specifying it in .eslintrc file:
f.e. .eslintrc.json:
{
"parser": "babel-eslint",
...
}
If you using SublimeLinter, togle linter off/on in order to reload config.

Decorators not supported yet in 6.x error

I'm trying to run Jasmine tests while using Babel to transpile.
Every time i try to run the tests, which are written in Aurelia.js syntax, I keep getting hit with the Decorators are not supported error(my Babel version is 6.3.15)
I have the following in my .babelrc file:
.babelrc
{
"presets":["es2015", "stage-0", "stage-1"],
"plugins":["transform-class-properties", "transform-decorators"]
}
and the snippet it fails on is:
#inject(HttpClient)
export class Users {
heading = "test";
users = [];
Surely Babel should transform the decorators given one of the presets contaisn the plugin for it? Even if that failed, wouldn't my transform-decorators plugin catch it instead?Also, Initially this was done with Babel 5.8.23 and i was still seeing this error, so i changed the package number to latest
Decorators are broken in Babel 6!
Here's the issue in the babel issue tracker.
Based on this reply it might be a while before the issue is fixed.
After downgrading to Babel 5, make sure your babel options have stage: 0 or the es7.decorators option. Here's where you need to configure the options:
config.js
build/babel-options.js
karma.conf.js
Make sure your babel options contain the following:
optional: [
"es7.decorators",
...
]
They should be in both config.js (for SystemJS) an karma.conf.js (for karma).

How do I install the babel-polyfill library?

I just started to use Babel to compile my ES6 javascript code into ES5. When I start to use Promises it looks like it's not working. The Babel website states support for promises via polyfills.
Without any luck, I tried to add:
require("babel/polyfill");
or
import * as p from "babel/polyfill";
With that I'll get the following error on my app bootstrapping:
Cannot find module 'babel/polyfill'
I searched for the module but it seems I'm missing some fundamental thing here. I also tried to add the old and good bluebird NPM but it looks like it's not working.
How to use the polyfills from Babel?
This changed a bit in babel v6.
From the docs:
The polyfill will emulate a full ES6 environment. This polyfill is automatically loaded when using babel-node.
Installation:
$ npm install babel-polyfill
Usage in Node / Browserify / Webpack:
To include the polyfill you need to require it at the top of the entry point to your application.
require("babel-polyfill");
Usage in Browser:
Available from the dist/polyfill.js file within a babel-polyfill npm release. This needs to be included before all your compiled Babel code. You can either prepend it to your compiled code or include it in a <script> before it.
NOTE: Do not require this via browserify etc, use babel-polyfill.
The Babel docs describe this pretty concisely:
Babel includes a polyfill that includes a custom regenerator runtime
and core.js.
This will emulate a full ES6 environment. This polyfill is
automatically loaded when using babel-node and babel/register.
Make sure you require it at the entry-point to your application, before anything else is called. If you're using a tool like webpack, that becomes pretty simple (you can tell webpack to include it in the bundle).
If you're using a tool like gulp-babel or babel-loader, you need to also install the babel package itself to use the polyfill.
Also note that for modules that affect the global scope (polyfills and the like), you can use a terse import to avoid having unused variables in your module:
import 'babel/polyfill';
For Babel version 7, if your are using #babel/preset-env, to include polyfill all you have to do is add a flag 'useBuiltIns' with the value of 'usage' in your babel configuration. There is no need to require or import polyfill at the entry point of your App.
With this flag specified, babel#7 will optimize and only include the polyfills you needs.
To use this flag, after installation:
npm install --save-dev #babel/core #babel/cli #babel/preset-env
npm install --save #babel/polyfill
Simply add the flag:
useBuiltIns: "usage"
to your babel configuration file called "babel.config.js" (also new to Babel#7), under the "#babel/env" section:
// file: babel.config.js
module.exports = () => {
const presets = [
[
"#babel/env",
{
targets: { /* your targeted browser */ },
useBuiltIns: "usage" // <-----------------*** add this
}
]
];
return { presets };
};
Reference:
usage#polyfill
babel-polyfill#usage-in-node-browserify-webpack
babel-preset-env#usebuiltins
Update Aug 2019:
With the release of Babel 7.4.0 (March 19, 2019) #babel/polyfill is deprecated. Instead of installing #babe/polyfill, you will install core-js:
npm install --save core-js#3
A new entry corejs is added to your babel.config.js
// file: babel.config.js
module.exports = () => {
const presets = [
[
"#babel/env",
{
targets: { /* your targeted browser */ },
useBuiltIns: "usage",
corejs: 3 // <----- specify version of corejs used
}
]
];
return { presets };
};
see example: https://github.com/ApolloTang/stackoverflow-eg--babel-v7.4.0-polyfill-w-core-v3
Reference:
7.4.0 Released: core-js 3, static private methods and partial
application
core-js#3, babel and a look into the future
If your package.json looks something like the following:
...
"devDependencies": {
"babel": "^6.5.2",
"babel-eslint": "^6.0.4",
"babel-polyfill": "^6.8.0",
"babel-preset-es2015": "^6.6.0",
"babelify": "^7.3.0",
...
And you get the Cannot find module 'babel/polyfill' error message, then you probably just need to change your import statement FROM:
import "babel/polyfill";
TO:
import "babel-polyfill";
And make sure it comes before any other import statement (not necessarily at the entry point of your application).
Reference: https://babeljs.io/docs/usage/polyfill/
First off, the obvious answer that no one has provided, you need to install Babel into your application:
npm install babel --save
(or babel-core if you instead want to require('babel-core/polyfill')).
Aside from that, I have a grunt task to transpile my es6 and jsx as a build step (i.e. I don't want to use babel/register, which is why I am trying to use babel/polyfill directly in the first place), so I'd like to put more emphasis on this part of #ssube's answer:
Make sure you require it at the entry-point to your application,
before anything else is called
I ran into some weird issue where I was trying to require babel/polyfill from some shared environment startup file and I got the error the user referenced - I think it might have had something to do with how babel orders imports versus requires but I'm unable to reproduce now. Anyway, moving import 'babel/polyfill' as the first line in both my client and server startup scripts fixed the problem.
Note that if you instead want to use require('babel/polyfill') I would make sure all your other module loader statements are also requires and not use imports - avoid mixing the two. In other words, if you have any import statements in your startup script, make import babel/polyfill the first line in your script rather than require('babel/polyfill').
babel-polyfill allows you to use the full set of ES6 features beyond
syntax changes. This includes features such as new built-in objects
like Promises and WeakMap, as well as new static methods like
Array.from or Object.assign.
Without babel-polyfill, babel only allows you to use features like
arrow functions, destructuring, default arguments, and other
syntax-specific features introduced in ES6.
https://www.quora.com/What-does-babel-polyfill-do
https://hackernoon.com/polyfills-everything-you-ever-wanted-to-know-or-maybe-a-bit-less-7c8de164e423
Like Babel says in the docs, for Babel > 7.4.0 the module #babel/polyfill is deprecated, so it's recommended to use directly core-js and regenerator-runtime libraries that before were included in #babel/polyfill.
So this worked for me:
npm install --save core-js#3.6.5
npm install regenerator-runtime
then add to the very top of your initial js file:
import 'core-js/stable';
import 'regenerator-runtime/runtime';

Categories

Resources