Webpack's UglifyJsPlugin not able to compile ES6 packages - javascript

I have this in my Webpack setup:
// webpack.prod.conf.js
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
drop_console: shouldDropConsole
},
sourceMap: true
}),
// .babelrc
"presets": [
["stage-2"],
["es2015", {"modules": false}]
],
When I do npm run build I get the following error:
ERROR in static/js/vendor.8b608f0ab832a371f4a5.js from UglifyJs
Unexpected token: name (finish)
[./node_modules/pica/lib/mathlib.js:35,0][static/js/vendor.8b608f0ab832a371f4a5.js:38950,6]
So UglifyJS doesn't recognize the ES6 code there: let.
How to solve this? Is there any workaround? (I'm using Webpack 3.6.0).

I found the solution (how to transpile ES6 to ES5 for node modules in a Webpack setup):
{
test: /\.js$/,
loader: 'babel-loader',
include: [
resolve('src'),
resolve('test'),
resolve('node_modules/pica'),
resolve('node_modules/countries-list')
],

Related

How can I use Node.js CommonJS modules in ES6 import/export modules using babel or webpack?

I'm sorry if this is a duplicate (I looked hard using the search tool but nothing came close). Anyone has any ideas how to transpile Node.js CommonJS modules so they can be used within an ES6 import/export project?
I know there's #babel/plugin-transform-modules-commonjs which transpiles ES6 modules into CommonJS form, but I think I'm in need of the opposite. The reason I need this is I have a config file written using Node's module.exports syntax that needs to be imported within a React project built with babel using ES6 modules, but I get a Uncaught TypeError: Cannot assign to read only property 'exports' of object error. Any ideas would be greatly appreciated.
Here's my babelrc.js file:
module.exports = {
presets: ['#babel/preset-env', '#babel/preset-react'],
plugins: [
['#babel/plugin-proposal-class-properties', { loose: true }],
['#babel/plugin-transform-runtime', { regenerator: true }],
'#babel/plugin-syntax-dynamic-import',
'#babel/plugin-proposal-optional-chaining'
],
env: {
production: {
plugins: [
[
"transform-react-remove-prop-types",
{ removeImport: true }
],
]
}
}
}
And my webpack config babel loader rule:
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true,
cacheCompression: false,
envName: isModeProduction ? 'production' : 'development'
}
}
]
},
Thanks to #Thomas Sablik's comment, I found out this was a known webpack issue.
And after poking round and looking up this error, I found this answer on another Stack Overflow which helped me fix it by adding "sourceType": "unambiguous" to my babel configuration.
https://stackoverflow.com/a/56283408/2942765
Thank you Thomas.

Why is my webpack babel setup emitting ESM requires when I have configured my preset to commonjs?

