How to minify ES6 functions with gulp-uglify? - javascript

When I run gulp I get the following error:
[12:54:14] { [GulpUglifyError: unable to minify JavaScript]
cause:
{ [SyntaxError: Unexpected token: operator (>)]
message: 'Unexpected token: operator (>)',
filename: 'bundle.js',
line: 3284,
col: 46,
pos: 126739 },
plugin: 'gulp-uglify',
fileName: 'C:\\servers\\vagrant\\workspace\\awesome\\web\\tool\\bundle.js',
showStack: false }
The offending line contains an arrow function:
let zeroCount = numberArray.filter(v => v === 0).length
I know I can replace it with the following to remedy the minification error by abandoning ES6 syntax:
let zeroCount = numberArray.filter(function(v) {return v === 0;}).length
How can I minify code containing ES6 features via gulp?

You can leverage gulp-babel as such...
const gulp = require('gulp');
const babel = require('gulp-babel');
const uglify = require('gulp-uglify');
gulp.task('minify', () => {
return gulp.src('src/**/*.js')
.pipe(babel({
presets: ['es2015']
}))
.pipe(uglify())
// [...]
});
This will transpile your es6 early in the pipeline and churn out as widely supported "plain" javascript by the time you minify.
May be important to note - as pointed out in comments - the core babel compiler ships as a peer dependency in this plugin. In case the core lib is not being pulled down via another dep in your repo, ensure this is installed on your end.
Looking at the peer dependency in gulp-babel the author is specifying #babel/core (7.x). Though, the slightly older babel-core (6.x) will work as well. My guess is the author (who is the same for both projects) is in the midsts of reorganizing their module naming. Either way, both npm installation endpoints point to https://github.com/babel/babel/tree/master/packages/babel-core, so you'll be fine with either of the following...
npm install babel-core --save-dev
or
npm install #babel/core --save-dev

The accepted answer doesn't really answer how to minify straight es6. If you want to minify es6 without transpiling, gulp-uglify v3.0.0 makes that possible:
Update March 2019
Using my original answer, you definitely want to replace the uglify-es package with terser, as it seems uglify-es is no longer being maintained.
Original answer, still works:
1.) First, upgrade your gulp-uglify package to > 3.0.0 If you're using yarn and want to update to the latest version:
yarn upgrade gulp-uglify --latest
2.) Now you can use uglify-es, the "es6 version" of uglify, as so:
const uglifyes = require('uglify-es');
const composer = require('gulp-uglify/composer');
const uglify = composer(uglifyes, console);
gulp.task('compress', function () {
return gulp.src('src/*.js')
.pipe(uglify())
.pipe(gulp.dest('dist'))
});
For more info: https://www.npmjs.com/package/gulp-uglify

You actually can uglify ES6 code without transpilation. Instead of gulp-uglify plugin, use gulp-uglifyes plugin.
var gulp = require('gulp');
var rename = require('gulp-rename');
var uglify = require('gulp-uglifyes');
var plumber = require('gulp-plumber');
var plumberNotifier = require('gulp-plumber-notifier');
var sourcemaps = require('gulp-sourcemaps');
var runSequence = require('run-sequence').use(gulp);
gulp.task('minjs', function () {
return gulp.src(['/dist/**/*.js', '!/dist/**/*.min.js'])
.pipe(plumberNotifier())
.pipe(sourcemaps.init())
.pipe(uglify({
mangle: false,
ecma: 6
}))
.pipe(rename(function (path) {
path.extname = '.min.js';
}))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('/dist'));
});

gulp-uglify:
For ES6 and newer.
install: npm install --save-dev gulp-uglify
install: npm install --save-dev gulp-babel #babel/core #babel/preset-env
Usage:
const gulp = require('gulp');
const uglify = require('gulp-uglify');
const babel = require('gulp-babel');
gulp.task('script', () => {
return gulp.src('src/**/*.js')
.pipe(babel({
presets: ['#babel/env']
}))
.pipe(uglify())
.pipe(gulp.dest('src/dist'))
});

I worked at this for a while before getting it to work. As other answers have stated the problem is that gulp-uglify doesn't support ES6. gulp-uglify-es does, however if is no longer maintained. Terser is recommended by others, but it doesn't play well with gulp and using it with pipe().
If you use gulp-uglify as I do your gulpfile.js looks something like:
var uglify = require('gulp-uglify');
const html2js = () => {
var source = gulp.src(config.appFiles.templates);
return source
.pipe(concat('templates-app.js'))
.pipe(uglify())
.pipe(gulp.dest(config.buildDir));
};
You can however use the gulp-terser package, which is very easy to just replace and get the same functionality:
var terser = require('gulp-terser');
const html2js = () => {
var source = gulp.src(config.appFiles.templates);
return source
.pipe(concat('templates-app.js'))
.pipe(terser())
.pipe(gulp.dest(config.buildDir));
};

Using gulp-uglify-es instead of gulp-uglify helped me perfectly to accomplish same as you're asking for

