---
title: 4.0 migration
sidebar_label: '4.0'
---

## Shifted supported platform versions

Since Node.js v16 has reached [end of life](https://nodejs.org/en/about/releases/), Packemon now
requires at minimum v18.12 and above to run. Furthermore, we're entirely dropping v14 support, and
shifting v16 into `legacy`, v18 into `stable`, v20 into `current`, and the new v21 into
`experimental`. As part of this process, we are also bumping minimum requirements and coupled npm
versions.

The updated [`support`](../config.md#support) compatibility table is as follows.

#### Before

|          | Legacy     | Stable     | Current    | Experimental |
| -------- | ---------- | ---------- | ---------- | ------------ |
| node     | >= 14.15.0 | >= 16.12.0 | >= 18.12.0 | >= 19.0.0    |
| npm      | >= 6.14.0  | >= 8.1.0   | >= 8.19.0  | >= 9.0.0     |
| electron | >= 7       | >= 11      | >= 16      | >= 21        |
| native   | iOS 13     | iOS 14     | iOS 15     | iOS 16       |

#### After

|          | Legacy     | Stable     | Current    | Experimental |
| -------- | ---------- | ---------- | ---------- | ------------ |
| node     | >= 16.12.0 | >= 18.12.0 | >= 20.10.0 | >= 21.6.0    |
| npm      | >= 8.1.0   | >= 8.19.0  | >= 10.0.0  | >= 10.4.0    |
| electron | >= 11      | >= 16      | >= 21      | >= 26        |
| native   | iOS 14     | iOS 15     | iOS 16     | iOS 17       |

Notable Node.js changes:

- Supports `fetch` natively.
- Registering ESM hooks.
- `import.meta.resolve()`
- `--experimental-detect-module`
- `--experimental-default-type`

## Packemon is now ESM only

We've finished our migration to an ESM only package by shipping only `.mjs` files. This was made
possible by our underlying `@boost` framework,
[which was also converted to ESM only in v5](https://boostlib.dev/docs/migrate/5.0). For users of
Packemon, ESM only should be entirely transparent to you, but at minimum, you should see increased
performance and reduced memory usage, as ESM is far more performant than CJS.

## React Native now supports `esm` target

Over the last year, [Metro](https://metrobundler.dev/), the React Native bundler has received a ton
of new features, such as symlinks support, ESM support, `package.json` exports/imports, Hermes
integration, Terser, Node.js 18+, and much more.

Since Metro has been modernized to such an extent, we're now confident in it's ESM support, so have
added `esm` as a valid format for the `native` platform.

## Streamlined exports and the `default` condition

Packemon has supported [automatic `package.json` `exports`](../features#automatic-package-exports)
since its inception, and we believe this to be one of its greatest features. However, automating
exports correctly has been _very difficult_ to get right, especially when building a package for
multiple platforms and formats.

One of the biggest issues that users face, is when a package is built for browers only, only a
`browser` export condition is generated. This _looks correct_, and is, but when it's not. For
non-bundler environments, such as Node.js and TypeScript, this condition is completely ignored,
resulting in "missing exports or types" errors. Although the package is built correctly, this feels
like a bug, and is a poor developer experience. It's also very confusing on how to fix it,
especially when a user has no knowledge on how exports and conditions work.

To remedy this problem, we've implemented a new algorithm that will automatically flatten exports
and add a `default` condition if it does not exist. The `default` condition is supported by _all
tools_, and should avoid the problem above. We believe this will work much better, but we're also
not 100% confident it will work correctly for all use cases, so all feedback is appreciated!