Today I observed babel/babel-loader exhibiting some undesirable behavior. I am bundling some assets for usage on nodejs. Post-compile, a bundle is generated with references to #babel/runtime/**/esm/**. Of course, node cannot import such files, and on node bundle.js I get:
Must use import to load ES Module: /my/project/node_modules/#babel/runtime/helpers/esm/defineProperty.js
require() of ES modules is not supported.
Right. Makes sense. But babel-loader injected those imports. In fact, the parent folder in #babel/runtime has all of the non-ESM things, which I actually probably do want imported! My babel config looks as such:
{
presets: [
[
"#babel/preset-env",
{
modules: 'commonjs',
targets: {
node: "current",
esmodules: false,
},
},
],
"#babel/preset-typescript",
]
}
As you can see, I'm attempting to tell babel via targets.esmodules: false and modules: 'commonjs' to use commonjs. I hoped these entries would tell babel to not expect ESM compatibility! None the less, generated bundles still look like:
...
var _toConsumableArray2 = _interopRequireDefault(__webpack_require__(/*! #babel/runtime/helpers/esm/toConsumableArray */ "#babel/runtime/helpers/esm/toConsumableArray"));
My full webpack config is pretty terse as well:
{
entry: serverFilename,
mode: 'development',
output: {
path: path.dirname(serverBuildFilename),
filename: path.basename(serverBuildFilename)
},
target: "node",
externals: [webpackNodeExternals()],
optimization: {
moduleIds: 'named',
minimize: false
},
resolve: {
extensions: ['.ts', '.tsx', '.wasm', '.mjs', '.js', '.json'],
},
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: babelConfig.presets // see babel config above
}
}
},
],
},
}
I can't tell if I'm missing configuration, if babel isn't respecting my configuration, or <your ideas here>!
All tips appreciated. Thanks!
It took me a while to figure out the solution and this post helps
https://github.com/webpack/webpack/issues/11696
Copied my solution from the issue here:
I ended up using webpack-node-externals in webpack config to sort of bypass this issue
const nodeExternals = require('webpack-node-externals');
// add these to the webpack config.
externals: [
nodeExternals({
whitelist: [/^#babel\/runtime/],
}),
],
This solution creates duplicated babel/runtime file injections and can also be mitigated by https://webpack.js.org/loaders/babel-loader/#babel-is-injecting-helpers-into-each-file-and-bloating-my-code

How to resolve 'class constructor cannot be invoked without new' error when building with svelte, babel, and webpack

I'm trying to get svelte, webpack, and babel to work together. I am producing the minified bundle, however, this bundle is throwing errors upon loading it up in the browser. This needs to be compatible with IE11 while using ES6 syntax.
I get
Class constructor I cannot be invoked without 'new'
The pertinent parts of my webpack looks as follows
{
test: /\.(js|jsx|mjs|svelte)?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
configFile: path.resolve(__dirname, 'babel.config.js')
}
}
]
},
{
test: /\.svelte$/,
exclude: /node_modules/,
use: {
loader: "svelte-loader",
options: {
emitCss: false,
hotReload: false
},
},
},
babel.config is as follows
module.exports = {
plugins: [
'#babel/plugin-proposal-class-properties',
'angularjs-annotate',
'lodash'
],
presets: [
['#babel/preset-env', {
useBuiltIns: 'usage',
corejs: { version: 3, proposals: true }
}],
'#babel/preset-react'
]
};
The svelte file itself is pretty basic
<script>
export let name = "World";
</script>
<h1>Hello {name}!</h1>
UPDATE
I can get it to run by excluding transform-classes in babel config
exclude: ['transform-classes'],
However, this of course breaks IE11.
You will need to update the webpack-cli and html-webpack-plugin versions in your package.json:
"webpack-cli": "^4.5.0",
"html-webpack-plugin": "^5.1.0",
Then, delete your node_modules and package-lock.json files and run a new npm install
Simply do this:
$ yarn remove webpack-cli && yarn add --dev webpack-cli
This will remove the old cli version, re-install the new one and compile everything afresh. Problem solved

Webpack babel-loader es2015 presets setting is not working

When I build react project with webpack, I got an 'Unexpected token' error
webpack --progress
ERROR in ./src/App.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: Unexpected token (13:13)
11 | }
12 |
> 13 | onSearch = (e) => {
| ^
14 | console.log('click');
15 | }
I thought my project doesn't transpile es6 codes to es5 because wrong setting of webpack.config.js, but I can't find what's wrong.
webpack.config.js
module.exports = {
entry: __dirname + "/src/App.js",
output: {
path: __dirname + "/public",
filename: "bundle.js"
},
module: {
rules: [{
test: /\.js?$/,
loader: 'babel-loader',
query: {
cacheDirectory: true,
presets: ['react', 'es2015']
}
}]
}
}
Install babel-preset-stage-2 package and try this:
.babelrc
{
"presets": ["es2015", "react", "stage-2"]
}
webpack.config.js
...
presets: ["es2015", "react", "stage-2"]
...
In the future, we might not use the babel's state presets as this Removing Babel's Stage Presets article said.
However, for now, it worked really well
What's Babel's Stage Presets:
A Babel preset is a shareable list of plugins.
The official Babel Stage presets tracked the TC39 Staging process for
new syntax proposals in JavaScript.
Each preset (ex. stage-3, stage-2, etc.) included all the plugins for
that particular stage and the ones above it. For example, stage-2
included stage-3, and so on.

