Webpack outputting ES6 code despite ES2015 preset - javascript

I'm writing client-side react code with ES6 synthax and have been using webpack to transform into ES5 using Babel, and generate a bundle that I send to browser.
It works great on Chrome. However, I recently tried my bundle on Safari 9.x and it failed with :
SyntaxError: Unexpected keyword 'const'. Const declarations are not supported in strict mode.
Upon closer inspection I noticed this code in the bundle.js was causing the error:
// customized for this use-case
const isObject = x =>
typeof x === 'object' &&
x !== null &&
!(x instanceof RegExp) &&
!(x instanceof Error) &&
!(x instanceof Date);
I thought webpack was supposed to eliminate ES6 code (since I'm using the es2015 preset) so I'm surprised that a const and an arrow function were still in the bundle. Why is there ES6 code still in my bundle? Is there any way for me to get webpack to transform that into ES5?
Here's a snippet of my webpack.config.js that I thought would have done the job of removing this synthax but didn't:
module: {
loaders: [{
test: /\.jsx?/,
include: APP_DIR,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react', 'stage-2'] //, 'react-hmre']
}
}

After much head scratching and investigation it turned out that one node module, snakecase-keys, is built using ES6 synthax. Since my webpack is only targeting my static directory and not my node modules it did not get Babel'd
This fixed it:
module: {
loaders: [{
test: /\.jsx?/,
// exclude: /(node_modules|bower_components)/,
include: [APP_DIR, /node_modules\/snakecase-keys/],
loader: 'babel-loader',
query: {
presets: ['es2015', 'react', 'stage-2'] //, 'react-hmre']
}
}]
}

Related

Arrow functions not compiling

I've been using Reactjs.net with Visual Studio and it compiles .jsx files that contain class methods defined using arrow functions syntax...
class A {
m = () => {
}
}
I've set up Webpack with ES2017 preset but it's giving an "unexpected token" error for the equals sign after the method name.
Why doesn't this compile?
Here is the loader section from my config...
module: {
loaders: [
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2017', 'react']
}
}
]
}
I installed https://babeljs.io/docs/plugins/preset-stage-2/
And added 'stage-2' to the list of presets.
I worked out this solution after turning on and off the presets here with some sample code...
https://babeljs.io/repl

Webpack bundled JS not being executed

This is a very strange problem because actually, some of the bundled code is being executed. I use style loader for my CSS and that of course gets put into bundle.js and loads and works fine. However, I also have a file with some code to set up the jQuery localScroll plugin, and that code isn't working.
To test it, I included in the same file a call to console.log(), just telling it to write the number 4. If I open up bundle.js, I can see the console.log() call as well as the call to $.localScroll(), they just simply aren't running. Calling $.localScroll() manually from the console works as intended.
Here is the JS file in question:
console.log(4);
$(() => {
$.localScroll({duration: 800});
});
Here is my Webpack config:
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: './webpack-entry.js',
plugins: [
new CleanWebpackPlugin(['dist']),
new webpack.optimize.UglifyJsPlugin()
],
output: {
filename: './javascripts/bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(png|svg|jpg|jpeg)$/,
use: {
loader: 'url-loader',
options: {
limit: 8192,
fallback: 'file-loader',
name: './images/[hash].[ext]'
}
}
},
{
test: /\.pug$/,
use: [
{
loader: 'file-loader',
options: {
name(file) {
if(new RegExp(/partials/).test(file)) {
return './views/partials/[name].[ext]'
}
return './views/[name].[ext]'
}
}
},
'pug-asset-loader?root=./src'
],
},
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['env'],
}
},
]
}
],
}
};
Finally, here is bundle.js (my custom code seems to be at the very bottom, in some sort of array of functions). The non-uglified version is too long for SO, so here it is on Hastebin: https://hastebin.com/vululimupi.js
The problem is that you haven't defined this dependency as a module. Rewriting it following supported module format specs should help.
After some testing, it seems that the essential problem is just as #uKolka was saying - my files were not getting required as modules. While I'm still not entirely certain why their code was still appearing in my bundle file but not running, I have found a way to still reap the recursive benefits of require.context(). It seems that require.context() returns a function which is itself capable of resolving the files it logs in whatever folder you have pointed it at. It also has a member function keys() which quite conveniently returns each dependent file name and is easily used with forEach().
Given all that, this is how my webpack-entry.js looks now:
import './src/stylesheets/scss/master.scss';
require.context('./src/views', true, /\.pug$/);
const js = require.context('./src/javascripts/', false, /\.js$/);
js.keys().forEach(key => js(key));
This works just fine.
In my case it was due to Babel and React. If you use React, then try to call ./src/index.js directly and use "#babel/preset-env", "#babel/preset-react" in your .babelrc. You can take a look at my gist. and in your webpack.config.js:
{
test: /\.js?$/,
use: ["babel-loader"],
exclude: /node_modules/
},
take a look at the gist:
https://gist.github.com/Nagibaba/14e898d99a4be89b00a60d28abc19bc0
For ruby's rails/webpacker users only.
This question title and content made me find it before this issue which may be the correct answers for some users here. To avoid link rot, I'll explain it shortly below:
Make sure your #rails/webpacker npm library and webpacker gem both have the same exact version.
I ended up doing:
IO.foreach("package.json").find { |line| line[%r("#rails/webpacker": "(.*?)")]}
gem "webpacker", Regexp.last_match(1).tr("-", ".")

