Coder Social home page Coder Social logo

gulp-terser-js's Introduction

gulp-terser-js

NPM Version NPM Downloads Linux Build Test Coverage

A Terser-js plugin for Gulp

Why choose terser?

uglify-es is no longer maintained and uglify-js does not support ES6+.

terser is a fork of uglify-es that retains API and CLI compatibility with uglify-es and uglify-js@3. Source:Why choose terser?

Why choose gulp-terser-js

This plugin displays formatted error:

error screenshot

Installation

npm install gulp-terser-js

Basic Usage

const terser = require('gulp-terser-js')

const minifyJS = () =>
  gulp.src('asset/js/*.js')
    .pipe(terser({
       mangle: {
         toplevel: true
       }
    }))
    .on('error', function (error) {
      this.emit('end')
    })
    .pipe(gulp.dest('public/js/'))


gulp.task('minifyJS', minifyJS)

Options

The options you can use can be found here.

Avanced Usage

const gulp = require('gulp')
const concat = require('gulp-concat')
const sourcemaps = require('gulp-sourcemaps')
const terser = require('gulp-terser-js')

const sourceMapOpt = {
  sourceMappingURL: (file) => 'http://127.0.0.1/map/' + file.relative + '.map'
}
const mapsFolder = './public/map'

const minifyJS = () =>  
  gulp.src('./asset/js/*.js')
    .pipe(gulp.dest(mapsFolder))
    .pipe(sourcemaps.init())
    .pipe(concat('script.js'))
    .pipe(terser({
      mangle: {
        toplevel: true
      }
    }))
    .on('error', function (error) {
      if (error.plugin !== "gulp-terser-js") {
        console.log(error.message)
      }
      this.emit('end')
    })
    .pipe(sourcemaps.write(mapsFolder, sourceMapOpt))
    .pipe(gulp.dest('./public/js/'))

gulp.task('minifyJS', minifyJS)

Source maps

When running Terser on compiled Javascript, you may run into issues with source maps. If you need to pass the content of your source maps to Terser, first you must set the loadMaps option to true when initializing gulp-sourcemaps. Next, make the content source map option true when piping Terser.

A basic setup may look like this:

gulp.src('asset/js/*.js')
  .pipe(sourcemaps.init({ loadMaps: true }))
  .pipe(terser({
     sourceMap: {
       content: true
     }
  }))
  .pipe(sourcemaps.write())
  .pipe(gulp.dest('dist'))

Can I use terser to format error of an other gulp module ?

// ... 
const less = require('gulp-less');

const generateCSS = () =>  
  gulp.src("./asset/css/*.less", srcOptions)
    .pipe(less()).on("error", printLESSError)
    .pipe(postcss([cssnano]))
    .pipe(sourcemaps.write(path.relative(srcOptions.cwd, mapsFolder), sourceMapOpt))
    .pipe(gulp.dest(outputBuildFolder))

function printLESSError(error) {
  if (error.plugin === "gulp-less") {
    terser.printError.call(this, {
      name: error.type,
      line: error.line,
      col: error.column,
      filePath: error.filename,
      fileContent: '' + fs.readFileSync(error.filename),
      message: (error.message || '').replace(error.filename, path.basename(error.filename)).split(' in file')[0],
      plugin: error.plugin
    })
  } else {
    console.log(error.message);
  }
  this.emit('end')
}

Version

Description gulp-terser-js
Node Version >= 8.10.0
Terser Version 4.1.4+
Gulp Version >= 4.X

gulp-terser-js's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

gulp-terser-js's Issues

sourcemap is incorrect when processing multiple files with existing sourcemaps

I have a collection of js files that were compiled from Typescript. I want to minify these with terser. They have existing sourcemaps. When I do this, some of the sourcemaps produced look incorrect. They have the wrong "sources" listed. It looks like they have the sources of the first file processed.

From my quick read of the code, it looks like options.sourceMap is modified and then passed into terser.

opts.sourceMap.filename = file.sourceMap.file
// ...
opts.sourceMap.content = file.sourceMap

Maybe opts.sourceMap should be clone from the original options each time?

Any way to pass error message to gulp-notify?

Any help greatly appreciated

Currently have my onError set up as so:

const onError = function(err) {
	notify.onError({
		title:    "Gulp",
		subtitle: "๐Ÿ”บ Fail",
		message:  "Error: <%= error.message.toString() %>",
		sound:    "Frog"
	})(err);

	this.emit('end');
};

and scripts task:

function scripts() {
	return (
		gulp
			.src(JS.src, { sourcemaps: true})
			.pipe(terser2({
				ecma: 6,
				keep_fnames: false,
				mangle: {
					toplevel: false,
				},
			}))
			.on('error', function (error) {
				if (error.plugin !== "gulp-terser-js") {
					console.log(error.message)

				}
				this.emit('end')
			})
			.pipe(plumber({errorHandler: onError}))
			.pipe(gulp.dest(JS.build, { sourcemaps: true }))
			.pipe(browsersync.stream())
			.pipe(notify({
				title: 'Gulp',
				subtitle: 'โœ… Success',
				message: 'Js compiled',
				sound: "Pop"
			}))
	);
}

package.json:

 "gulp": "^4.0.2",
"gulp-notify": "^3.2.0",
 "gulp-terser-js": "^5.2.2",

gulp-terser-js assumes that OS EOL is the file's EOL

Encountered this with [email protected] on Windows, but not Linux:

[10:13:19] TypeError: Cannot read property 'replace' of undefined
    at printError (C:\myproject\node_modules\gulp-terser-js\bin\index.js:71:69)
    at DestroyableTransform._transform (C:\myproject\node_modules\gulp-terser-js\bin\index.js:42:19)
    at DestroyableTransform.Transform._read (C:\myproject\node_modules\gulp-terser-js\node_modules\readable-stream\lib\_stream_transform.js:177:10)
    at DestroyableTransform.Transform._write (C:\myproject\node_modules\gulp-terser-js\node_modules\readable-stream\lib\_stream_transform.js:164:83)
    at doWrite (C:\myproject\node_modules\gulp-terser-js\node_modules\readable-stream\lib\_stream_writable.js:405:139)
    at writeOrBuffer (C:\myproject\node_modules\gulp-terser-js\node_modules\readable-stream\lib\_stream_writable.js:394:5)
    at DestroyableTransform.Writable.write (C:\myproject\node_modules\gulp-terser-js\node_modules\readable-stream\lib\_stream_writable.js:303:11)
    at DestroyableTransform.ondata (C:\myproject\node_modules\readable-stream\lib\_stream_readable.js:619:20)
    at DestroyableTransform.emit (events.js:210:5)
    at DestroyableTransform.EventEmitter.emit (domain.js:499:23)
[10:13:19] 'build' errored after 8.42 s

That LoC is:

const pos = (more + 2) + fileContent.split(os.EOL)[error.line - 1].replace(/[^\t]/g, '').length * 3 + parseInt(col)

Replacing both instances of os.EOL in node_modules/gulp-terser-js/bin/index.js with '\n' fixes the problem in Windows so we get a nice error report.
Replacing os.EOL with '\r' in Linux makes the same problem reproducible in Linux.

We have a lot of files with \n as the line ending. What I suspect is that terser is reporting line numbers correctly, but gulp-terser-js is not correlating that to the file because it is assuming that os.EOL is the same line ending that the file is using.

Just getting this information out there before I have time to confirm my theory, write a test, or submit an MR.

Update dependencies version

  • terser 3.14.0 -> 4.1.4
  • object-assign 4.0.1 -> 4.1.1
  • plugin-error 0.1.2 -> 1.0.1
  • through2 2.0.0 -> 3.0.1
  • vinyl-sourcemaps-apply 0.2.0 -> 0.2.1

In readme recommanded gulp version -> 4.x