Webpack babel 6 ES6 decorators

I've got a project written in ES6 with webpack as my bundler. Most of the transpiling works fine, but when I try to include decorators anywhere, I get this error:
Decorators are not supported yet in 6.x pending proposal update.
I've looked over the babel issue tracker, and haven't been able to find anything on it there, so I'm assuming I'm using it wrong. My webpack config (the relevant bits):
loaders: [
{
loader: 'babel',
exclude: /node_modules/,
include: path.join(__dirname, 'src'),
test: /\.jsx?$/,
query: {
plugins: ['transform-runtime'],
presets: ['es2015', 'stage-0', 'react']
}
}
]
I have no trouble with anything else, arrow functions, destructuring all work fine, this is the only thing that doesn't work.
I know I could always downgrade to babel 5.8 where I had it working a while ago, but if there's any way to get this working in the current version (v6.2.0), it would help.
This Babel plugin worked for me:
https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy
npm i --save-dev babel-plugin-transform-decorators-legacy
.babelrc
{
"presets": ["es2015", "stage-0", "react"],
"plugins": [
["transform-decorators-legacy"],
// ...
]
}
or
Webpack
{
test: /\.jsx?$/,
loader: 'babel',
query: {
cacheDirectory: true,
plugins: ['transform-decorators-legacy' ],
presets: ['es2015', 'stage-0', 'react']
}
}
React Native
With react-native you must use the babel-preset-react-native-stage-0 plugin instead.
npm i --save babel-preset-react-native-stage-0
.babelrc
{
"presets": ["react-native-stage-0/decorator-support"]
}
Please see this question and answer for a complete explanation.
After spending 5 minutes on the babeljs slack webchat, I found out that decorators are broken in the current version of babel (v6.2). The only solution seems to be to downgrade to 5.8 at this time.
It would also seem they moved their issue tracker from github to https://phabricator.babeljs.io
I write all this down, since after hours of searching I have found the current documentation very poor and lacking.
Installing only babel-plugin-transform-decorators-legacy didn't work for me (I have a configuration using enzyme along with karma). Turns out installing transform-class-properties: transform-class-properties and also making sure that the legacy plugin is before the transform class plugin as per the docs in transform-decorators-legacy finally made it work for me.
I'm also not using a .babelrc file, but adding this to my karma.conf.js file worked for me:
babelPreprocessor: {
options: {
presets: ['airbnb', 'es2015', 'stage-0', 'react'],
plugins: ["transform-decorators-legacy", "transform-class-properties"]
}
}
I also added it to my loaders:
loaders: [
{
test: /\.js$/,
loader: 'babel',
exclude: path.resolve(__dirname, 'node_modules'),
query: {
presets: ['airbnb', 'es2015', 'stage-0', 'react'],
plugins: ["transform-decorators-legacy", "transform-class-properties"]
}
},
You just need a transform decorators plugin: http://babeljs.io/docs/plugins/transform-decorators/
If you upgraded your project from Babel 6 to Babel 7, then you want to install #babel/plugin-proposal-decorators.
If you want to support legacy decorators as used in Babel 5, you need to configure your .babelrc as follows:
plugins: [
['#babel/plugin-proposal-decorators', { legacy: true }],
['#babel/plugin-proposal-class-properties', { loose: true }],
]
Ensure #babel/plugin-proposal-decorators comes before #babel/plugin-proposal-class-properties in the case that you are making use of the latter.

Categories

Resources