Skip to content

Commit 0f649d6

Browse files
committed
Integrate review suggestions
1 parent ee59bf9 commit 0f649d6

File tree

1 file changed

+9
-9
lines changed
  • content/case-study-foreign-integration-js-browser

1 file changed

+9
-9
lines changed

content/case-study-foreign-integration-js-browser/index.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ https://github.com/user-attachments/assets/ceb86903-d136-4821-8e2d-de2e433889a5
4848

4949
Callbacks fully enable probably the most fascinating purpose of JavaScript backend, which is web programming. GHCJS has been around for quite some time now,
5050
however it is both outdated (being a GHC fork requiring separate maintenance; currently stuck on 8.10) and cumbersome to use (often necessitating a separate setup, typically through Nix). In one of my previous companies, while evaluating potential options for rewriting the frontend, I decided to use PureScript. It was close enough to Haskell and very easy to set up - it can be installed directly through `npm`, has its own `stack`-like package manager `spago` with a suite of existing bundler plugins, and a blazing fast language server.
51-
During this journey I was using [purescript-halogen](https://github.com/purescript-halogen/purescript-halogen) library - a typesafe, declarative VDOM framework based on the Elm Architecture.
51+
During this journey I was using [purescript-halogen](https://github.com/purescript-halogen/purescript-halogen) library - a typesafe, declarative VDOM framework based on [The Elm Architecture](https://guide.elm-lang.org/architecture/).
5252

5353
However, with all the joy that the Haskell-like web programming brought me, I couldn't shake the feeling that there is a room for improvement. From the small things that are
5454
always annoying in polyglot stacks (like FE-BE JSON encoding discrepancies or lack of code sharing), to sometimes very illegible `purs` compiler error messages and of course lack of a lot of language features. This is not my intention to criticize - for a language this small I was amazed by the number and quality of existing tools and frameworks and a plenty of documentation; the overall experience exceeded my expectations by far. I would still recommend PureScript to anyone that wants a lightweight, easy to setup web language with strong type system.
@@ -57,12 +57,12 @@ However the mentioned shortcomings were why I was closely following the developm
5757

5858
## Using JavaScript backend with existing JavaScript tools
5959

60-
Any, even the most complex and technically beautiful undertaking is worthless if its fruits are not usable.
60+
Yet, even the most complex and technically beautiful undertaking is worthless if its fruits are not usable.
6161
One of the measures of such usability in this case is interoperability with the JavaScript ecosystem - existing libraries, bundlers, minifiers, as well of the performance (size and speed) of the generated code.
6262

6363
### Optimizing and bundling
6464

65-
Currently, `google-closure-compiler` is supported for minification of the bundle (see [previous blog](https://blog.haskell.org/report-of-js-code-minification/)). Let's try it.
65+
Currently, `google-closure-compiler` is supported for minification of the bundle (see the blog post on [JS code minification](https://blog.haskell.org/report-of-js-code-minification/)). Let's try it.
6666

6767
```sh
6868
mateusz@m12844:~/personal/halogen-blog$ ./run_example 1
@@ -73,7 +73,7 @@ Output size: 396K
7373
```
7474

7575
Notice we have to call `google-closure-compiler` with two input files: first is the `all.js` package generated by the compiler after bundling our library with all dependencies,
76-
GHC rts and emscripten rts files; second, is the `all.externs.js` file that declares external variables for the minifier. Its purpose is twofold - first it instructs the compiler those are declared elsewhere and it should not fail with undeclared variable; second, it prohibits mangling those identifiers during minification.
76+
GHC's RTS and emscripten RTS files; second, is the `all.externs.js` file that declares external variables for the minifier. Its purpose is twofold - It informs the compiler that those variables are declared elsewhere, as not to fail with an "undeclared variable" error, and it prevents the mangling of those identifiers during minification.
7777

7878
Nice! We reduced size of the js file from 1.8M to merely 396K. This is even smaller after compression:
7979
```sh
@@ -197,8 +197,8 @@ import Data.Foldable
197197
import Data.Text qualified as T
198198
```
199199

200-
We are going to use foreign import for initializing and destroying a button ripple effect. We will include this code in `js-sources` pragma of the cabalfile:
201-
```yaml
200+
We are going to use foreign import for initializing and destroying a button ripple effect. We will include this code in `js-sources` field of the package's cabal file:
201+
```cabal
202202
library
203203
(..)
204204
js-sources: src/Button.js
@@ -452,7 +452,7 @@ module.exports = {
452452
}
453453
```
454454
455-
And voila! It all works as before. The uncompressed bundle size is slightly bigger (844 KiB vs 803 KiB with `google-closure-compiler`) however we don't need any more workarounds,
455+
And voilà! It all works as before. The uncompressed bundle size is slightly bigger (844 KiB vs 803 KiB with `google-closure-compiler`) however we don't need any more workarounds,
456456
and we can safely ship our foreign code with imports to our users (provided they do install our `npm` dependencies).
457457
458458
A library with richer functionality is available [here](https://github.com/Swordlash/haskell-halogen-material).
@@ -464,7 +464,7 @@ The above article shows how to use the JavaScript backend effectively and integr
464464
465465
What's next? There is still a lot to do in terms of code size & performance, as well as integration with other tools:
466466
467-
- This cabal [PR](https://github.com/haskell/cabal/pull/10722) adds a new pragma `js-options` that allows to pass custom flags to `js-sources` preprocessor.
467+
- This cabal [PR](https://github.com/haskell/cabal/pull/10722) adds a new field, `js-options`, that allows to pass custom flags to `js-sources` preprocessor.
468468
Notably that would enable i.e. conditional compilation of traces along the lines of `#ifdef XXX <put-trace>` in foreign library code and `if flag(trace-flag) js-options: -optJSP-DXXX` in cabal file.
469469
- Low-hanging fruits like [adding multiline strings support to inline foreign imports](https://gitlab.haskell.org/ghc/ghc/-/issues/25633).
470470
- Bigger [integration efforts](https://gitlab.haskell.org/ghc/ghc/-/issues/25469) with npm.
@@ -477,4 +477,4 @@ Personally, I'm going to continue maintaining and developing the `haskell-haloge
477477
478478
## Thanks!
479479
480-
Many thanks to [Serge S. Gulin](https://github.com/GulinSS) for his help and discussions on Matrix channel, and to [Hécate Kleidukos](https://gitlab.haskell.org/Kleidukos) for inviting me to write this blog. I want also to thank [Sylvain Henry](https://gitlab.haskell.org/hsyl20) and [Luite Stegeman](https://gitlab.haskell.org/luite) for our mail and PR discussions, and whole IOG GHC Engineering team for the joint effort of releasing the JS backend. Awesome work!
480+
Many thanks to [Serge S. Gulin](https://github.com/GulinSS) for his help and discussions on Matrix channel, and to [Hécate Kleidukos](https://gitlab.haskell.org/Kleidukos) for inviting me to write this blog post. I want also to thank [Sylvain Henry](https://gitlab.haskell.org/hsyl20) and [Luite Stegeman](https://gitlab.haskell.org/luite) for our mail and PR discussions, and whole IOG GHC Engineering team for the joint effort of releasing the JS backend. Awesome work!

0 commit comments

Comments
 (0)