Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 79 additions & 15 deletions migration-guides/0.15-Migration-Guide.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# PureScript 0.15 Migration Guide

## ES modules migration guide
## Tooling

- `purescript-psa` does not need to be updated.
- `spago` needs to be updated to `vT.B.D`.
- `pulp` needs to be updated to `v16.0.0`.
- `purs-tidy` needs to be updated to `vT.B.D`.

## ES modules migration guide

### tl;dr

Expand All @@ -10,7 +17,7 @@

### A little bit of background

In April 2021 the Node.js LTS version 10 reached end-of-life, which was the last version that did not yet support ES modules (ESM). This means, that all Node.js LTS and current versions support ES modules. And since all major browsers support ESM already since a long time, there is no need anymore in the JS ecosystem to support Common JS (CJS) and the community is advocating to [drop CJS support](https://github.com/sindresorhus/meta/discussions/15), which kinda makes sense. The community is following suit and is dropping its support for CJS, some notable examples are [remark](https://github.com/remarkjs/remark/tree/main/packages/remark#install), [`node-fetch`](https://github.com/node-fetch/node-fetch#commonjs) and [`framer-motion`](https://github.com/framer/motion) amongst many others.
In April 2021 the Node.js LTS version 10 reached end-of-life, which was the last version that did not yet support ES modules (ESM). This means, that all Node.js LTS and current versions support ES modules. And since all major browsers support ESM already since a long time, there is no need anymore in the JS ecosystem to support Common JS (CJS) and the community is advocating to [drop CJS support](https://github.com/sindresorhus/meta/discussions/15), which kinda makes sense. The community is following suit and is dropping its support for CJS, some notable examples are [remark](https://github.com/remarkjs/remark/tree/main/packages/remark#install), [`node-fetch`](https://github.com/node-fetch/node-fetch#commonjs) and [`framer-motion`](https://github.com/framer/motion) amongst many others.

What does that mean for Purescript v0.14? Well, a little bit of bad news, because Purescript v0.14 only supports CJS. Fortunately, there has been a [long-standing PR](https://github.com/purescript/purescript/pull/3791) to support ES modules in Purescript. So time to get this over the finish line and get ESM and

Expand All @@ -32,13 +39,13 @@ However, this has a couple of implications that will need you to migrate your co


* v0.15 drops support for Node.js versions < 12

This is just the logical consequence of Node.js versions < 12 having reached EOL and not supporting ESM. More on this here:

[How can I use Purescript on Node.js?](#how-can-i-update-cjs-to-esm)

* v0.15 drops `purs bundle` and relies on an external bundlers

Yes, you heard right. The Purescript compiler no longer comes with a built-in `bundle` command. `purs bundle` was already broken in a couple of ways, didn't do a great job on bundle size, and was basically unmaintained. Updating `purs bundle` to ESM would have required a considerable amount of work, taking time away from the compiler team to work on more urgent matters in the compiler.

Therefore, v0.15 relies on an external bundler like `esbuild`, `webpack` or `parcel`. And that is good news because these tools are used industry-wide and do a much better job on bundling than `purs bundle`. You will see significantly improved bundle sizes with v0.15, like e.g. for [purescript-halogen template](https://github.com/purescript-halogen/purescript-halogen-template):
Expand Down Expand Up @@ -99,7 +106,7 @@ However, this has a couple of implications that will need you to migrate your co
"use strict";
$PS["Main"] = $PS["Main"] || {};
var exports = $PS["Main"];
var Effect_Console = $PS["Effect.Console"];
var Effect_Console = $PS["Effect.Console"];
var main = Effect_Console.log("\ud83c\udf5d");
exports["main"] = main;
})(PS);
Expand All @@ -112,11 +119,13 @@ However, this has a couple of implications that will need you to migrate your co

### How can I update CJS to ESM?

When you are writing JS FFI the most common situations where you will see changes are:
Most of the below changes can be automated (see next section), but this section describes what changes need to be made in more detail.

When you are writing JS FFI the most common situations where you will see changes are:

* Importing a module

In v0.14 you had to import a module using `require`
In v0.14 you had to import a module using `require`

```javascript
const mymodule = require('mymodule')
Expand All @@ -137,11 +146,19 @@ When you are writing JS FFI the most common situations where you will see change
exports.greet = function() { return "hello " + world }
```

In v0.15 you need to use `export`
In v0.15 you need to use `export`
```javascript
export const world = "🗺"

export function greet() { return "hello " + world }

// Sometimes, defining the function and then exporting it under
// a different name is needed to prevent issues with JavaScript
// keywords. For example, we might use the below FFI
// to export a function named `new`
// foreign import new :: Effect SomeObject
const newImpl = function () { return new SomeObject; }
export { newImpl as new };
```

Fortunately, there are tools that can automatically perform this conversion for you in most of the cases.
Expand All @@ -167,6 +184,7 @@ https://github.com/lebab/lebab#unsafe-transforms

In general though it works well in most of the cases.

See also the ["Migrate to ES Modules"](https://github.com/JordanMartinez/purescript-ecosystem-update/blob/master/src/bash/lib/migrateFfiToEs6.sh) script used in the ecosystem updates for inspiration.

Another option you can try is [`cjstoesm`](https://github.com/wessberg/cjstoesm).

Expand All @@ -182,7 +200,7 @@ import { main } from 'output/Main/index.js'
main()
```

and run
and run
```bash
node index.js
# or if you are on Node.js 12
Expand Down Expand Up @@ -212,20 +230,20 @@ For a full discussion see [the github issue](https://github.com/working-group-pu

See [`spago` documentation](https://github.com/purescript/spago#bundle-a-project-into-a-single-js-file).

Basic usage:
Basic usage:
```bash
spago bundle-app # bundle for the browser
spago bundle-app # bundle for the browser
spago bundle-app --platform node # bundle for node
spago bundle-app --minify # minified bundle for the browser
spago bundle-app --minify # minified bundle for the browser
spago bundle-app --platform node --minify # minified bundle for node

spago bundle-module # bundle for the browser
spago bundle-module # bundle for the browser
spago bundle-module --platform node # bundle for node
spago bundle-module --minify # minified bundle for the browser
spago bundle-module --minify # minified bundle for the browser
spago bundle-module --platform node --minify # minified bundle for node
```

#### Using `esbuild` to bundle
#### Using `esbuild` to bundle

See [`esbuild` documentation](https://esbuild.github.io/).

Expand Down Expand Up @@ -257,3 +275,49 @@ Basic usage:
parcel build index.html --no-source-maps --no-optimize --no-scope-hoist --dist-dir "dist/" # bundle for the browser
parcel build index.html --no-source-maps --dist-dir "dist/" # minified bundle for the browser
```

## Breaking Changes Made in Core Libraries

### Changes affecting multiple libraries

- Migrated all FFI to ES modules and dropped support for CommonJS modules.
- Removed all kind-specific Proxy types (e.g. `SProxy`, `Proxy2`, `Proxy3`, `RLProxy`, etc.)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe note "If you are using any of these types, replace them with Proxy instead."

- Replace usage of such types with `Type.Proxy (Proxy(..))`.
- Removed `MonadZero` type class and all of its deprecated instances.

### `purescript-prelude` changes

- The data type, `NoConstructors`, often used in `Generic`-related code, was changed to newtype `Void`, enabling one to unwrap the newtype and use `absurd`.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is non-breaking then I'm not sure it needs to be included; if it is breaking then we can keep it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure it's breaking, but it's been labeled as such and does actually enable type class instances to exist that weren't possible before. So, I do think it deserves a mention because many do rely upon Generic. That being said, I think the main audience would be people using Generic to define things like GenericShow type classes.


### `purescript-ordered-collections`: update on `Map`'s `Semigroup` instance

This section has yet to be written. Below is what was written in the v0.14.x guide.

- Changes we will be making in future releases:
- v0.14.0
- `Data.Map.Unbiased` - added
- `Data.Map`'s `Semigroup` instance unchanged but a deprecation notice is added, warning of future change
- v0.15.0
- `Data.Map.Unbiased` - deprecated
- `Data.Map`'s `Semigroup` instance is changed to `Data.Map.Unbiased` implementation. A deprecation notice is still shown, warning of the change.
- v0.16.0
- `Data.Map.Unbiased` - removed
- `Data.Map` - warning on `Semigroup` instance is removed

See [Unbiasing the Semigroup instance for Map](https://discourse.purescript.org/t/unbiasing-the-semigroup-instance-for-map/1935) and [purescript/purescript-ordered-collections#38](https://github.com/purescript/purescript-ordered-collections/pull/38) for more context.

### `purescript-foreign-object`'s `Semigroup` instance was changed

This section has yet to be written. Including here because it relates to the Map discussion above.

## Breaking Changes in the `purescript-contrib` libraries

This section has yet to be written

## Breaking Changes in the `purescript-node` libraries

This section has yet to be written

## Breaking Changes in the `purescript-web` libraries

This section has yet to be written