diff --git a/_blogposts/2025-11-17-announcing-rescript-12.mdx b/_blogposts/2025-11-17-announcing-rescript-12.mdx new file mode 100644 index 000000000..b9750794b --- /dev/null +++ b/_blogposts/2025-11-17-announcing-rescript-12.mdx @@ -0,0 +1,221 @@ +--- +author: rescript-team +date: "2025-11-17" +previewImg: /static/blog/rescript-12-reforging-build-system.webp +articleImg: /static/blog/rescript-12-reforging-build-system.webp +badge: release +title: "Announcing ReScript 12" +description: | + ReScript 12 arrives with a redesigned build toolchain, a modular runtime, and a wave of ergonomic language features. +--- + +## Introduction + +ReScript 12 is now available. +This release completes the multi-year effort to separate the compiler from legacy constraints, refreshes critical developer workflows, and delivers a modern feature set that is grounded in real-world feedback. +The headline upgrades include a rewritten build system, a standalone runtime package, unified operator support, JSX preserve mode, and numerous syntax improvements that make ReScript code easier to write and maintain. + +Teams upgrading from ReScript 11 should review the highlighted breaking changes and schedule time for migration. +The new tooling provides focused commands, better diagnostics, and smaller downloads, while the language additions flatten sharp edges that many of you encountered in larger codebases. + +## Breaking Changes + +### Build system redesign + +ReScript 12 ships with the new build system introduced earlier this month in the [Reforging the Build System](./2025-11-04-reforging-build-system.mdx) preview. +The tooling now relies on a modern architecture that tracks dependencies more precisely, avoids unnecessary recompilations, and integrates with incremental workflows. +The old build system remains available through `rescript-legacy`, but active projects should switch to the new commands to benefit from faster feedback loops and clearer output. + +### Runtime package split + +The compiler no longer embeds runtime modules. +Instead, the runtime lives in the dedicated `@rescript/runtime` npm package, which contains Belt, Stdlib, Js, primitive modules, and supporting artifacts compiled in both ES Module and CommonJS formats. +Earlier versions bundled these files inside the `rescript` package and exposed an optional `@rescript/std` helper. +ReScript 12 removes `@rescript/std`; install `rescript` and `@rescript/runtime` together to keep projects in sync. +Projects that previously published custom runtime shims should revisit their setup to ensure the new package structure remains discoverable. + +### Updated bitwise operator surface + +Legacy OCaml-style bitwise functions such as `land`, `lor`, and `lsl` are deprecated. +They continue to work in v12 with warnings but will be removed in v13. +ReScript now prefers unified operator syntax: `&&&`, `|||`, `^^^`, and `~~~` cover AND, OR, XOR, and NOT for both `int` and `bigint`. + +### API naming alignment + +APIs that previously ended with `Exn` now end with `OrThrow`. +Examples include `Option.getOrThrow`, `List.headOrThrow`, `BigInt.fromStringOrThrow`, and `JSON.parseOrThrow`. +The change clarifies that these functions throw JavaScript errors, aligning the naming with the language’s semantics. +The deprecated `*Exn` variants remain available in v12 to ease the transition, and the codemod bundled with the migration tool can perform a mechanical rename. +Be aware that `Result.getOrThrow` now throws a JavaScript `Error`, so update any exception handling logic that depended on OCaml exception names. + +### JSX version requirement + +JSX v3 has been removed. +ReScript 12 requires JSX v4 configuration in `rescript.json`, using the `"jsx": { "version": 4 }` schema. +ReScript React projects must update their configuration before moving to v12. +Projects attempting to compile with v3 will receive an explicit error, ensuring that your codebase uses the current transform and associated tooling. + +### Deprecation of OCaml compatibility helpers + +The standard library continues its shift away from OCaml-specific aliases. +Functions such as `succ`, `pred`, `abs_float`, `string_of_int`, `fst`, `raise`, and the `char` type are now deprecated. +The recommended replacements are the JavaScript-aligned counterparts in `Int`, `Float`, `Bool`, `Pair`, and related modules, alongside the `throw` keyword for exceptions. +References to the OCaml composition operators (`|>`, `@@`) now warn and will be removed in v13; the ReScript pipe operator `->` replaces them. +The migration tool highlights deprecated usage, and incremental cleanups are encouraged so your codebase is ready before the next major release. + +## New features + +### Unified operators + +ReScript 12 finalizes the unified operator work introduced [earlier this year](./2025-04-11-introducing-unified-operators.mdx). +Arithmetic, comparison, and bitwise operators now behave consistently across `int` and `bigint`, allowing the compiler to infer the correct specialization from the left operand. + +### Expanded bitwise capabilities + +In addition to deprecating the OCaml-style helpers, ReScript 12 adds new operator spellings. +JavaScript-style bitwise operators (`&`, `|`, `^`, `~`) and shift operators (`<<`, `>>`, `>>>`) are first-class citizens that compile directly to their JavaScript equivalents. +Combined with the unified F#-style operators, developers can select the syntax that best fits their code policies without sacrificing performance or type safety. + +### Dict literals and pattern matching + +The language now supports dictionary literals (`dict{"foo": "bar"}`) that compile to plain JavaScript objects. +Dict literals work with variables, multi-line formatting, and optional entries, and they drastically reduce the boilerplate compared to `Dict.fromArray`. +Pattern matching also understands dicts, enabling concise destructuring of JSON payloads and configuration objects. +The compiler emits the same optimized JavaScript while preserving ReScript's type guarantees. + +```rescript +let user = dict{"name": "Ada", "role": "engineer"} + +switch user { +| dict{"name": name, "role": role} => Console.log2(name, role) +| _ => Console.log("missing user metadata") +} +``` + +### Nested and inline record types + +Nested record definitions and inline record payloads remove the need for auxiliary type declarations. +You can define optional nested structures directly inside records, or attach record payloads to variant constructors without creating standalone types. +The feature supports mutable fields, type parameters, and record spreading, providing better locality for complex domain models with no runtime penalty. + +```rescript +type profile = { + name: string, + extra?: { + location: {city: string, country: string}, + mutable note: option, + }, +} +``` + +### Variant pattern spreads + +Pattern spreads (`| ...SomeVariant as value =>`) allow you to reuse handlers for entire subsets of constructors. +When a variant extends another variant through spreads, you can match the shared constructors in one branch and delegate to helper functions, keeping exhaustive matches concise even as the hierarchy grows. +The compiler enforces subtype relationships and ensures that runtime representations remain compatible. + +```rescript +type base = Start | Stop | Pause +type extended = | ...base | Resume + +let handle = (event: extended) => + switch event { + | ...base as core => Console.log2("base", core) + | Resume => Console.log("resuming") + } +``` + +### JSX preserve mode + +Projects that rely on downstream JSX tooling can enable [preserve mode](../docs/manual/v12.0.0/jsx#preserve-mode) via `"jsx": { "version": 4, "preserve": true }`. +The compiler will emit JSX syntax directly instead of transforming elements to `react/jsx-runtime` calls, allowing bundlers such as ESBuild, SWC, or Babel to apply their own transforms. +This mode keeps JSX readable in the output, retains spread props, and maintains compatibility with React Server Components. +React classic mode is no longer supported, so projects must use the JSX v4 transform regardless of preserve mode settings. +When preserve mode is disabled, the compiler continues to output the optimized runtime calls you are accustomed to. + +### Function-level directives + +The new `@directive` attribute emits JavaScript directive strings at the top of generated functions. +Use it to mark server actions with `'use server'`, memoized handlers with `'use memo'`, or any other directive that your framework requires. +The attribute works on synchronous and asynchronous functions, supports labeled parameters, and removes the need for `%raw` blocks. +Combined with JSX preserve mode, this enables clean integration with [React Server Components](../docs/react/latest/server-components.mdx) and other directive-based runtimes. + +### Regex literals + +ReScript now understands JavaScript-style regular expression literals (`/pattern/flags`). +They are full equivalents of `%re` expressions, supporting all ECMAScript flags, Unicode character classes, and sticky searches. +The literals compile directly to JavaScript regex objects, so existing APIs like `RegExp.exec` and `RegExp.test` continue to work exactly as before, but with clearer syntax and better editor support. + +```rescript +let emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/i + +if emailPattern->RegExp.test("contact@rescript-lang.org") { + Console.log("Valid email") +} + +switch emailPattern->RegExp.exec("invalid") { +| Some(match) => Console.log(match->RegExp.Result.fullMatch) +| None => Console.log("No match") +} +``` + +### Experimental `let?` syntax + +This release introduces an experimental `let?` syntax for zero-cost unwrapping of `option` and `result` values. +The syntax remains behind an opt-in flag while the community evaluates its ergonomics. +Refer to the forum discussion at https://forum.rescript-lang.org/t/proposing-new-syntax-for-zero-cost-unwrapping-options-results/6227 for the current proposal, examples, and feedback guidelines. + +```rescript +type user = { + address?: { + city?: string, + }, +} + +let userCity = (user: user): option => { + let? Some(address) = user.address + let? Some(city) = address.city + Some(city) +} +``` + +## Platform and tooling improvements + +### Cleaner JavaScript output + +The printer now emits compact arrow functions and streamlines anonymous function expressions, making generated JavaScript easier to audit. +These changes preserve semantics while aligning the output with modern JavaScript style. + +### Internal architecture updates + +The compiler cleans up its internal abstract syntax tree, removes unused OCaml-era nodes, and tracks async and partial function metadata directly on AST nodes. +These changes simplify future feature work and reduce maintenance overhead. + +### ESM-first distribution + +The `rescript` npm package declares `"type": "module"` and ships ESM code across the CLI. +Import statements replace CommonJS `require` usage, improving compatibility with contemporary bundlers and enabling better tree-shaking. + +### Platform-specific binaries + +Installer footprints shrink thanks to platform-specific binary packages such as `@rescript/darwin-arm64`, `@rescript/linux-x64`, and `@rescript/win32-x64`. +npm installs only the binary that matches your operating system and architecture, delivering substantially faster installs and smaller cache footprints for CI pipelines. +The primary `rescript` package loads the appropriate binary at runtime and surfaces clear error messages if the matching package is missing. + +## Acknowledgments + +![ReScript core team during the 2025 Vienna retreat](/static/blog/rescript-retreat-2025.webp) + +Thank you to every contributor, tester, and partner who helped shape ReScript 12. +The core team gathered in Vienna earlier this year to map out this release, and your feedback guided every decision. +Community pull requests, bug reports, and experiments across the ecosystem gave us the confidence to complete large refactors and deprecations. + +## Reach out + +Join the conversation on the community forum if you have migration questions or want to share what you build with ReScript 12. +Businesses that rely on ReScript can contact the association at https://rescript-association.org/contact to explore support, sponsorship, or collaboration. +Funding enables the team to ship features like the new runtime architecture faster, so every contribution, financial or otherwise, helps the language move forward. + +We look forward to hearing what you create with ReScript 12. + +![The ReScript team at the 2025 retreat in Vienna](/static/blog/rescript-team-2025.webp) diff --git a/public/static/blog/rescript-retreat-2025.webp b/public/static/blog/rescript-retreat-2025.webp new file mode 100644 index 000000000..cc02c7350 Binary files /dev/null and b/public/static/blog/rescript-retreat-2025.webp differ diff --git a/public/static/blog/rescript-team-2025.webp b/public/static/blog/rescript-team-2025.webp new file mode 100644 index 000000000..4691456bd Binary files /dev/null and b/public/static/blog/rescript-team-2025.webp differ