Webpack's UglifyJsPlugin throws error with Node modules containing let - javascript

This is the relevant code (I'm using Vue.js' Webpack official template):
.babelrc:
"presets": [
"babel-preset-es2015",
"babel-preset-stage-2",
]
webpack.prod.config.js
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
drop_console: shouldDropConsole
},
sourceMap: true
}),
This is the error I get when I do npm run build:
ERROR in static/js/vendor.a6271913414e87e123c2.js from UglifyJs
Unexpected token: name (_months)
[./node_modules/calendar-js/index.js:56,0][static/js/vendor.a6271913414e87e123c2.js:90602,6]
This is the offending line:
let _months = MONTHS;
(If I replace all the let's to vars the project is built without problems. And the const's don't seem to bother Webpack/UglifyJS.)
Do I need to configure something so that Webpack/UglifyJS build node modules containing let's? (The let's in my actual project don't give me problems.)

This could be because you might be using an older version of node which does not support es6 syntax.
let, const, arrow functions etc. are part of es6 syntax. To know more follow this link http://es6-features.org/
You might need the older version of node for your other projects so install nvm. NVM is a node version manager which will help you to switch between node versions easily. Follow the link for documentation and installation process https://github.com/creationix/nvm
Node v6+ supports ES6 syntax try upgrading to that.
UPDATE
On the comments of this answer, it's confirmed that it was not a version issue and got resolved by following this GitHub issue thread https://github.com/joeeames/WebpackFundamentalsCourse/issues/3.
Peace!

Related

Additional loader for pdfjs-dist in react app?

I have the pdfjs-dist dependency in my react app and it isn't working - I'm not sure what I changed to cause this. I'm running node v14.16.1, npm v7.9.0, react 17.0.2, react-scripts 4.0.3, and pdfjs-dist 2.7.570. I'm getting the following error message when I run npm start:
Failed to compile.
./node_modules/pdfjs-dist/build/pdf.js 2407:53
Module parse failed: Unexpected token (2407:53)
File was processed with these loaders:
* ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
| intent: renderingIntent,
| renderInteractiveForms: renderInteractiveForms === true,
> annotationStorage: annotationStorage?.getAll() || null
| });
| }
I've tried uninstalling and reinstalling relevant packages, as well as npm update, npm audit, and so forth. I also tried adding the worker-loader npm package but it's already a peer dependency on pdfjs-dist so it made no difference. My partner on this project has the same repo and he has no issues, so I'm sure it's something on my end. I believe it has to do with support for optional chaining, but not sure how to proceed.
Thanks!
I just stumbled upon the same issue. What I did was to revert pdfjs-dist to an earlier version (2.9.359 back to 2.6.347 in my case). It all works fine now, hope it helps someone.
A possible explanation from a similar case could be found in this other question.
try to include the package in babel-loader rule
{
test: /\.[tj]sx?$/i,
include: [
/\/node_modules\/pdfjs-dist/,`enter code here`
/\/src/,
],
loader: 'babel-loader',`enter code here`
options: {},
},
Most likely you have incorrect version of webpack. Try to use es5 build
https://github.com/mozilla/pdf.js/issues/12905
This helped me,
You need to import this lib asynchronously
let pdfjs;
(async function () {
pdfjs = await import("pdfjs-dist/build/pdf");
const pdfjsWorker = await import("pdfjs-dist/build/pdf.worker.entry");
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
})();
You Need to downgrade the package version to
("pdfjs-dist": "2.5.207")
This works fine for me.

Error: Support for the experimental syntax 'optionalChaining' isn't currently enabled, but it is

