Skip to content

Commit

Permalink
feat: hot module replacement
Browse files Browse the repository at this point in the history
- now supports HMR
- limitations
  - in node_modules/* modules are not supported HMR yet.
- custom runtime module system by `swc-plugin-global-module`
  - https://github.com/leegeunhyeok/swc-plugin-global-module

close #38
  • Loading branch information
leegeunhyeok committed Dec 29, 2023
1 parent ced78aa commit 6fc2d8d
Show file tree
Hide file tree
Showing 137 changed files with 2,524 additions and 1,783 deletions.
11 changes: 11 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ module.exports = {
'no-console': 'off',
},
},
{
files: ['packages/hmr/lib/runtime/*.ts'],
rules: {
'no-console': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
},
},
{
files: ['packages/jest/lib/**/*.ts'],
rules: {
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
- 💾 In-memory & Local File System Caching
- 🎨 Flexible & Extensible
- 🔥 Supports JSC & Hermes Runtime
- 🔄 Supports Live Reload
- 🔄 Supports HMR & Live Reload
- 🐛 Supports Debugging(Flipper, Chrome Debugger)
- 🌍 Supports All Platforms(Android, iOS, Web)
- ✨ New Architecture Ready
Expand Down
31 changes: 23 additions & 8 deletions docs/pages/configuration/basic-configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ exports.default = {};
By default, follow the configuration below.

```js
/**
* @type {import('@react-native-esbuild/core').Config}
*/
exports.default = {
cache: true,
logger: {
Expand All @@ -28,13 +31,6 @@ exports.default = {
assetExtensions: [/* internal/lib/defaults.ts */],
},
transformer: {
jsc: {
transform: {
react: {
runtime: 'automatic',
},
},
},
stripFlowPackageNames: ['react-native'],
},
web: {
Expand Down Expand Up @@ -68,7 +64,6 @@ Resolver configurations.

Transformer configurations.

- `transformer.jsc`: [jsc](https://swc.rs/docs/configuration/compilation) config in swc.
- `transformer.stripFlowPackageNames`: Package names to strip flow syntax from (Defaults to `['react-native']`)
- `transformer.fullyTransformPackageNames`: Package names to fully transform with [metro-react-native-babel-preset](https://github.com/facebook/react-native/tree/main/packages/react-native-babel-preset) from
- `transformer.additionalTransformRules`: Additional transform rules. This rules will be applied before phase of transform to es5
Expand All @@ -90,6 +85,15 @@ Additional Esbuild plugins.

For more details, go to [Custom Plugins](/configuration/custom-plugins)

### experimental

<Callout>
Experimental configurations.
</Callout>

- `experimental.hmr`: Enable HMR(Hot Module Replacement) on development mode. (Defaults to `false`)
- For more details and limitations, go to [Hot Module Replacement](/limitations/hot-module-replacement).

## Types

<details>
Expand Down Expand Up @@ -209,6 +213,17 @@ interface Config {
* Additional Esbuild plugins.
*/
plugins?: EsbuildPlugin[];
/**
* Experimental configurations
*/
experimental?: {
/**
* Enable HMR(Hot Module Replacement) on development mode.
*
* Defaults to `false`.
*/
hmr?: boolean;
};
/**
* Client event receiver
*/
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/getting-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ And create `react-native-esbuild.js` to project root.
exports.default = {};
```

for more details, go to [Configuration](/configuration/basic).
for more details, go to [Basic Configuration](/configuration/basic-configuration).

## Native Setup

Expand Down
5 changes: 0 additions & 5 deletions docs/pages/limitations/hot-module-replacement.md

This file was deleted.

30 changes: 30 additions & 0 deletions docs/pages/limitations/hot-module-replacement.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Callout } from 'nextra/components'

# Hot Module Replacement

<Callout type="warning">
HMR(Hot Module Replacement) is experimental.
</Callout>

esbuild doesn't currently support Hot Module Replacement(HMR).

So, I working hard for implement custom HMR and it's partially available as an experimental feature.

You can enable HMR by `experimental.hmr` set to `true` in your configuration file.

```js
/**
* @type {import('@react-native-esbuild/core').Config}
*/
exports.default = {
// ...
experimental: {
hmr: true,
},
};
```

and here are some limitations.

- Detects changes in the `<projectRoot>/*` only.
- Changes detected in `<projectRoot>/node_modules/*` will be ignored and fully refreshed after rebuild.
3 changes: 3 additions & 0 deletions example/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ yarn-error.log
!.yarn/sdks
!.yarn/versions

# @swc
.swc

