You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ReScript is a soundly typed language with an optimizing compiler focused on the JS platform.
14
-
It's focused on type safety, performance and JS interop. It used to be called BuckleScript.
13
+
We are happy to announce ReScript 9.0!
15
14
16
-
[[email protected]](https://www.npmjs.com/package/bs-platform/v/9.0.0) is now available, you can try it via
15
+
ReScript is a strongly typed language that compiles to efficient, fully-typed and human-readable JavaScript. It comes with one of the fastest JS compiler toolchains available today and offers first class support for ReactJS development.
16
+
17
+
Use `npm` to install the newest [9.0.0 release](https://www.npmjs.com/package/bs-platform/v/9.0.0) with the following command:
The changes are listed[here](https://github.com/rescript-lang/rescript-compiler/blob/master/Changes.md#90).
23
+
In this post we will highlight the most notable changes. The full changelog for this release can be found[here](https://github.com/rescript-lang/rescript-compiler/blob/master/Changes.md#90).
23
24
24
-
We will go through some highlighted user visible changes.
25
+
## Compiler Improvements
25
26
26
-
### Customized light weight stdlib
27
+
### New External Stdlib Configuration
27
28
28
29
This is a long-awaited [feature request](https://github.com/rescript-lang/rescript-compiler/pull/2171).
29
30
30
-
Since this release, users can add such lines in bsconfig.json to make our compiler pakcage a dev dependency.
31
+
Our compiler comes with a set of stdlib modules (such as `Belt`, `Pervasives`, etc.) for core functionality. Compiled ReScript code relies on the JS runtime version of these stdlib modules.
32
+
33
+
In previous versions, users couldn't ship their compiled JS code without defining a `package.json` dependency on `bs-platform`. Whenever a ReScript developer wanted to publish a package just for pure JS consumption / lean container deployment, they were required to use a bundler to bundle up their library / stdlib code, which made things way more complex and harder to understand.
34
+
35
+
To fix this problem, we now publish our pre-compiled stdlib JS files as a separate npm package called [`@rescript/std`](https://www.npmjs.com/package/@rescript/std). Each new `bs-platform` release has a matching `@rescript/std` release for runtime compatibility.
36
+
37
+
We also introduced a new configuration within our `bsconfig.json` file to tell the compiler to use our pre-compiled package instead:
31
38
32
39
```json
33
-
"external-stdlib" : "@rescript/std"
40
+
{
41
+
/* ... */
42
+
"external-stdlib" : "@rescript/std"
43
+
}
44
+
```
45
+
46
+
With this configuration set, compiled JS code will now point to the defined `external-stdlib` path:
47
+
48
+
<CodeTablabels={["ReScript", "JavaScript"]}>
49
+
50
+
```res
51
+
Belt.Array.forEach([1,2,3], (num) => Js.log(num))
34
52
```
35
53
36
-
Our current compiler package is quite large since it ships both prebuilt compilers for 3 major platforms
37
-
and the standard library. With this configuration, the compiler will generate js files on top of `@rescript/std` so that
38
-
the compiler package is not needed after the JS files are generated. This is helpful if you want to export ReScript based
39
-
libraries to JS users while not asking JS users to install a large dependency.
54
+
```js
55
+
// Note the import path starting with "@rescript/std"
The JavaScript output above was compiled with an `es6` target, but will also work with `commonjs`.
40
71
41
-
Caveat: make sure the version of `@rescript/std` is the same as `bs-platform`, use this configuration only when the package size
42
-
is indeed a problem for you.
72
+
**Important:** When using this option, you need to make sure that the version number of `bs-platform` and `@rescript/std` matches with the same version number in your `package.json` file, otherwise you'll eventually run into runtime problems due to mismatching stdlib behavior!
43
73
44
-
### Zero-cost bundle size when adding ReScript
74
+
To prevent unnecessary complications, only use this feature when...
75
+
- You want to ship a library for JS / TS consumers without making them depend on `bs-platform`
76
+
- You can't depend on `bs-platform` due to toolchain size (docker containers, low-storage deployment devices, etc)
45
77
46
-
With each release, we keep a close eye on generating code that is optimized for tree-shaking.
47
-
We believe we reached a milestone that ReScript adds close to zero cost to your bundle-size.
48
-
Unlike many other programming languages compiled into JS, the bundled code is almost ReScript runtime free and
49
-
the generated library code fits the tree-shaking principle very well.
78
+
### Less Bundle Bloat when Adding ReScript
50
79
51
-
To demonstrate what we achieved, we made a [repo](https://github.com/bobzhang/zero-cost-rescript) so that
52
-
you can try it and see how good the bundled code is.
80
+
With each release, we keep a close eye on generating code that is optimized for tree-shaking. We believe we reached a milestone where ReScript doesn't add any bloat to your bundle-size (this is what we call our "zero-cost" philosophy).
53
81
82
+
Unlike many other compile-to-js languages, the bundled code is almost ReScript runtime free and the generated library code fits the tree-shaking principle very well.
54
83
55
-
### Improved code generation for pattern match
84
+
We made a small [demo repo](https://github.com/bobzhang/zero-cost-rescript) and added the precompiled JS bundles to demonstrate what we've achieved. Check it out!
56
85
57
-
We continue improving the quality of generated code in this release.
86
+
### Improved Code Generation for Pattern Matching
58
87
59
-
Take this [issue](https://github.com/rescript-lang/rescript-compiler/issues/4924) for example:
88
+
We fine-tuned our pattern matching engine to optimize the JS output even more. Here is an example of a pretty substantial optimization, based on [this issue](https://github.com/rescript-lang/rescript-compiler/issues/4924):
60
89
61
90
```res
91
+
type test =
92
+
| NoArg
93
+
| AnotherNoArg
94
+
| OtherArg(int)
95
+
62
96
let test = x =>
63
97
switch x {
64
98
| NoArg => true
65
99
| _ => false
66
100
}
67
101
```
68
102
69
-
It used to generate the following code:
103
+
Now let's have a look at how the JS output would look like in comparison to older versions:
104
+
105
+
<CodeTablabels={["9.0 Output", "8.4 Output" ]}>
106
+
107
+
```js
108
+
functiontest(x){
109
+
return x ===0
110
+
}
111
+
```
70
112
71
113
```js
72
114
functiontest(x) {
@@ -76,20 +118,18 @@ function test(x) {
76
118
returnfalse;
77
119
}
78
120
}
79
-
80
-
```
81
-
which now gets optimized to:
82
-
```js
83
-
functiontest(x){
84
-
return x ===0
85
-
}
86
121
```
87
122
88
-
This is possible because our optimizer will try to analyze several predicates and get rid of redundant ones.
89
-
More diffs can be found [here](https://github.com/rescript-lang/rescript-compiler/pull/4927/files?file-filters%5B%5D=.js).
90
123
91
-
Another important improvement is that we fixed the pattern match offset issue, which leads to the consequence, that magic numbers will not be generated for complex pattern matches anymore.
92
-
Below is a representative diff resulting from this cleanup:
124
+
</CodeTab>
125
+
126
+
As you can see, the 9.0 compiler removes all the unnecessary `typeof` checks!
127
+
128
+
This is possible because our optimizer will try to analyze several predicates and get rid of redundant ones. More diffs can be found [here](https://github.com/rescript-lang/rescript-compiler/pull/4927/files?file-filters%5B%5D=.js).
129
+
130
+
Another important improvement is that we fixed the pattern match offset issue, which lead to the consequence that magic numbers will not be generated for complex pattern matches anymore.
131
+
132
+
For those interested in the details, here is a representative diff resulting from this cleanup:
93
133
94
134
```diff
95
135
function is_space(param){
@@ -105,30 +145,97 @@ function is_space(param){
105
145
}
106
146
```
107
147
108
-
### Syntax changes
148
+
## Syntax Improvements
149
+
150
+
### `when` -> `if`
151
+
152
+
Starting from 9.0, [`when` clauses](/docs/manual/latest/pattern-matching-destructuring#when-clause) within a `switch` statement will automatically convert to the `if` keyword instead.
153
+
154
+
```res
155
+
switch person1 {
156
+
| Student({reportCard: {gpa}}) if gpa < 0.5 =>
157
+
Js.log("What's happening")
158
+
| _ => () // do nothing
159
+
}
160
+
```
161
+
162
+
The syntax parser and printer will automatically take care of older code, so no action required for existing codebases. The `when` keyword is deprecated.
163
+
109
164
110
-
We introduced two minor tweaks for the concrete syntax.
165
+
### Cleaner Polyvariant Syntax
111
166
112
-
- It is now recommended to use `if` instead of `when` in pattern match guards
167
+
Polyvariants with invalid identifier names (e.g. names including hypens `-`), don't require any special escaping syntax anymore:
168
+
169
+
<CodeTablabels={["New (9.0)", "Old (8.4)"]}>
170
+
171
+
```res
172
+
type animation = [ #"ease-in" | #"ease-out" ]
173
+
```
113
174
114
175
```res
115
-
switch expr {
116
-
| pat if predicate => // was: pat when predicate
176
+
type animation = [ #\"ease-in" | #\"ease-out" ]
177
+
```
178
+
179
+
</CodeTab>
180
+
181
+
We introduced this change to allow easier interop with existing JS string enums. In pure ReScript code, we'd still recommend our users to stick with valid identifier names instead (e.g. `easeIn` instead of `ease-in`).
182
+
183
+
184
+
## Breaking Changes
185
+
186
+
This release comes with a minor breaking change that shouldn't have much impact on the upgrade of existing codebases.
187
+
188
+
### Nested Records within Objects
189
+
190
+
Previously, if you wrote `{"user": {age: 10}}`, the inner record was interpreted as an object instead of a record (`{"user": {"age": 10}}`); this is a byproduct of some internal interop transformation details; with the ReScript syntax, this went from understandable to confusing, so we're changing it so that the inner record is indeed now treated as a record. This is an obvious fix, but a breaking change if you were accidentally leveraging that nested record as object.
191
+
192
+
Here is a code example before and after the change. Note how the `user` record secretly turns into a ReScipt object in the previous version:
193
+
194
+
<CodeTablabels={["9.0 Example", "8.4 Example" ]}>
195
+
196
+
```res
197
+
type user = {
198
+
age: int
117
199
}
200
+
201
+
let data = {
202
+
"user": {
203
+
age: 1
204
+
}
205
+
}
206
+
207
+
// This is the way: `age` should be usable via record accessor
208
+
let age = data["user"].age
118
209
```
119
210
120
-
`when` is still supported but it will be deprecated in the future.
211
+
```res
212
+
type user = {
213
+
age: int
214
+
}
215
+
216
+
let data = {
217
+
"user": {
218
+
age: 1
219
+
}
220
+
}
221
+
222
+
// This was the problem: The record implicitly turned
223
+
// into a ReScript object (which is confusing)
224
+
let age = data["user"]["age"]
225
+
```
226
+
227
+
</CodeTab>
228
+
229
+
More discussions on this change can be found [here](https://forum.rescript-lang.org/t/fixing-the-semantics-of-nested-objects-breaking-changes/976).
230
+
121
231
122
-
- explicit nested object literal syntax
232
+
## Closing Note
123
233
234
+
We only highlighted a few user-facing features, but there are also some pretty interesting internal changes happening right now.
124
235
125
-
`{ "keya": { keyb: 3 } }` used to be interpreted as `{ "keya": { "keyb": 3 } } `, such implicity makes
126
-
us not able to embed regular records inside JS object literals. With this release,
127
-
JS object literals have to be written explicitly and `{ "keya": { keyb: 3 } }` will be interpreted as a regular
128
-
record inside a JS object literal. More discussions can be found [here](https://forum.rescript-lang.org/t/fixing-the-semantics-of-nested-objects-breaking-changes/976).
236
+
For example, we are tinkering with the idea on using WASM to replace Camlp4, and we are also working on a generalized visitor pattern that doesn't require objects.
129
237
238
+
We will discuss these topics in a separate development post, but we are already excited about the new possibilities this will bring within the compiler toolchain.
130
239
131
-
There are also some pretty interesting internal changes in this release.
132
-
For example, using WASM to replace Camlp4 and a generalized visitor pattern without using objects, which we will discuss in a separate post.
0 commit comments