Skip to content

Announcing Scala.js 1.16.0. #631

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ colors: #in hex code if not noted else

### VERSIONS ###
versions:
scalaJS: 1.15.0
scalaJS: 1.16.0
scalaJSBinary: 1
scalaJS06x: 0.6.33
scalaJS06xBinary: 0.6
Expand Down
1 change: 1 addition & 0 deletions _data/library/versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@
- 1.11.0
- 1.12.0
- 1.13.0
- 1.16.0
105 changes: 105 additions & 0 deletions _posts/news/2024-03-19-announcing-scalajs-1.16.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
layout: post
title: Announcing Scala.js 1.16.0
category: news
tags: [releases]
permalink: /news/2024/03/19/announcing-scalajs-1.16.0/
---


We are excited to announce the release of Scala.js 1.16.0!

The biggest highlight of this release is that we added a Scala.js-specific minifier.
When combined with a general-purpose JavaScript minifier, our minifier should bring most of the code size benefits of the Google Closure Compiler when the latter cannot be enabled, notably when emitting ECMAScript modules.

Scala.js 1.16.0 also upgrades by default to the standard library of Scala 2.12.19 and 2.13.13.

Read on for more details.

<!--more-->

## Getting started

If you are new to Scala.js, head over to [the tutorial]({{ BASE_PATH }}/tutorial/).

