diff --git a/content/guides/quick-start.adoc b/content/guides/quick-start.adoc index 9d2660e7..33dffaad 100644 --- a/content/guides/quick-start.adoc +++ b/content/guides/quick-start.adoc @@ -15,7 +15,7 @@ part of this tutorial are a web browser and an installation of https://clojure.org/guides/getting_started[Clojure]. On Windows you will need https://www.oracle.com/java/technologies/javase/jdk21-archive-downloads.html[Java 21] and the -https://github.com/clojure/clojurescript/releases/download/r1.12.42/cljs.jar[standalone +https://github.com/clojure/clojurescript/releases/download/r1.12.116/cljs.jar[standalone ClojureScript JAR]. Note that the requirement of a web browser excludes headless environments, and we then recommend skimming to the Node.js portion of the tutorial. @@ -45,7 +45,7 @@ If you are on macOS or Linux your `deps.edn` file should contain the following: [source,clojure] ---- -{:deps {org.clojure/clojurescript {:mvn/version "1.12.42"}}} +{:deps {org.clojure/clojurescript {:mvn/version "1.12.116"}}} ---- In your favorite text editor edit the `src/hello_world/core.cljs` to @@ -308,7 +308,7 @@ Modify your `deps.edn` file: [source,clojure] ---- -{:deps {org.clojure/clojurescript {:mvn/version "1.12.42"} +{:deps {org.clojure/clojurescript {:mvn/version "1.12.116"} cljsjs/react-dom {:mvn/version "16.2.0-3"}}} ---- diff --git a/content/news/2025-11-24-release.adoc b/content/news/2025-11-24-release.adoc new file mode 100644 index 00000000..1988eb2c --- /dev/null +++ b/content/news/2025-11-24-release.adoc @@ -0,0 +1,106 @@ += 1.12.116 Release +ClojureScript Team +2025-11-24 12:00:00 +:jbake-type: post + +ifdef::env-github,env-browser[:outfilesuffix: .adoc] + +We're happy to announce a new release of ClojureScript. If you're an existing +user of ClojureScript please read over the following release notes carefully. + +This a major feature release with a significant number of enhancements. Before diving in, note that Google Closure Compiler has been updated to `v20250820`. + +For a complete list of fixes, changes, and enhancements to +ClojureScript see +https://github.com/clojure/clojurescript/blob/master/changes.md#1.12.116[here] + +## ECMAScript 2016 Language Specification + +ClojureScript, outside of a few small exceptions, has generated https://www.ecma-international.org/wp-content/uploads/ECMA-262_3rd_edition_december_1999.pdf[ECMAScript 3rd edition (1999)] compatible code. We avoided any newer constructs because historically they offered undesirable outcomes: increased code size due to polyfilling and decreased performance due to yet unoptimized paths in JavaScript virtual machines. + +Nine years have passed since the https://262.ecma-international.org/7.0/[ECMAScript 2016] was released and the major JavaScript virtual machines now offer great performance across the specification. While language constructs like `let` surprisingly https://vincentrolfs.dev/blog/ts-var[fail] to deliver much value for ClojureScript, features like https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy[Proxy] and https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect[Reflect] solve real problems at low prices. + +ClojureScript will use ES2016 moving forward where it delivers value and performance benefits. + +## `cljs.proxy` + +ClojureScript's interop story, while strong, was never as complete as Clojure on the JVM due to the lack of common interfaces, i.e. `java.util.Map`. ClojureScript values had to be marshalled to JavaScript values via `clj->js`, generating a significant amount of computational waste. + +Enter `cljs.proxy`. This new experimental namespace uses ES2016 Proxy to lazily bridge ClojureScript maps and vectors to JavaScript. JavaScript code can now see ClojureScript maps as objects and vectors as array-likes. `cljs.proxy` was carefully written to add very little overhead for object access patterns over a direct `-lookup` call. + +[source,clojure] +``` +(require '[cljs.proxy :refer [builder]] + '[goog.object :as gobj]) + +(def proxy (builder)) +(def proxied-map (proxy {:foo 1 :bar 2})) + +(gobj/get proxied-map "foo") ;; => 1 +``` + +This feature needs commmunity tire kicking, but we believe this approach offers sizeable benefits over existing practice. + +## Clojure Method Values + +ClojureScript now supports https://clojure.org/reference/java_interop#methodvalues[Clojure 1.12 method value] syntax as well as static field syntax. `PersistentVector/EMPTY` works, but also `String/.toUpperCase` and `Object/new`. Thanks to ES2016 `Reflect` we do not need manual `:param-tags` for disambiguation, and it covers the many cases where type information will simply not be available to the ClojureScript compiler. + +[source,clojure] +``` +(refer-global :only '[String]) +(map String/.toUpperCase ["foo" "bar" "baz"]) ;; => ("FOO" "BAR" "BAZ") +``` + +## `:refer-global` and `:require-global` + +`:refer-global` lets a namespace declare what definitions from the global environment should be available in the current namespace without `js` prefixing. It can be combined with `:rename`. + +[source,clojure] +``` +(refer-global :only '[Date] :rename '{Date my-date}) +(my-date/new) +``` + +`:require-global` lets you use JavaScript librares that you included as script tags on the page without any further build configuration. JavaScript build tooling brings a considerable amount of additional complexity and now https://helixguard.ai/blog/malicious-sha1hulud-2025-11-24[risk] and there is a growing population of developers moving to technologies that eliminate it. https://hypermedia.systems[Hypermedia] frameworks in particular have returned to more innocent times where at most you needed exactly one JavaScript dependency to be productive. + +ClojureScript now supports hypermedia-centric development approaches where you might have only one dependency and you are using ClojureScript / Google Closure Library primarily to build https://developer.mozilla.org/en-US/docs/Web/API/Web_components[Web Components] and want to sidestep the JavaScript dependency churn and tooling burden. + +[source,clojure] +``` +(require-global '[Idiomorph :as idio]) +(idio/morph ...) +``` + +## `:lite-mode` and `:elide-to-string` + +Not all programs we might want to write require ambition. There are light scripting use cases, say for a blog, that are not currently well served by ClojureScript. + +How to break the 20K compressed wall? After some time in the hammock, we decided to travel back to 2011 and resurface the original data structures that Rich Hickey and co. included in the standard library. While not as efficient, they are decoupled and smaller. Setting the new `:lite-mode` compiler flag to `true` makes the ClojureScript compiler emit calls to the older constructors and tree-shaking can eliminate the heavier persistent implementations. + +Printing is another blocker for very compact artifacts. Many simpler programs will never recursively print EDN. The `:elide-to-string` compiler flag removes the `toString` implementations leading to improved tree-shaking. + +Combining these two experimental flags cuts the initial artifact size by two thirds. It's important to understand these flags cannot be used to make large ClojureScript programs smaller - once you have enough dependencies or rely on enough features, the savings are a wash. + +But for people who know that they want to build something very compact, yet not give up on useful bits of `cljs.core` and Google Closure Library, these two new flags provide more control. + +The following program is 6K Brotli compressed with `:lite-mode` and `:elide-to-string`. + +[source,clojure] +``` +(->> (map inc (range 10)) + (filter even?) + (partition 2) + (drop 1) + (mapcat identity) + into-array) +``` + +We're excited to hear feedback about all these new features! + +## Contributors + +Thanks to all of the community members who contributed to ClojureScript 1.12.116 + +* Michel Borkent +* Paula Gearon +* Roman Liutikov diff --git a/content/reference/compiler-options.adoc b/content/reference/compiler-options.adoc index c9d28db5..af749cf5 100644 --- a/content/reference/compiler-options.adoc +++ b/content/reference/compiler-options.adoc @@ -691,6 +691,18 @@ Whether to elide `use strict` statements in JavaScript output. Defaults to `true :elide-strict false ---- +[[elide-to-string]] +=== :elide-to-string + +EXPERIMENTAL. Elide `.toString` implementations from ClojueScript +collections. Intended to be paired with `:lite-mode`. Useful only for +simpler programs. + +[source,clojure] +---- +:elide-to-string true +---- + [[fingerprint]] === :fingerprint @@ -804,6 +816,19 @@ Defaults to the empty vector `[]` "src/org/example/example.js"] ---- +[[lite-mode]] +=== :lite-mode + +EXPERIMENTAL. Clojure data literals will emit constructor calls to +lighter weight copy-on-write data structures. Results in smaller +advanced compiled artifacts. Useful only for simpler programs. See +also `:elide-to-string`. + +[source,clojure] +---- +:lite-mode true +---- + [[nodejs-rt]] === :nodejs-rt