I've followed the instructions here and here and I've added the following to my package.json
},
"babel": {
"plugins": [
"#babel/plugin-proposal-nullish-coalescing-operator",
"#babel/plugin-proposal-optional-chaining"
]
},
"dependencies": {
But I'm still getting the error
Support for the experimental syntax 'optionalChaining' isn't currently enabled
What am I doing wrong here?
Okay I am bit late here, but I can see the question is still active, for those come later:
At the time of writing, optional chaining might not work in NUXT project with node > 12, try using the current LTS version (node 12).
I think the issue might related to one or more dependencies of NUXT but we didn't investigate further, using node 12 resolves the issue for us.
I had a similar problem,
I was using Vue CLI ,the reason is that the scaffolding version is too low (plugins installed separately seem to be ignored), you can check and upgrade your project scaffolding

Where should I insert '#babel/polyfill' into?: main.js or each modules [duplicate]

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';

webpack with NO loader is preventing me from using advanced JavaScript syntax, parse error on native spread syntax

I'm writing a node tool and I bundle it with webpack before publishing to npm (to have a fast execution with npx)
I don't need any loader / babel setup since it's pure JavaScript which is running fine under my current node 9. It used to work. The webpack config is trivial (13 lines).
However, when bundling, webpack latest (^3.10.0) complains on the spread syntax I started to use: (JS stage 3 at this date, but accepted by node 8.1+ and node 9)
Module parse failed: Unexpected token (47:2)
You may need an appropriate loader to handle this file type.
|
| return {
| ...SEC,
| listenToUncaughtErrors,
| listenToUnhandledRejections,
So why? The target (node) is accepting this syntax, and isn't webpack supposed to just bundle my code?
Is webpack parsing my code with an embedded JS interpreter? It seems so, but where can I find the specifications of this interpreter and see what features are supported?
I couldn't find anything in the doc. Similar questions here are not in a "no babel" configuration.
So why is webpack complaining here?
[edit] config and full code here and pasted here for your convenience:
module.exports = {
target: 'node',
entry: {
main: './src/index.js'
},
output: {
path: path.join(__dirname, '../dist'),
filename: 'bundled.js',
},
externals: {
conf: 'commonjs conf',
},
}
(A colleague of mine pointed me to the answer)
YES, webpack is parsing the JavaScript code. It is internally using acorn "A tiny, fast JavaScript parser, written completely in JavaScript.". At the time of this question, webpack is calling acorn with the language version 2017
and YES, acorn is restricting the available JavaScript features. According to the doc: "Only 'stage 4' (finalized) ECMAScript features are being implemented by Acorn."
Spread syntax being a stage 3 feature (at the time of this question), webpack/acorn can't parse it, leading to the error:
Module parse failed: Unexpected token.
You may need an appropriate loader to handle this file type.
So YES, webpack is parsing the code and using stage <= 3 features requires a webpack loader.

How can I use babel-polyfill for multiple separated entries / outputs?

I have this in my webpack.config.js to create two different outputs from two sources:
module.exports = {
entry: {
'dist/index.js': ['babel-polyfill', './src/Component.jsx'],
'example/bundle.js': ['babel-polyfill', './src/Page.jsx'],
},
output: {
path: './',
filename: '[name]',
},
...
Compiling it with webpack works just fine, but if I load index.js in a browser I get this error:
Uncaught Error: only one instance of babel-polyfill is allowed
I need babel-polyfill for both outputs. What can I do?
When developing a library (as opposed to an application), the Babel team does not recommend including babel-polyfill in your library. We recommend either:
Assume the ES6 globals are present, thus you'd instruct your library users to load babel-polyfill in their own codebase.
Use babel-runtime by enabling babel-plugin-transform-runtime, which attempts to analyze your code to figure out what ES6 library functionality you are using, then rewrites the code to load the polyfilled logic from babel-runtime instead of from the global scope. One downside of this approach is that it has no way to polyfill new .prototype methods like Array.prototype.find since it can't know if foo.find is an array.
So my recommendation would be to remove babel-polyfill from your dist/index.js bundle entirely.
Use idempotent-babel-polyfill
import 'idempotent-babel-polyfill';
https://github.com/codejamninja/idempotent-babel-polyfill

Categories