# @react-native-esbuild
.rne
.swc
Expand Down
3 changes: 3 additions & 0 deletions example/react-native-esbuild.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,7 @@ exports.default = {
],
},
},
experimental: {
hmr: true,
},
};
18 changes: 2 additions & 16 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,27 +27,13 @@ const config: Config = {
testMatch: ['<rootDir>/packages/core/**/*.test.ts'],
setupFilesAfterEnv: ['<rootDir>/test/setup.ts'],
},
{
displayName: '@react-native-esbuild/config',
transform,
testEnvironment: 'node',
testMatch: ['<rootDir>/packages/config/**/*.test.ts'],
setupFilesAfterEnv: ['<rootDir>/test/setup.ts'],
},
{
displayName: '@react-native-esbuild/dev-server',
transform,
testEnvironment: 'node',
testMatch: ['<rootDir>/packages/dev-server/**/*.test.ts'],
setupFilesAfterEnv: ['<rootDir>/test/setup.ts'],
},
{
displayName: '@react-native-esbuild/internal',
transform,
testEnvironment: 'node',
testMatch: ['<rootDir>/packages/internal/**/*.test.ts'],
setupFilesAfterEnv: ['<rootDir>/test/setup.ts'],
},
{
displayName: '@react-native-esbuild/plugins',
transform,
Expand All @@ -70,10 +56,10 @@ const config: Config = {
setupFilesAfterEnv: ['<rootDir>/test/setup.ts'],
},
{
displayName: '@react-native-esbuild/utils',
displayName: '@react-native-esbuild/shared',
transform,
testEnvironment: 'node',
testMatch: ['<rootDir>/packages/utils/**/*.test.ts'],
testMatch: ['<rootDir>/packages/shared/**/*.test.ts'],
setupFilesAfterEnv: ['<rootDir>/test/setup.ts'],
},
],
Expand Down
12 changes: 4 additions & 8 deletions packages/cli/lib/cli.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import {
DEFAULT_ENTRY_POINT,
DEFAULT_WEB_ENTRY_POINT,
} from '@react-native-esbuild/config';
import { VERSION } from './constants';
import { constants } from '@react-native-esbuild/shared';
import type { RawArgv } from './types';

const commonOptions = {
Expand All @@ -27,7 +23,7 @@ const commonOptions = {
export const cli = (): RawArgv | Promise<RawArgv> => {
return yargs(hideBin(process.argv))
.scriptName('rne')
.version(VERSION)
.version(self._version as string)
.usage('$0 <cmd> [args]')
.command(
'start',
Expand Down Expand Up @@ -79,7 +75,7 @@ export const cli = (): RawArgv | Promise<RawArgv> => {
'entry-file': {
type: 'string',
describe: 'Set the entry file path',
default: DEFAULT_WEB_ENTRY_POINT,
default: constants.DEFAULT_WEB_ENTRY_POINT,
},
host: {
describe: 'Set the server host',
Expand Down Expand Up @@ -124,7 +120,7 @@ export const cli = (): RawArgv | Promise<RawArgv> => {
'entry-file': {
type: 'string',
describe: 'Set the entry file path',
default: DEFAULT_ENTRY_POINT,
default: constants.DEFAULT_ENTRY_POINT,
},
'bundle-output': {
type: 'string',
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/lib/commands/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ReactNativeEsbuildBundler } from '@react-native-esbuild/core';
import {
DEFAULT_ENTRY_POINT,
type BundleOptions,
} from '@react-native-esbuild/config';
} from '@react-native-esbuild/shared';
import { printDebugOptions } from '../helpers';
import { bundleArgvSchema } from '../schema';
import { presets } from '../presets';
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/lib/commands/serve.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ReactNativeWebServer } from '@react-native-esbuild/dev-server';
import type { BundleOptions } from '@react-native-esbuild/config';
import type { BundleOptions } from '@react-native-esbuild/shared';
import { printDebugOptions } from '../helpers';
import { serveArgvSchema } from '../schema';
import { presets } from '../presets';
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/lib/commands/start.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable quotes -- Allow quote in template literal */
import path from 'node:path';
import { ReactNativeAppServer } from '@react-native-esbuild/dev-server';
import { DEFAULT_ENTRY_POINT } from '@react-native-esbuild/config';
import { DEFAULT_ENTRY_POINT } from '@react-native-esbuild/shared';
import { enableInteractiveMode, printDebugOptions } from '../helpers';
import { startArgvSchema } from '../schema';
import { presets } from '../presets';
Expand Down
3 changes: 0 additions & 3 deletions packages/cli/lib/constants/index.ts

This file was deleted.

2 changes: 1 addition & 1 deletion packages/cli/lib/helpers/cli.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { colors } from '@react-native-esbuild/utils';
import { colors } from '@react-native-esbuild/shared';
import { logger } from '../shared';

export const getCommand = <RawArgv extends { _: (string | number)[] }>(
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ReactNativeEsbuildBundler } from '@react-native-esbuild/core';
import { LogLevel } from '@react-native-esbuild/utils';
import { LogLevel } from '@react-native-esbuild/shared';
import { cli } from './cli';
import * as Commands from './commands';
import { getCommand, handleUncaughtException } from './helpers';
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/lib/schema/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from 'node:path';
import { SUPPORT_PLATFORMS } from '@react-native-esbuild/config';
import { SUPPORT_PLATFORMS } from '@react-native-esbuild/shared';
import { z } from 'zod';

const resolvePath = (filepath: string): string =>
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/lib/shared.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { Logger } from '@react-native-esbuild/utils';
import { Logger } from '@react-native-esbuild/shared';

export const logger = new Logger('cli');
3 changes: 1 addition & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@
"url": "https://github.com/leegeunhyeok/react-native-esbuild/issues"
},
"dependencies": {
"@react-native-esbuild/config": "workspace:*",
"@react-native-esbuild/core": "workspace:*",
"@react-native-esbuild/dev-server": "workspace:*",
"@react-native-esbuild/plugins": "workspace:*",
"@react-native-esbuild/utils": "workspace:*",
"@react-native-esbuild/shared": "workspace:*",
"yargs": "^17.7.2",
"zod": "^3.22.2"
},
Expand Down
Loading

1 comment on commit 6fc2d8d

@github-actions
Copy link

Choose a reason for hiding this comment

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

Coverage report

St.
Category Percentage Covered / Total
🔴 Statements 12.98% 281/2165
🔴 Branches 12.15% 70/576
🔴 Functions 9.37% 61/651
🔴 Lines 12.27% 255/2078

Test suite run success

56 tests passing in 7 suites.

Report generated by 🧪jest coverage report action from 6fc2d8d

Please sign in to comment.