I have a piece of code:
'use strict';
class ArticleModel {
constructor(options = {}) {
this.options = options
}
}
module.exports = ArticleModel
which results in the error Unexpected token = - I don't believe Babel is parsing this. Which babel 6 plugin is needed to parse default parameters in a function?
Edit 1 - this is my .babelrc file
{
"presets": [
"es2015",
"stage-0"
]
}
Edit 2 - I am not running babel from the same directory as .babelrc. I'm running babel from inside test/ where the structure looks like this:
/app
/test
/test/runner.js < -- this is what calls babel-core/register
.babelrc
Do I need to explicitly tell babel-core/register where .babelrc is? I assumed it rolled up a directory for it.
Edit 3 - changed babel/register to babel-core/register. Still get the same issue.
npm install babel-preset-es2015 --save-dev
Add the following line to your .babelrc file:
{
"presets": ["es2015"]
}
Did you try this?
How are you importing the module into the test? I had a similar problem when my tests started to break after upgrading from Babel 5 to 6. In my case it turned out that the problem was because the import has to referenced the default property in the imported lib.
The initiator of this Babel issue gives a good example: https://github.com/babel/babel/issues/2679
Related
For some reason, my jest configuration doesn't work with the latest version of d3-path#3.0.1. It worked fine with version 2.0.0. I guess it has something to do with d3-path switching to ESM, but I was already using ES6 in my own code, so I don't get why it suddenly doesn't work anymore. I have the following packages installed:
"dependencies": {
"d3-path": "^3.0.1"
},
"devDependencies": {
"#babel/core": "^7.15.8",
"#babel/preset-env": "^7.15.8",
"babel-jest": "^27.3.1",
"jest": "^27.3.1"
}
My babel.config.js:
module.exports = {
presets: [['#babel/preset-env', {targets: {node: 'current'}}]],
};
My index.js:
import { path } from 'd3-path'
export default () => path()
The test file:
import fn from '../src/index.js'
describe('test', () => {
it('works', () => {
fn()
expect(2 + 2).toBe(4)
})
})
The error message:
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){export {default as path} from "./path.js";
^^^^^^
SyntaxError: Unexpected token 'export'
> 1 | import { path } from 'd3-path'
To reproduce:
git clone https://github.com/luucvanderzee/jest-problem.git
cd jest-problem
npm i
npm run test
// The test runs without failure- this is because we're currently still using d3-path#2.0.0
npm uninstall d3-path && npm install d3-path // (upgrade to d3-path#3.0.1)
npm run test
// Now the test fails.
How should I configure jest and/or babel to solve this issue?
EDIT:
I already tried the following (from this page of the jest docs):
Creating a jest.config.js file with the following:
module.exports = {
transform: {}
}
Changing my "test" command from "jest" to "node --experimental-vm-modules node_modules/jest/bin/jest.js"
This gives me another error:
/home/luuc/Projects/javascript/jest-problem/test/test.test.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import fn from '../src/index.js'
^^^^^^
SyntaxError: Cannot use import statement outside a module
I also don't get what is meant by
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
Isn't the problem that the module is not transformed? Would adding an ignore pattern not just lead to the module not getting transformed?
Problem
The error happens because jest does not send the content of node_modules to be transformed by babel by default.
The following output line of npm run test indicates one way to solve the problem:
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
Solution
The configuration of jest should be updated in order to instruct it to transform the ESM code present in d3-path dependency.
To do so, add the following to a jest.config.js file in the root directory of the project:
module.exports = {
transformIgnorePatterns: ['node_modules/(?!(d3-path)/)']
}
npm run test runs fine after that.
The transformIgnorePatterns option is documented here.
Edit - including more modules
In order to include all modules starting with d3, the following syntax may be used:
transformIgnorePatterns: ['/node_modules/(?!(d3.*)/)']
TLDR;
transformIgnorePatterns: [
"/node_modules/(?!d3|d3-array|d3-axis|d3-brush|d3-chord|d3-color|d3-contour|d3-delaunay|d3-dispatch|d3-drag|d3-dsv|d3-ease|d3-fetch|d3-force|d3-format|d3-geo|d3-hierarchy|d3-interpolate|d3-path|d3-polygon|d3-quadtree|d3-random|d3-scale|d3-scale-chromatic|d3-selection|d3-shape|d3-time|d3-time-format|d3-timer|d3-transition|d3-zoom}|internmap|d3-delaunay|delaunator|robust-predicates)"
]
For the ones reaching this page after updating recharts dependency, here I found the solution, provided by them.
I want to avoid this:
const SomeMethod = require('../shared/SomeMethod')
And instead use something more modern like this:
import { SomeMethod } from '/shared'
(under the hood): the /shared directory includes an index file of course, returning the object with the SomeMethod property which is also includes to a file.
As I am using JEST, I need two things to get around: 1 is that the node installed supports ES6 imports and 2 is that JEST will be familiar with relative path - notice that I have used the **/**shared so it means - go to the src directory and start from there.
But how to achieve this?
You can achieve this using babel. According to the documentation of jest, you need to do the following
yarn add --dev babel-jest #babel/core #babel/preset-env
and then create babel.config.js at the root of your project with the following content
module.exports = {
presets: [
[
'#babel/preset-env',
{
targets: {
node: 'current',
},
},
],
],
};
You can look into the documentation for more
Here is a step by step process of the same which is addressing the same problem
In order to use absolute path for Jest add the following line in jest.config.js
module.exports = {
moduleDirectories: ['node_modules', 'src'],
...
};
here, src is considered as the root. You may need to change this one according to your folder name.
For more information you can follow this article
After migrating to Babel 7 when I launch my tests I get this error
TypeError: Cannot read property 'default' of undefined
for this line (e.g. index.js file):
export { default } from './SearchInput';
Where SearchInput.jsx file is in the same folder and is using
export class SearchInput {}
syntax.
This happens only in Jest tests (in app runtime it works).
How can I fix it?
EDIT:
This is my babel config babel.config.js:
module.exports = function(api) {
api.cache.forever();
return {
presets: ['#babel/preset-env', '#babel/preset-react'],
plugins: ['#babel/plugin-proposal-class-properties'],
};
};
It seems that jest does not respect plugins, cos when I removed static defaultProps and static propTypes and moved them to SearchInput.defaultProps and SearchInput.propTypes, tests started to work.
You probably forgot to upgrade babel-jest as well.
Note: If you are using babel version 7 you have to install babel-jest with
yarn add --dev babel-jest 'babel-core#^7.0.0-bridge' #babel/core
https://github.com/facebook/jest/tree/master/packages/babel-jest
I am trying to use gulp in order to minify a folder containing JS files. However, one of the files has the above error, preventing it from being minified.
I managed to catch and print the error, which I've partially printed here:
JS_Parse_Error {
message: 'SyntaxError: Unexpected token: punc ())',
filename: 'ex.js',
line: 189,
col: 25,
pos: 6482,
stack: Error\n at new JS_Parse_Error (eval at <anonymous> ... )
plugin: 'gulp-uglify',
fileName: '.../js/ex.js',
showStack: false
}
The file in question contains the following, shortened:
function() {
...
$.confirm({
buttons: {
confirm: function() {
$.post('/ajax-handler', {
...
})
.done( function(response) {
var data = filterResponse(response);
if (data['status'] == 'success') {
sleep(1000).then(() => {
* ...
});
sleep(5000).then(() => {
...
});
} else {
console.log('Oops!');
}
})
.fail( function(err, status, response) {
...
});
},
cancel: function() {}
}
});
...
}
I added the "*" above in order to indicate the exact position listed by JS_Parse_Error.
// Update
From the comments ~ #imolit
v2.0.0 (2018-09-14) - BREAKING CHANGES (link)
Switch back to uglify-js (uglify-es is abandoned, if you need uglify ES6 code please use terser-webpack-plugin).
Original answer before the update...
I hope you can get inspired by this solution which works with webpack. (link below)
Simply teach UglifyJS ES6
There are two versions of UglifyJS - ES5 and ES6 (Harmony), see on git
ES5 version comes by default with all the plugins, but if you install a Harmony version explicitly, those plugins will use it instead.
package.json
"uglify-js": "git+https://github.com/mishoo/UglifyJS2.git#harmony"
or
npm install --save uglify-js#github:mishoo/UglifyJS2#harmony
yarn add git://github.com/mishoo/UglifyJS2#harmony --dev
Webpack
To use it with webpack install also the webpack plugin
npm install uglifyjs-webpack-plugin --save-dev
yarn add uglifyjs-webpack-plugin --dev
then import the manually installed plugin
var UglifyJSPlugin = require('uglifyjs-webpack-plugin');
and replace it in code
- new webpack.optimize.UglifyJsPlugin({ ... })
+ new UglifyJSPlugin({ ... })
For more webpack info (Installation/Usage) see https://github.com/webpack-contrib/uglifyjs-webpack-plugin#install
npm install uglifyjs-webpack-plugin --save-dev is not enough
The main problem is "uglifyjs-webpack-plugin": "^0.4.6" in webpack's package.json
According to semver, ^0.4.6 := >=0.4.6 <0.5.0. Because of the leading zero, webpack will never use the 1.0.0-beta.2.
So after running npm i -D uglifyjs-webpack-plugin#beta, you need to do one more step which is rm -rf node_modules/webpack/node_modules/uglifyjs-webpack-plugin. Then webpack will pick up the version from node_modules/uglifyjs-webpack-plugin instead of node_modules/webpack/node_modules/uglifyjs-webpack-plugin
Update on 2018-04-18: webpack v4 does not have this issue
Add the babel-preset-es2015 dependency to fix this.
And also add 'es2015' in .babelrc file.
json
{
"presets": ["es2015"]
}
I am having the same issue, i found a great answers here that helped me to reach the the file that was causing the error.
Go to Rails Console and Paste:
JS_PATH = "app/assets/javascripts/**/*.js";
Dir[JS_PATH].each do |file_name|
puts "\n#{file_name}"
puts Uglifier.compile(File.read(file_name))
end
Hope it helps someone!
If you got this error using Grunt (grunt-contrib-uglify) the solution is to install ES6 version of the plugin:
npm install grunt-contrib-uglify-es --save-dev
For me it had nothing to do with Uglify not working correctly, but rather a dependency (in this case empty-promise) that has not been compiled to ES5 yet. As we just imported the raw source file, but babel is only transpiling files outside of node_modules, uglify got confused by the ES6 syntax.
Simply check if any dependency you've recently added might not have a "dist" build.
Add stage-3 to presets in .babelrc file.
{
"presets": [
"stage-3"
]
}
I'm getting below error running this command
gulp.task('minify', function () {
return gulp
.src('public/app/js/myapp.bundle.js')
.pipe(uglify())
.pipe(gulp.dest('public/app/js/myapp.bundle.min.js'));
});
GulpUglifyError: unable to minify JavaScript Caused by: SyntaxError: Unexpected token: name (MenuItem) (line: 1628, col: 18, pos: 53569)
Code on that location is this
setters: [],
execute: function () {
class MenuItem { // <-- line 1628
What's wrong?
UglifyJS does not currently support EcmaScript 6 structures like classes.
You'll probably need to run your JavaScript through a transpiler step first, or find a minifier that knows what to do with ES6 code.
Update 2017-06-17
The branch of UglifyJS that is designed to work with ES6 is now published as uglify-es on npm.
Update 2018-09-10
terser is the new uglify-es, uglify-es is no longer maintained.
If using gulp both npmjs gulp-uglify-es and npmjs gulp-terser packages support terser.
npm install gulp-terser --save-dev
const gulp = require('gulp');
const terser = require('gulp-terser');
function es(){
return gulp.src('./src/index.js')
.pipe(terser())
.pipe(gulp.dest('./build'))
}
gulp.task('default', es);
If you run into this problem and you have in fact a transpiler step like Babel, make sure that you include the proper Babel preset in you .babelrc file. Otherwise Babel will simply leave your code as is.
E.g.
{
"presets": ["es2015"]
}