Skip to content
This repository has been archived by the owner on Oct 9, 2020. It is now read-only.

Commit

Permalink
Use terser to support minification of more permissive babel presets
Browse files Browse the repository at this point in the history
Currently, only ES5 javascript can be minified, due to the reliance on
uglify-js. With terser (a maintained fork of the harmony branch of
UglifyJS2) it is possible to support a broader range of javascript
syntax.

The API changed between uglify-js@2 and uglify-js@3 / terser, but the
translation to the new API was fairly straightforward. It hews more
closely to the original code than #815, and consequently I think it
avoids regressing any features (for instance, the ability to include
sourceContents in source maps or to control the comment stripping is
retained).

As browsers continue to support more features beyond ES5, and
because babel recommends use of the 'env' preset, it will become
increasingly likely that users' babel transpilation settings will cause
errors when trying to minify with jspm and friends as long as it uses
uglify-js.

refs #815, #726
  • Loading branch information
fdintino committed Jan 24, 2019
1 parent 17050ae commit a2e7901
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 22 deletions.
47 changes: 29 additions & 18 deletions lib/output.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,22 @@ var fs = require('fs');
var Promise = require('bluebird');
var asp = require('bluebird').promisify;
var extend = require('./utils').extend;
var terser = require('terser');

var fromFileURL = require('./utils').fromFileURL;
var toFileURL = require('./utils').toFileURL;

// Ugly hack to get around terser's strange code loading and export system
// (inherited from uglify-js), and the fact that their SourceMap wrapper is
// not exported
var TerserSourceMap = new Function('MOZ_SourceMap', "exports", "require", function() {
var code = ['terser/lib/utils.js', 'terser/lib/sourcemap.js'].map(function(file) {
return fs.readFileSync(require.resolve(file), 'utf8');
});
code.push('return SourceMap;');
return code.join('\n');
}())(require('source-map'), terser, require);

function countLines(str) {
return str.split(/\r\n|\r|\n/).length;
}
Expand Down Expand Up @@ -72,36 +84,35 @@ function createOutput(outFile, outputs, basePath, sourceMaps, sourceMapContents)
}

function minify(output, fileName, mangle, uglifyOpts) {
var uglify = require('uglify-js');
var ast;
var files = {};
files[fileName] = output.source;
var result;
try{
ast = uglify.parse(output.source, { filename: fileName });
result = terser.minify(files, {
parse: {},
compress: uglifyOpts.compress,
mangle: mangle,
output: { ast: true, code: false }
});
} catch(e){
throw new Error(e);
}
ast.figure_out_scope();

ast = ast.transform(uglify.Compressor(uglifyOpts.compress));
ast.figure_out_scope();
if (mangle !== false)
ast.mangle_names();

if (result.error) {
throw new Error(result.error);
}

var ast = result.ast;

var sourceMap;
if (output.sourceMap) {
if (typeof output.sourceMap === 'string')
output.sourceMap = JSON.parse(output.sourceMap);

var sourceMapIn = output.sourceMap;
sourceMap = uglify.SourceMap({
sourceMap = TerserSourceMap({
file: fileName,
orig: sourceMapIn
orig: output.sourceMap
});

if (uglifyOpts.sourceMapIncludeSources && sourceMapIn && Array.isArray(sourceMapIn.sourcesContent)) {
sourceMapIn.sourcesContent.forEach(function(content, idx) {
sourceMap.get().setSourceContent(sourceMapIn.sources[idx], content);
});
}
}

var outputOptions = uglifyOpts.beautify;
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
"rollup": "^0.58.2",
"source-map": "^0.5.3",
"systemjs": "^0.19.46",
"traceur": "0.0.105",
"uglify-js": "^2.6.1"
"terser": "^3.8.1",
"traceur": "0.0.105"
},
"devDependencies": {
"babel": "^5.8.38",
Expand Down
3 changes: 1 addition & 2 deletions test/test-sfx.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@
<div id="mocha">
<script>
window.$ = { jquery: 1 };
window.DEBUG = false;
</script>
<script src="output/sfx.js"></script>
<script>
mocha.setup('tdd');

DEBUG = false;

function assert(assertion, msg) {
if (!assertion)
throw new Error(msg || 'Assertion failed');
Expand Down

0 comments on commit a2e7901

Please sign in to comment.