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
Callbacks fully enable probably the most fascinating purpose of JavaScript backend, which is web programming. GHCJS has been around for quite some time now,
50
50
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/).
52
52
53
53
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
54
54
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
57
57
58
58
## Using JavaScript backend with existing JavaScript tools
59
59
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.
61
61
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.
62
62
63
63
### Optimizing and bundling
64
64
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.
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.
77
77
78
78
Nice! We reduced size of the js file from 1.8M to merely 396K. This is even smaller after compression:
79
79
```sh
@@ -197,8 +197,8 @@ import Data.Foldable
197
197
importData.TextqualifiedasT
198
198
```
199
199
200
-
We are going to use foreign import for initializing and destroying a button ripple effect.We will include this code in `js-sources` pragmaof 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` fieldof the package's cabal file:
201
+
```cabal
202
202
library
203
203
(..)
204
204
js-sources: src/Button.js
@@ -452,7 +452,7 @@ module.exports = {
452
452
}
453
453
```
454
454
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,
456
456
and we can safely ship our foreign code with imports to our users (provided they do install our `npm` dependencies).
457
457
458
458
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
464
464
465
465
What's next? There is still a lot to do in terms of code size & performance, as well as integration with other tools:
466
466
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.
468
468
Notably that would enable i.e. conditional compilation of traces along the lines of `#ifdef XXX<put-trace>` in foreign library code and `ifflag(trace-flag) js-options:-optJSP-DXXX` in cabal file.
469
469
- Low-hanging fruits like [adding multiline strings support to inline foreign imports](https://gitlab.haskell.org/ghc/ghc/-/issues/25633).
470
470
- 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
477
477
478
478
## Thanks!
479
479
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