If you need help with anything related to Scala.js, you may find our community [in `#scala-js` on Discord](https://discord.com/invite/scala) and [on Stack Overflow](https://stackoverflow.com/questions/tagged/scala.js).

Bug reports can be filed [on GitHub](https://github.com/scala-js/scala-js/issues).

## Release notes

If upgrading from Scala.js 0.6.x, make sure to read [the release notes of Scala.js 1.0.0]({{ BASE_PATH }}/news/2020/02/25/announcing-scalajs-1.0.0/) first, as they contain a host of important information, including breaking changes.

This is a **minor** release:

* It is backward binary compatible with all earlier versions in the 1.x series: libraries compiled with 1.0.x through 1.15.x can be used with 1.16.0 without change.
* It is *not* forward binary compatible with 1.15.x: libraries compiled with 1.16.0 cannot be used with 1.15.x or earlier.
* It is *not* entirely backward source compatible: it is not guaranteed that a codebase will compile *as is* when upgrading from 1.15.x (in particular in the presence of `-Xfatal-warnings`).

As a reminder, libraries compiled with 0.6.x cannot be used with Scala.js 1.x; they must be republished with 1.x first.

## Enhancements with compatibility concerns

### Changes to the IR and linker APIs

For tooling authors who directly manipulate the IR and linker APIs, there have been some breaking changes in that area.
This is in line with our version policy for the linker APIs.

The most likely changes you may hit are:

* `FieldName` is now a composite of the defining `ClassName` and a `SimpleFieldName`.
* `StoreModule` has no parameter anymore; it implicitly applies to storing the `this` value of the enclosing module class.

## Enhancements

### Scala.js-specific minifier

In the `fullLink` mode, the Scala.js linker now includes dedicated code size optimizations.
They are mostly useful when the Google Closure Compiler is deactivated, which is the case by default when emitting ECMAScript modules.

The most important optimization is that it compresses all *property* names (fields and methods) of Scala classes.
It computes how frequently each one is used across the codebase, and assigns shorter names to the most frequent ones.

Renaming local and global variables and functions in this way is a standard feature of general-purpose JavaScript minifiers.
However, in general they cannot rename *properties* without breaking the semantics of JavaScript programs.
This is why Scala.js has leveraged Closure since the very first relase.
Closure's so-called "advanced optimizations" assume that the JavaScript program fits in a specific subset of semantics, which allows it to rename properties.

Unfortunately, the way Closure handles ES modules is incompatible with what we need.
Closure is therefore disabled when emitting ES modules from Scala.js.
This has resulted in large bundle sizes for users of ES modules.

Our minifier, which is aware of our types and of Scala.js semantics, fills that gap between Closure and general-purpose minifiers.
When combined with a general-purpose minifier such as the one bundled with Vite, the new optimizations bring code size around 15% bigger than Closure.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sjrd @gzm0 Thanks so much for this highly awaited feature.

Just curious, what are the reasons Closure can still be better than the new Scala.js optimizer and a good general-purpose minifier? Are there hopes for a better than Closure fullOpt ES modules optimizer solution?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because Closure had several engineers working on it for more than a decade, probably. ;)

More precisely, because we don't do everything that could be done. At least not yet. It's likely that we will get progressively closer, over time.

Contrast that with the previous status quo, which was several *times* bigger than the Closure output.

If, for some reason, the new optimizations cause issues in your case, you can disable them with

{% highlight scala %}
scalaJSLinkerConfig ~= { _.withMinify(false) }
{% endhighlight %}

Please let us know if you encounter any issue with this new mode.

### Other code size improvements

In addition to the minifier, Scala.js 1.16.0 generally produces smaller .js files.
This is the result of various code size optimizations that we apply in all configurations.

In particular, the optimizer now eagerly "dealiases" `val` fields of top-level objects if they are simple and if the object's initializer can be proven to be pure.

### Reduced memory consumption of the linker

The linker is generally optimized for *incremental* runs, which naturally requires to maintain a lot of caches in memory.
We have started work on reducing the memory consumption of the linker without compromising on speed.
This release already ships with the first installment of these improvements, reducing the memory footprint of the linker by 10%.
If interested, you can find out the details [in the relevant pull request #4917](https://github.com/scala-js/scala-js/pull/4917).

## Bug fixes

Among others, the following bugs have been fixed in 1.16.0:

* [#4929](https://github.com/scala-js/scala-js/issues/4929) Assertion failed: Trying to move a local VarDef after the super constructor call of a non-native JS class
* [#4949](https://github.com/scala-js/scala-js/issues/4949) Wrong pretty-printing of JS tree that *starts* with an object lit

You can find the full list [on GitHub](https://github.com/scala-js/scala-js/issues?q=is%3Aissue+milestone%3Av1.16.0+is%3Aclosed).
1 change: 1 addition & 0 deletions assets/badges/scalajs-1.16.0.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions doc/all-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ title: All previous versions of the Scala.js API

## All previous versions of the API

### Scala.js 1.16.0
* [1.16.0 scalajs-library]({{ site.production_url }}/api/scalajs-library/1.16.0/scala/scalajs/js/index.html)
* [1.16.0 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/1.16.0/)
* [1.16.0 scalajs-javalib-intf]({{ site.production_url }}/api/scalajs-javalib-intf/1.16.0/)
* [1.16.0 scalajs-ir]({{ site.production_url }}/api/scalajs-ir/1.16.0/org/scalajs/ir/index.html)
* [1.16.0 scalajs-linker-interface]({{ site.production_url }}/api/scalajs-linker-interface/1.16.0/org/scalajs/linker/interface/index.html) ([Scala.js version]({{ site.production_url }}/api/scalajs-linker-interface-js/1.16.0/org/scalajs/linker/interface/index.html))
* [1.16.0 scalajs-linker]({{ site.production_url }}/api/scalajs-linker/1.16.0/org/scalajs/linker/index.html) ([Scala.js version]({{ site.production_url }}/api/scalajs-linker-js/1.16.0/org/scalajs/linker/index.html))
* [1.16.0 scalajs-test-adapter]({{ site.production_url }}/api/scalajs-sbt-test-adapter/1.16.0/org/scalajs/testing/adapter/index.html)
* [1.16.0 sbt-scalajs]({{ site.production_url }}/api/sbt-scalajs/1.16.0/#org.scalajs.sbtplugin.package)

### Scala.js 1.15.0
* [1.15.0 scalajs-library]({{ site.production_url }}/api/scalajs-library/1.15.0/scala/scalajs/js/index.html)
* [1.15.0 scalajs-test-interface]({{ site.production_url }}/api/scalajs-test-interface/1.15.0/)
Expand Down
1 change: 1 addition & 0 deletions doc/internals/version-history.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ title: Version history

## Version history of Scala.js

- [1.16.0](/news/2024/03/19/announcing-scalajs-1.16.0/)
- [1.15.0](/news/2023/12/29/announcing-scalajs-1.15.0/)
- [1.14.0](/news/2023/09/25/announcing-scalajs-1.14.0/)
- [1.13.2](/news/2023/06/23/announcing-scalajs-1.13.2/)
Expand Down