The current (Nov 2021) easiest way to transpile and uglify is to use gulp-terser.
If you're already using gulp-uglify then just install gulp-terser and change "uglify" with "terser" and you're done.
const uglifyes = require('terser');
gulp.task('compress', function () {
return gulp.src('src/*.js')
.pipe(terser())
.pipe(gulp.dest('dist'))
});

unfortunately, as per now, you can't use uglify with es-next code,
you can:
Transpile to ES5using Babel
Use Babili instead of Uglify.

module.exports = {
...
optimization: {
minimize: true
},
...
}
webpack can do the job

Related

Syntax in crac-webpack-rewired to solve webpack polyfills error

I created my project in React using create-react-app, but after sometime I got to this error in the console
BREAKING CHANGE: webpack \< 5 used to include polyfills for node.js core modules by default.
This is no longer the case. Verify if you need this module and configure a polyfill for it.
If you want to include a polyfill, you need to:
\- add a fallback 'resolve.fallback: { "path": require.resolve("path-browserify") }'
\- install 'path-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
resolve.fallback: { "path": false }
# ./node_modules/loader-utils/lib/index.js 7:25-54
# ./node_modules/file-loader/dist/index.js 11:19-42
# ./node_modules/file-loader/dist/cjs.js 3:15-33
# ./src/App.js 13:0-35
# ./src/index.js 7:0-24 11:33-36
After reading this post, I reached the conclusion I had to modify the webpack.config.js that I did not have because I created the project with create-react-app. Instead of ejecting (it is not very recommended), I used the npm package advised at the end of this thread. The problem is that there are no examples on how to use it. My question is which syntaxis do I have to follow to modify config/webpack.extend.js? This is the code at the moment:
module.exports = {
dev: (config) => {
//override webpack configuration
config.externals =[..];
return config;
},
prod: (config) => {
//override webpack configuration
config.externals =[..];
return config;
}
};
I have tried using console.log(config) but it never gets to print as errors are printed back.
You cannot use console.log() because that code is not executed from the browser, but in the Webpack "compilation" phase.
This could be a possible solution for your case.
module.exports = {
dev: (config) => {
//override webpack configuration
config.resolve.fallback = {"path": require.resolve("path-browserify")};
return config;
},
prod: (config) => {
//override webpack configuration
config.resolve.fallback = {"path": require.resolve("path-browserify")};
return config;
}
}
Notice that you have to install the package path-browserfy.
You can also set the path property to false.

how to combine all yarn files with gulp

I have yarn up and running, have figured out a bit how it works, and made my inroads into figuring out gulp, after having discovered how to install version 4 instead of the default version that throws deprecation errors.
Now I have installed 3 packages with yarn, and it has downloaded a LOT of dependencies. No problem, one can use a gulp file to combine those into one javascript(or so i'm told)
The only thing is, how do I do that whilst maintaining the yarn dependencies as yarn builds those up? How would I format my gulp task for combining the yarn libaries i've added?
My gulp task currently looks like this:
//Concatenate & Minify JS
gulp.task('scripts', function() {
return gulp.src('assets/javascript/*.js')
.pipe(concat('all.js'))
.pipe(gulp.dest('assets/dist'))
.pipe(rename('all.min.js'))
.pipe(uglify())
.pipe(gulp.dest('assets/dist/js'));
});
And this concatenates my scripts as it should, but when I wanted to add the yarn folder it hit me that yarn manages dependencies and what not so everything has it's correct dependency and such. I doubt I can just add them all to the same file and hope all is well.(or can I?)
I run this task with yarn run watch
I've added the following packages: html5shiv, jquery, modernizr
What would be the correct way to add the yarn files in in assets/node_modules?
After long searching I found https://pawelgrzybek.com/using-webpack-with-gulpjs/
which gave me the following solution:
Execute the command:
sudo yarn add global gulp webpack webpack-stream babel-core babel-loader babel-preset-latest
create a webpack.config.js file
enter in it:
module.exports = {
output: {
filename: 'bundle.js', // or whatever you want the filename to be
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
presets: [
['latest', { modules: false }],
],
},
},
],
},
};
Then create a gulpfile.js
var gulp = require('gulp');
var webpack = require('webpack');
var webpackStream = require('webpack-stream');
var webpackConfig = require('./webpack.config.js');
gulp.task('watch', watchTask);
gulp.task('default', defaultTask);
gulp.task('scripts', function() {
return gulp.src('assets/javascript/*.js')
.pipe(webpackStream(webpackConfig), webpack)
.pipe(gulp.dest('./assets/js')); // Or whereever you want your js file to end up.
});
function watchTask(done) {
// Wherever you stored your javascript files
gulp.watch('assets/javascript/*.js', gulp.parallel('scripts'))
done();
}
function defaultTask(done) {
// place code for your default task here
done();
}
Then in the directory execute yarn watch and have it run in the background where you can throw an eye on it now and then.

Gulp concat plugins error