Improve doc

        .on('error', function (error) {
          if (error.plugin === "gulp-terser-js")) {
            this.emit('end')
          }

Support for async/await

I get "unexpected await identifier inside strict mode" when trying to minify a file with async/await

printError is not defined

d:\node_modules\gulp-terser-js\index.js:41
      return next(printError(new PluginError('gulp-terser', res.error)));
                  ^

ReferenceError: printError is not defined
    at DestroyableTransform._transform (d:\node_modules\gulp-terser-js\index.js:41:19)
    at DestroyableTransform.Transform._read (d:\node_modules\through2\node_modules\readable-stream\lib\_stream_transform.js:182:10)
    at DestroyableTransform.Transform._write (d:\node_modules\through2\node_modules\readable-stream\lib\_stream_transform.js:170:83)
    at doWrite (d:\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:406:64)
    at writeOrBuffer (d:\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:395:5)
    at DestroyableTransform.Writable.write (d:\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:322:11)
    at DestroyableTransform.ondata (d:\node_modules\through2\node_modules\readable-stream\lib\_stream_readable.js:612:20)
    at emitOne (events.js:115:13)
    at DestroyableTransform.emit (events.js:210:7)
    at addChunk (d:\node_modules\through2\node_modules\readable-stream\lib\_stream_readable.js:284:12)

My version:

{ npm: '5.3.0',
  ares: '1.10.1-DEV',
  cldr: '31.0.1',
  http_parser: '2.7.0',
  icu: '59.1',
  modules: '57',
  node: '8.2.1',
  openssl: '1.0.2l',
  tz: '2017b',
  unicode: '9.0',
  uv: '1.13.1',
  v8: '5.8.283.41',
  zlib: '1.2.11' }

My Package.json:

{
  "name": "site-builder",
  "version": "1.0.0",
  "description": "Build site",
  "main": "index.js",
  "scripts": {
    "test": "echo \"No test command\"",
    "buildHouse": "gulp houseBuildAll",
    "buildRelease": "gulp releaseBuildAll",
    "devWatcher": "gulp houseBuildThenDevWatcher"
  },
  "author": "My Site",
  "license": "ISC",
  "devDependencies": {
    "browser-sync": "^2.18.13",
    "child-process": "^1.0.2",
    "crc32": "^0.2.2",
    "gulp": "^3.9.1",
    "gulp-changed": "^3.1.0",
    "gulp-csso": "^2.0.0",
    "gulp-expect-file": "0.0.7",
    "gulp-filter": "^5.0.1",
    "gulp-html-beautify": "^1.0.1",
    "gulp-htmlmin": "^3.0.0",
    "gulp-if": "^2.0.2",
    "gulp-index": "0.0.8",
    "gulp-nunjucks-render": "^2.2.1",
    "gulp-plumber": "^1.1.0",
    "gulp-print": "^2.0.1",
    "gulp-terser-js": "^4.0.0",
    "gulp-typescript": "^5.0.1",
    "merge-stream": "^2.0.0",
    "run-sequence": "^2.1.0",
    "typescript": "^3.5.2"
  },
  "false": {},
  "dependencies": {}
}

My usage:

var terser = require('gulp-terser-js');

function buildScriptsTask(rebuildAll = true, releaseBuild = false) {
    return gulp.src(sourceUIFolder + '/**/*.js')
        .pipe(filter(['**', '!**/*_Global.*']))
        .pipe(gulpif(!rebuildAll, plumber()))
        .pipe(gulpif(!rebuildAll, changed(outputFolder + uiFolder)))
        .pipe(print(printFormat))
        .pipe(nunjucksRender(nunjucksOptions))
        .pipe(messageGenerator.generateMessages(outputFolder + uiFolder, rebuildAll))
        .pipe(gulpif(releaseBuild, terser()))
        .pipe(gulp.dest(outputFolder + uiFolder));
}

gulp.task('releaseBuild_Scripts_All', function() {
    return buildScriptsTask(rebuildAll = true, releaseBuild = true);
});

gulp.task('releaseBuildAll', function(done) {
runSequence('makeDestWritable',
           ['releaseBuild_Html_All',
            'releaseBuild_Scripts_All',
            'releaseBuild_Styles_All',
            'releaseBuild_SharedScripts_All',
            'releaseBuild_SharedStyles_All'
        ],
        'saveMessages_All',
        'buildIndex'
        );
}
//...

TypeError: this.emit is not a function

When the plugin encounters an error in my javascript code, it logs the error, but this is followed by a TypeError that breaks my gulp watch script.

It seems that the "this" context in the printError function no longers refers to the gulp stream.

Platform: Windows
Error:
D:..\node_modules\gulp-terser-js\index.js:82
return this.emit('end');
^

TypeError: this.emit is not a function
at printError (D:..\node_modules\gulp-terser-js\index.js:82:14)
at DestroyableTransform._transform (D:..\node_modules\gulp-terser-js\index.js:40:7)
at DestroyableTransform.Transform._read (D:..\node_modules\readable-stream\lib_stream_transform.js:184:10)
at DestroyableTransform.Transform._write (D:..\node_modules\readable-stream\lib_stream_transform.js:172:83)
at doWrite (D:..\node_modules\readable-stream\lib_stream_writable.js:428:64)
at writeOrBuffer (D:..\node_modules\readable-stream\lib_stream_writable.js:417:5)
at DestroyableTransform.Writable.write (D:..\node_modules\readable-stream\lib_stream_writable.js:334:11)
at DestroyableTransform.ondata (D:..\node_modules\readable-stream\lib_stream_readable.js:619:20)
at DestroyableTransform.emit (events.js:182:13)
at DestroyableTransform.EventEmitter.emit (domain.js:459:23)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.