Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(babel): minify typeof window #27530

Merged
merged 10 commits into from Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
64 changes: 64 additions & 0 deletions docs/pages/guides/tree-shaking.mdx
Expand Up @@ -185,6 +185,70 @@ The above code snippet is then minified, which removes the unused conditional:
- This system does not apply to server code as environment variables are not inlined in server bundles.
- Library authors should not use `EXPO_PUBLIC_` environment variables as they only run in application code for security reasons.

## Removing server code

> SDK 51 and greater

It's common to use `typeof window === 'undefined'` to conditionally enable/disable code for server/client environments.
EvanBacon marked this conversation as resolved.
Show resolved Hide resolved

`babel-preset-expo` automatically transforms `typeof window === 'undefined` to `true` when bundling for server environments, and `false` when bundling for websites. The check is left as-is when bundling for native client environments to support apps that polyfill `window`.
EvanBacon marked this conversation as resolved.
Show resolved Hide resolved

This transform is run in both development and production, but only removes conditional requires in production.
EvanBacon marked this conversation as resolved.
Show resolved Hide resolved

You can configure `babel-preset-expo` to skip the transform by passing `{ preserveTypeofWindow: false }`.

<Step label="1">

```js Input
if (typeof window === 'undefined') {
console.log('Hello on the server!');
}
```

</Step>

<Step label="2">

The above input code snippet is transformed to the following after `babel-preset-expo` when bundling for server environments (API routes, server rendering):
EvanBacon marked this conversation as resolved.
Show resolved Hide resolved

```js Post babel-preset-expo (bundling for server)
if (true) {
console.log('Hello on the server!');
}
```

Bundling client code for web browsers will change `typeof window` to `false`:

```js Post babel-preset-expo
if (false) {
console.log('Hello on the server!');
}
```

Bundling client code for native apps will leave `typeof window` in place:

```js Post babel-preset-expo
if (typeof window === 'undefined') {
console.log('Hello on the server!');
}
```

</Step>

<Step label="3">

The above code snippet is then minified, which removes the unused conditional:

```js Post minifier (server)
console.log('Hello on the server!');
```

```js Post minifier (client websites)
// Empty file
```

</Step>

## Remove unused imports and exports

As of Expo SDK 50, unused imports and exports are not removed from the production bundle. We plan to add this feature to all platforms in a future release.
Expand Down
1 change: 1 addition & 0 deletions packages/babel-preset-expo/CHANGELOG.md
Expand Up @@ -6,6 +6,7 @@

### 🎉 New features

- Minify `typeof window` in server and web contexts. ([#27530](https://github.com/expo/expo/pull/27530) by [@EvanBacon](https://github.com/EvanBacon))
- Add support for using `process.env.EXPO_OS` to detect the platform without platform shaking imports. ([#27509](https://github.com/expo/expo/pull/27509) by [@EvanBacon](https://github.com/EvanBacon))
- Add basic `react-server` support. ([#27264](https://github.com/expo/expo/pull/27264) by [@EvanBacon](https://github.com/EvanBacon))

Expand Down
18 changes: 18 additions & 0 deletions packages/babel-preset-expo/README.md
Expand Up @@ -42,6 +42,24 @@ If the `bundler` is not defined, it will default to checking if a `babel-loader`

## Options

### `minifyTypeofWindow`

Set `minifyTypeofWindow: false` to preserve the `typeof window` check in your code, e.g. `if (typeof window === 'undefined')` -> `if (true)` in servers. This is useful when you're using libraries that mock the window object on native or in the server.

```js
[
'babel-preset-expo',
{
// If your native app doesn't polyfill `window` then setting this to `false` can reduce bundle size.
native: {
minifyTypeofWindow: true,
},
},
];
```

Defaults to `false` for server environments and web, `true` for native platforms to support legacy browser polyfills.

### `reanimated`

`boolean`, defaults to `true`. Set `reanimated: false` to disable adding the `react-native-reanimated/plugin` when `react-native-reanimated` is installed.
Expand Down
2 changes: 2 additions & 0 deletions packages/babel-preset-expo/build/index.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 23 additions & 10 deletions packages/babel-preset-expo/build/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 0 additions & 9 deletions packages/babel-preset-expo/build/inline-env-vars.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 1 addition & 32 deletions packages/babel-preset-expo/build/inline-env-vars.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/babel-preset-expo/package.json
Expand Up @@ -49,6 +49,7 @@
"@babel/preset-react": "^7.22.15",
"@react-native/babel-preset": "^0.73.18",
"babel-plugin-react-native-web": "~0.19.10",
"babel-plugin-transform-define": "^2.1.4",
"react-refresh": "0.14.0"
},
"devDependencies": {
Expand Down