From a5afa5ffc6625052318443efb3ceaf10234d38b6 Mon Sep 17 00:00:00 2001 From: Lorenzo Gabriele Date: Wed, 20 Mar 2024 10:09:54 +0100 Subject: [PATCH] Support Scala.js minify via `scalaJSMinify: Target[String]` (#3094) `minify` is a new feature released in Scala.js 1.16.0 https://www.scala-js.org/news/2024/03/19/announcing-scalajs-1.16.0 Pull Request: https://github.com/com-lihaoyi/mill/pull/3094 --- build.sc | 2 +- .../src/mill/scalajslib/ScalaJSModule.scala | 27 ++++++++++++++++--- .../scalajslib/worker/ScalaJSWorker.scala | 6 +++-- .../worker/api/ScalaJSWorkerApi.scala | 3 ++- .../scalajslib/worker/ScalaJSWorkerImpl.scala | 11 ++++++-- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/build.sc b/build.sc index 226ec51c4ee..0d8b77a10e5 100644 --- a/build.sc +++ b/build.sc @@ -70,7 +70,7 @@ object Deps { val testScala33Version = "3.3.1" object Scalajs_1 { - val scalaJsVersion = "1.15.0" + val scalaJsVersion = "1.16.0" val scalajsEnvJsdomNodejs = ivy"org.scala-js::scalajs-env-jsdom-nodejs:1.1.0" val scalajsEnvExoegoJsdomNodejs = ivy"net.exoego::scalajs-env-jsdom-nodejs:2.1.0" val scalajsEnvNodejs = ivy"org.scala-js::scalajs-env-nodejs:1.4.0" diff --git a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala index cd6ac0baaba..0772733cd92 100644 --- a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala +++ b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala @@ -129,7 +129,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => moduleKind = moduleKind(), esFeatures = esFeatures(), moduleSplitStyle = moduleSplitStyle(), - outputPatterns = scalaJSOutputPatterns() + outputPatterns = scalaJSOutputPatterns(), + minify = scalaJSMinify() ) } @@ -170,7 +171,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => moduleKind: ModuleKind, esFeatures: ESFeatures, moduleSplitStyle: ModuleSplitStyle, - outputPatterns: OutputPatterns + outputPatterns: OutputPatterns, + minify: Boolean )(implicit ctx: mill.api.Ctx): Result[Report] = { val outputPath = ctx.dest @@ -189,7 +191,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => moduleKind = moduleKind, esFeatures = esFeatures, moduleSplitStyle = moduleSplitStyle, - outputPatterns = outputPatterns + outputPatterns = outputPatterns, + minify = minify ) } @@ -269,6 +272,21 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => /** Name patterns for output. */ def scalaJSOutputPatterns: Target[OutputPatterns] = T { OutputPatterns.Defaults } + /** + * Apply Scala.js-specific minification of the produced .js files. + * + * When enabled, the linker more aggressively reduces the size of the + * generated code, at the cost of readability and debuggability. It does + * not perform size optimizations that would negatively impact run-time + * performance. + * + * The focus is on optimizations that general-purpose JavaScript minifiers + * cannot do on their own. For the best results, we expect the Scala.js + * minifier to be used in conjunction with a general-purpose JavaScript + * minifier. + */ + def scalaJSMinify: Target[Boolean] = T { true } + override def prepareOffline(all: Flag): Command[Unit] = { val tasks = if (all.value) Seq(scalaJSToolsClasspath) @@ -327,7 +345,8 @@ trait TestScalaJSModule extends ScalaJSModule with TestModule { moduleKind = moduleKind(), esFeatures = esFeatures(), moduleSplitStyle = moduleSplitStyle(), - outputPatterns = scalaJSOutputPatterns() + outputPatterns = scalaJSOutputPatterns(), + minify = scalaJSMinify() ) } diff --git a/scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala b/scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala index a7552ee1f1d..29c3f5aa3c9 100644 --- a/scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala +++ b/scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala @@ -160,7 +160,8 @@ private[scalajslib] class ScalaJSWorker extends AutoCloseable { moduleKind: api.ModuleKind, esFeatures: api.ESFeatures, moduleSplitStyle: api.ModuleSplitStyle, - outputPatterns: api.OutputPatterns + outputPatterns: api.OutputPatterns, + minify: Boolean )(implicit ctx: Ctx.Home): Result[api.Report] = { bridge(toolsClasspath).link( runClasspath = runClasspath.iterator.map(_.path.toNIO).toSeq, @@ -174,7 +175,8 @@ private[scalajslib] class ScalaJSWorker extends AutoCloseable { moduleKind = toWorkerApi(moduleKind), esFeatures = toWorkerApi(esFeatures), moduleSplitStyle = toWorkerApi(moduleSplitStyle), - outputPatterns = toWorkerApi(outputPatterns) + outputPatterns = toWorkerApi(outputPatterns), + minify = minify ) match { case Right(report) => Result.Success(fromWorkerApi(report)) case Left(message) => Result.Failure(message) diff --git a/scalajslib/worker-api/src/mill/scalajslib/worker/api/ScalaJSWorkerApi.scala b/scalajslib/worker-api/src/mill/scalajslib/worker/api/ScalaJSWorkerApi.scala index 0c39abbaf20..d5d12345a24 100644 --- a/scalajslib/worker-api/src/mill/scalajslib/worker/api/ScalaJSWorkerApi.scala +++ b/scalajslib/worker-api/src/mill/scalajslib/worker/api/ScalaJSWorkerApi.scala @@ -16,7 +16,8 @@ private[scalajslib] trait ScalaJSWorkerApi { moduleKind: ModuleKind, esFeatures: ESFeatures, moduleSplitStyle: ModuleSplitStyle, - outputPatterns: OutputPatterns + outputPatterns: OutputPatterns, + minify: Boolean ): Either[String, Report] def run(config: JsEnvConfig, report: Report): Unit diff --git a/scalajslib/worker/1/src/mill/scalajslib/worker/ScalaJSWorkerImpl.scala b/scalajslib/worker/1/src/mill/scalajslib/worker/ScalaJSWorkerImpl.scala index 1df6144ff87..ce1b58ee70b 100644 --- a/scalajslib/worker/1/src/mill/scalajslib/worker/ScalaJSWorkerImpl.scala +++ b/scalajslib/worker/1/src/mill/scalajslib/worker/ScalaJSWorkerImpl.scala @@ -34,6 +34,7 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi { esFeatures: ESFeatures, moduleSplitStyle: ModuleSplitStyle, outputPatterns: OutputPatterns, + minify: Boolean, dest: File ) private def minorIsGreaterThanOrEqual(number: Int) = ScalaJSVersions.current match { @@ -146,7 +147,11 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi { ) else withModuleSplitStyle - val linker = StandardImpl.clearableLinker(withOutputPatterns) + val withMinify = + if (minorIsGreaterThanOrEqual(16)) withOutputPatterns.withMinify(input.minify) + else withOutputPatterns + + val linker = StandardImpl.clearableLinker(withMinify) val irFileCacheCache = irFileCache.newCache (linker, irFileCacheCache) } @@ -163,7 +168,8 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi { moduleKind: ModuleKind, esFeatures: ESFeatures, moduleSplitStyle: ModuleSplitStyle, - outputPatterns: OutputPatterns + outputPatterns: OutputPatterns, + minify: Boolean ): Either[String, Report] = { // On Scala.js 1.2- we want to use the legacy mode either way since // the new mode is not supported and in tests we always use legacy = false @@ -177,6 +183,7 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi { esFeatures = esFeatures, moduleSplitStyle = moduleSplitStyle, outputPatterns = outputPatterns, + minify = minify, dest = dest )) val irContainersAndPathsFuture = PathIRContainer.fromClasspath(runClasspath)