From e24218758bb21bfdc296731d70f3d48ab786e5f5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Micha=C5=82=20Go=C5=82=C4=99biowski-Owczarek?= Date: Mon, 10 Jul 2023 18:23:07 +0200 Subject: [PATCH] Build: Switch form Terser to SWC for JS minification (#5286) Also, as part of this, fix the `file` & `sources` properties of the source map file. Fixes gh-5285 Closes gh-5286 Ref gh-5258 --- Gruntfile.js | 44 ++++++++++++++++++++----------- build/tasks/build.js | 2 +- build/tasks/minify.js | 56 ++++++++++++++++++++++++++++++++++++++++ build/tasks/sourcemap.js | 2 +- package.json | 3 +-- 5 files changed, 88 insertions(+), 19 deletions(-) create mode 100644 build/tasks/minify.js diff --git a/Gruntfile.js b/Gruntfile.js index 65aec9648..b5cbc1bf3 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -312,27 +312,41 @@ module.exports = function( grunt ) { files: [ "<%= eslint.dev.src %>" ], tasks: [ "dev" ] }, - terser: { + minify: { all: { files: { "dist/<%= grunt.option('filename').replace('.js', '.min.js') %>": "dist/<%= grunt.option('filename') %>" }, options: { - ecma: 5, sourceMap: { - filename: "dist/<%= grunt.option('filename').replace('.js', '.min.map') %>" - }, - format: { - ascii_only: true, - comments: false, - preamble: "/*! jQuery v<%= pkg.version %> | " + - "(c) OpenJS Foundation and other contributors | " + - "jquery.org/license */" + filename: "dist/<%= grunt.option('filename').replace('.js', '.min.map') %>", + + // The map's `files` & `sources` property are set incorrectly, fix + // them via overrides from the task config. + // See https://github.com/swc-project/swc/issues/7588#issuecomment-1624345254 + overrides: { + file: "jquery.min.js", + sources: [ + "jquery.js" + ] + } }, - compress: { - hoist_funs: false, - loops: false + swc: { + format: { + ecma: 5, + asciiOnly: true, + comments: false, + preamble: "/*! jQuery v4.0.0-pre | " + + "(c) OpenJS Foundation and other contributors | " + + "jquery.org/license */\n" + }, + compress: { + ecma: 5, + hoist_funs: false, + loops: false + }, + mangle: true } } } @@ -400,7 +414,7 @@ module.exports = function( grunt ) { grunt.registerTask( "dev", [ "build:*:*", runIfNewNode( "newer:eslint:dev" ), - "newer:terser", + "newer:minify", "remove_map_comment", "dist:*", "qunit_fixture", @@ -410,7 +424,7 @@ module.exports = function( grunt ) { grunt.registerTask( "default", [ runIfNewNode( "eslint:dev" ), "build:*:*", - "terser", + "minify", "remove_map_comment", "dist:*", "test:prepare", diff --git a/build/tasks/build.js b/build/tasks/build.js index 98d95cbe5..e1dd39993 100644 --- a/build/tasks/build.js +++ b/build/tasks/build.js @@ -339,6 +339,6 @@ module.exports = function( grunt ) { ""; grunt.log.writeln( "Creating custom build...\n" ); - grunt.task.run( [ "build:*:*" + ( modules ? ":" + modules : "" ), "terser", "dist" ] ); + grunt.task.run( [ "build:*:*" + ( modules ? ":" + modules : "" ), "minify", "dist" ] ); } ); }; diff --git a/build/tasks/minify.js b/build/tasks/minify.js new file mode 100644 index 000000000..1a6ddbd4a --- /dev/null +++ b/build/tasks/minify.js @@ -0,0 +1,56 @@ +/** + * Minify JavaScript using SWC. + */ + +"use strict"; + +module.exports = ( grunt ) => { + const swc = require( "@swc/core" ); + + grunt.registerMultiTask( + "minify", + "Minify JavaScript using SWC", + async function() { + const done = this.async(); + const options = this.options(); + const sourceMapFilename = options.sourceMap && options.sourceMap.filename; + const sourceMapOverrides = options.sourceMap && options.sourceMap.overrides || {}; + + await Promise.all( this.files.map( async( { src, dest } ) => { + if ( src.length !== 1 ) { + grunt.fatal( "The minify task requires a single source per destination" ); + } + + const { code, map: incompleteMap } = await swc.minify( + grunt.file.read( src[ 0 ] ), + { + ...options.swc, + inlineSourcesContent: false, + sourceMap: sourceMapFilename ? + { + filename: sourceMapFilename + } : + false + } + ); + + grunt.file.write( dest, code ); + + if ( sourceMapFilename ) { + + // Apply map overrides if needed. See the task config description + // for more details. + const mapObject = { + ...JSON.parse( incompleteMap ), + ...sourceMapOverrides + }; + const map = JSON.stringify( mapObject ); + + grunt.file.write( sourceMapFilename, map ); + } + } ) ); + + done(); + } + ); +}; diff --git a/build/tasks/sourcemap.js b/build/tasks/sourcemap.js index f6ef5698e..8b9c248e0 100644 --- a/build/tasks/sourcemap.js +++ b/build/tasks/sourcemap.js @@ -3,7 +3,7 @@ var fs = require( "fs" ); module.exports = function( grunt ) { - var config = grunt.config( "terser.all.files" ); + var config = grunt.config( "minify.all.files" ); grunt.registerTask( "remove_map_comment", function() { var minLoc = grunt.config.process( Object.keys( config )[ 0 ] ); diff --git a/package.json b/package.json index dd92954d3..e02aa9b80 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "devDependencies": { "@babel/core": "7.10.5", "@babel/plugin-transform-for-of": "7.10.4", + "@swc/core": "1.3.66", "colors": "1.4.0", "commitplease": "3.2.0", "core-js-bundle": "3.6.5", @@ -42,7 +43,6 @@ "grunt-karma": "4.0.2", "grunt-newer": "1.3.0", "grunt-npmcopy": "0.2.0", - "grunt-terser": "2.0.0", "gzip-js": "0.3.2", "husky": "4.2.5", "jsdom": "19.0.0", @@ -67,7 +67,6 @@ "rollup": "2.21.0", "sinon": "7.3.1", "strip-json-comments": "3.1.1", - "terser": "5.17.6", "testswarm": "1.1.2" }, "scripts": { -- 2.39.5