Babel used with Grunt working differently than when used with Webpack

I have a project using Babel for Webpack, transpiling ES6 code into plain Js. This works perfectly well, including the imported classes etc, see below.
Result:
var _Person = __webpack_require__(2);
var vic = new _Person.person("Fred McIntire", "Web Developer");
vic.EchoProperties();
Webpack.config.js
module: {
loaders: [{
test: /\.js$/,
exclude: "/node_modules/",
loader: ['babel'],
query: {
presets: ['es2015']
}
}]
},
However while using Babel with Grunt in another project, hence "grunt-babel" plugin, I noticed it transpiles the imports into CommonJs by default and does not include the imported classes.
Result
var _Person=require("./modules/Person"),
vic=new _Person.person("Fred McIntire","Web Developer");
vic.EchoProperties();
gruntfile.js
babel: {
options: {
sourceMap: true,
presets: ['es2015'],
plugins: ['transform-es2015-modules-amd']
},
dist: {
files: {
'assets/js/transpiled/app.es6.js': 'assets/js/custom/app.js'
}
}
},
(I included "plugins: ['transform-es2015-modules-amd']" just for testing purposes).
I want the grunt-babel to transpile down to: (and include the imports)
var _Person = __webpack_require__(2);
not
var _Person=require("./modules/Person")
Therefore how do i update the gruntfile.js settings for grunt-babel in order to act in the same manner as it does used with Webpack?
Thanks in advance...

How to confirm if ES6 is being used (ReactJS + Redux)

I have the following set up:
And I am trying to do the following:
case 'UPDATE_PASSWORD':
return {
...state, //preserve current state, apply changes to it below
password: action.password,
};
but I am getting:
Unexpected token (5:8) at where '...' starts
What may be the issue? How do I check if I am using ES6?
This is a proposed ECMAScript feature (object spread) and can be enabled by adding stage-0 to your babel presets:
npm install --save-dev babel-preset-stage-0
Then, in your .babelrc or within your webpack.config.js query add the preset to your babel settings. Example .babelrc:
{
"presets": [
"es2015",
"react",
"stage-0"
]
}
Or, if you make use of the webpack babel-loader query string:
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react', 'stage-0']
}
}
EDIT
Babel presets are an assortment of many transformations. As per zerkms' suggestion, you could use stage-2, which does not include/transpile many other features you may not be using at this time. If you really just want the object spread to work, you can also just install transform object rest spread.

Using Webpack and Babel to convert ES6 to AMD

I'm using webpack in my app, and have babel converting my js/jsx files from es6 to es5.
I'd like to have babel convert the module loading in these files to AMD. I see how to do this with grunt-babel:
Using Babel to convert ES6 modules to ES5 AMD modules, not working as expected
How would I do this if I want webpack to handle the babel conversion?
For example, in webpack.config.js I have:
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel'
}
}
Can I set an option in there for Babel to use AMD?
You can set an options for babel with query key:
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
modules: 'amd'
}
}
}
For all available options take a look here: http://babeljs.io/docs/usage/options/
If you want to generate the whole bundle as AMD module, you can set it in the "output.libraryTarget" config:
{
output: {
libraryTarget: "amd"
}
}
See here, in "output.libraryTarget":
https://webpack.github.io/docs/configuration.html

Categories