I'm using gulp for concat my plugins (bootstrap, jquery, etc) in one big file, this is my code:
const gulp = require('gulp');
const csso = require('gulp-csso');
const concat = require('gulp-concat');
const babel = require('gulp-babel');
const uglify = require('gulp-uglify');
gulp.task('build', function() {
gulp.src(["./bower_components/bootstrap/dist/css/bootstrap.min.css",
"./bower_components/ekko-lightbox/dist/ekko-lightbox.css",
"./bower_components/owl.carousel/dist/assets/owl.carousel.min.css",
"./bower_components/owl.carousel/dist/assets/owl.theme.default.css",
"./client/css/core.css",
"./client/css/responsive.css"])
.pipe(csso())
.pipe(concat("main.css"))
.pipe(gulp.dest("./build"));
gulp.src(["./bower_components/jquery/dist/jquery.js",
"./bower_components/bootstrap/dist/js/bootstrap.bundle.js",
"./bower_components/ekko-lightbox/dist/ekko-lightbox.min.js",
"./bower_components/lazysizes/lazysizes.min.js",
"./bower_components/owl.carousel/dist/owl.carousel.min.js",
"./bower_components/moment/min/moment.min.js",
"./bower_components/moment/min/locales.min.js",
"./client/js/script.js" ])
.pipe(babel({
presets: ['es2015']
}))
.pipe(uglify())
.pipe(concat("main.js"))
.pipe(gulp.dest('./build'));
});
And it's doing OK. But when i'm including this script on my project, console throws my error: Uncaught TypeError: Cannot set property 'bootstrap' of undefined.
I tried just concat it without es2015 or uglify, but this error (or another, like moment is not defined) still persists. What am i doing wrong?
Ok, i got it.
npm install --save-dev babel-plugin-proposal-object-rest-spread
npm install --save-dev babel-plugin-transform-object-rest-spread
Then pipe
.pipe(babel({
presets: [['env', {
loose: true,
modules: false,
exclude: ['transform-es2015-typeof-symbol']
}]],
plugins: ['transform-es2015-modules-strip', 'transform-object-rest-spread']
}))
And it works

Gulp and Babel: Error: Cannot find module

I have a project that I've set up using gulp and babel. Everything is working fine, except when I create a module and import it once it's converted from ES6 to ES6 it doesn't work. I get an error:
Error: Cannot find module 'hello.js'
at Function.Module._resolveFilename (module.js:440:15)
at Function.Module._load (module.js:388:25)
at Module.require (module.js:468:17)
Here's my gulpfile.babel.js:
import gulp from "gulp";
import babel from "gulp-babel"
import concat from "gulp-concat"
const dirs = {
src: "src",
dest: "build"
}
gulp.task("build", () => {
return gulp.src(dirs.src + "/**/*.js")
.pipe(babel())
.pipe(concat("build.js"))
.pipe(gulp.dest(dirs.dest))
});
gulp.task("default", ["build"]);
During build everything is concatenated into one file. Under src/ I have:
app.js
hellojs
app.js
import hello from './hello.js'
console.log(hello());
hello.js
export default () => {
return 'Hey from hello.js';
};
And I run like so:
npm start
Which basically calls node ./build/build.js.
I think it's because it's concatenating the ES6 into ES5 and the bundle.js still contains the require for hello.js. It wont find it though because its concatenated. Is that possible?
It is incorrect to concatenate two module files and expect the program to work properly, even when transpiled to ES5. Bundling involves more than concatenating the scripts: each module needs a closure for registering exports and resolving the contents of other modules.
You must instead use a bundling tool such as Browserify, Webpack or Rollup. Here's how one would bundle with Browserify (which in this case, it is easier to rely on the Babelify transform rather than gulp-babel):
var browserify = require('browserify');
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var babelify = require('babelify');
gulp.task('browserify', function() {
return browserify({
entries: './src/app.js'
})
.transform(babelify)
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest('./build/'));
});

How can I apply browserify to my gulp file?

I am relatively new to gulp and browserify. For my understanding, if you could please explain how I could use browserify with my current gulp file...
As I'm using 'require' for my gulp modules, would I get any benefit using browserify? If so, how would it benefit me?
var sass = require('gulp-sass'),
concat = require('gulp-concat'),
watch = require('gulp-watch'),
gulp = require('gulp'),
minifyCSS = require('gulp-minify-css'),
rename = require('gulp-rename'), // to rename any file
destination = 'public/css';
// task to compile sass, minify then rename file
gulp.task('sass', function () {
gulp.src('public/sass/**/*.scss')
.pipe(sass())
.pipe(gulp.dest(destination))
.pipe(concat('style.css'))
.pipe(gulp.dest(destination))
.pipe(minifyCSS())
.pipe(rename('style.min.css'))
.pipe(gulp.dest(destination));
});
// save typing gulp sass, and use just gulp instead
gulp.task('default', ['sass']);
// simple watch task
gulp.task('watch', function () {
gulp.watch('public/sass/**/*.scss', ['sass']);
});
What do you think browserify does?
At the moment, I don't see any need to include it as you are not processing/bundling any scripts.

Categories