Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
leegeunhyeok committed Nov 28, 2023
1 parent cb9a38d commit 081fe18
Show file tree
Hide file tree
Showing 19 changed files with 218 additions and 188 deletions.
Binary file not shown.
23 changes: 12 additions & 11 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ PODS:
- glog
- react-native-flipper (0.176.0):
- React-Core
- react-native-safe-area-context (4.7.2):
- react-native-safe-area-context (4.7.3):
- React-Core
- React-NativeModulesApple (0.72.6):
- hermes-engine
Expand Down Expand Up @@ -489,9 +489,10 @@ PODS:
- React-jsi (= 0.72.6)
- React-logger (= 0.72.6)
- React-perflogger (= 0.72.6)
- RNGestureHandler (2.13.1):
- RNGestureHandler (2.13.4):
- RCT-Folly (= 2021.07.22.00)
- React-Core
- RNReanimated (3.5.2):
- RNReanimated (3.5.4):
- DoubleConversion
- FBLazyVector
- glog
Expand Down Expand Up @@ -520,10 +521,10 @@ PODS:
- React-RCTText
- ReactCommon/turbomodule/core
- Yoga
- RNScreens (3.25.0):
- RNScreens (3.27.0):
- RCT-Folly (= 2021.07.22.00)
- React-Core
- React-RCTImage
- RNSVG (13.13.0):
- RNSVG (13.14.0):
- React-Core
- SocketRocket (0.6.1)
- Yoga (1.14.0)
Expand Down Expand Up @@ -746,7 +747,7 @@ SPEC CHECKSUMS:
React-jsinspector: 194e32c6aab382d88713ad3dd0025c5f5c4ee072
React-logger: cebf22b6cf43434e471dc561e5911b40ac01d289
react-native-flipper: bbbbb6e3d8b7e6f5fb083885cb9898765fd6d782
react-native-safe-area-context: 7aa8e6d9d0f3100a820efb1a98af68aa747f9284
react-native-safe-area-context: 238cd8b619e05cb904ccad97ef42e84d1b5ae6ec
React-NativeModulesApple: 02e35e9a51e10c6422f04f5e4076a7c02243fff2
React-perflogger: e3596db7e753f51766bceadc061936ef1472edc3
React-RCTActionSheet: 17ab132c748b4471012abbcdcf5befe860660485
Expand All @@ -764,10 +765,10 @@ SPEC CHECKSUMS:
React-runtimescheduler: f23e337008403341177fc52ee4ca94e442c17ede
React-utils: fa59c9a3375fb6f4aeb66714fd3f7f76b43a9f16
ReactCommon: dd03c17275c200496f346af93a7b94c53f3093a4
RNGestureHandler: 38aa38413896620338948fbb5c90579a7b1c3fde
RNReanimated: 2491645f0883526f4470d8b5c761308709ba31f8
RNScreens: 85d3880b52d34db7b8eeebe2f1a0e807c05e69fa
RNSVG: ed492aaf3af9ca01bc945f7a149d76d62e73ec82
RNGestureHandler: 6e46dde1f87e5f018a54fe5d40cd0e0b942b49ee
RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87
RNScreens: 3c2d122f5e08c192e254c510b212306da97d2581
RNSVG: d00c8f91c3cbf6d476451313a18f04d220d4f396
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
Yoga: b76f1acfda8212aa16b7e26bcce3983230c82603
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
Expand Down
6 changes: 4 additions & 2 deletions example/ios/example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,8 @@
);
OTHER_LDFLAGS = (
"$(inherited)",
" ",
"-Wl",
"-ld_classic",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
Expand Down Expand Up @@ -675,7 +676,8 @@
);
OTHER_LDFLAGS = (
"$(inherited)",
" ",
"-Wl",
"-ld_classic",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
Expand Down
77 changes: 38 additions & 39 deletions packages/core/lib/bundler/bundler.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import path from 'node:path';
import type { Stats } from 'node:fs';
import esbuild, {
type BuildOptions,
type BuildResult,
Expand Down Expand Up @@ -134,20 +135,7 @@ export class ReactNativeEsbuildBundler extends BundlerEventEmitter {

private startWatcher(): Promise<void> {
return FileSystemWatcher.getInstance()
.setHandler((event, changedFile, stats) => {
const hasTask = this.buildTasks.size > 0;
const isChanged = event === 'change';
ReactNativeEsbuildBundler.shared.setValue({
watcher: {
changed: hasTask && isChanged ? changedFile : null,
stats: stats ?? null,
},
});

for (const { context, handler } of this.buildTasks.values()) {
context.rebuild().catch((error) => handler?.rejecter?.(error));
}
})
.setHandler(this.handleFileChanged.bind(this))
.watch(this.root);
}

Expand Down Expand Up @@ -187,7 +175,7 @@ export class ReactNativeEsbuildBundler extends BundlerEventEmitter {
return {
entryPoints: [bundleOptions.entry],
outfile: bundleOptions.outfile,
sourceRoot: path.dirname(bundleOptions.entry),
sourceRoot: this.root,
mainFields: config.resolver.mainFields,
resolveExtensions: getResolveExtensionsOption(
bundleOptions,
Expand All @@ -197,7 +185,11 @@ export class ReactNativeEsbuildBundler extends BundlerEventEmitter {
loader: getLoaderOption(config.resolver.assetExtensions),
define: getGlobalVariables(bundleOptions),
banner: {
js: await getTransformedPreludeScript(bundleOptions, this.root),
js: await getTransformedPreludeScript(
bundleOptions,
this.root,
enableHmr ? ['swc-plugin-global-esm/runtime'] : undefined,
),
},
plugins: [
createBuildStatusPlugin(context, {
Expand Down Expand Up @@ -305,6 +297,9 @@ export class ReactNativeEsbuildBundler extends BundlerEventEmitter {
invariant(bundleOutput, 'empty bundle output');
invariant(bundleSourcemapOutput, 'empty sourcemap output');

const bundleMeta = HmrTransformer.createBundleMeta(data.result.metafile);
ReactNativeEsbuildBundler.shared.setValue({ bundleMeta });

currentTask.handler?.resolver?.({
result: {
source: bundleOutput.contents,
Expand All @@ -318,31 +313,35 @@ export class ReactNativeEsbuildBundler extends BundlerEventEmitter {
currentTask.handler?.rejecter?.(error);
} finally {
currentTask.status = 'resolved';
this.emit('build-end', {
revisionId,
id: context.id,
additionalData: context.additionalData,
update: null,
});
}
}

private handleFileChanged(
event: string,
changedFile: string,
_stats?: Stats,
): void {
const hasTask = this.buildTasks.size > 0;
const isChanged = event === 'change';
if (!(hasTask && isChanged)) return;

for (const [id, hmrController] of ReactNativeEsbuildBundler.hmr.entries()) {
const { bundleMeta } = ReactNativeEsbuildBundler.shared.get(id);
Promise.resolve(
sharedStorage.hmr.path
? hmrController.getUpdates(
sharedStorage.hmr.path,
data.result.metafile,
)
: null,
)
.then((update) => {
this.emit('build-end', {
revisionId,
id: context.id,
additionalData: context.additionalData,
update,
});
})
.catch((error) => {
logger.error('unexpected error', error as Error);
this.emit('build-end', {
revisionId,
id: context.id,
additionalData: context.additionalData,
update: null,
});
bundleMeta ? hmrController.getDelta(changedFile, bundleMeta) : null,
).then((update) => {
this.emit('build-end', {
id,
update,
revisionId: new Date().getTime().toString(),
});
});
}
}

Expand Down
25 changes: 15 additions & 10 deletions packages/core/lib/bundler/helpers/hmr.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
AsyncTransformPipeline,
swcPresets,
transformRuntimeModule,
} from '@react-native-esbuild/transformer';
import type { BundleOptions } from '@react-native-esbuild/config';
import type { Config } from '../../types';
Expand All @@ -24,25 +25,29 @@ export const getHmrRuntimeTransformer = (
} = config.transformer ?? {};
const additionalBabelRules = additionalTransformRules?.babel ?? [];
const additionalSwcRules = additionalTransformRules?.swc ?? [];

const transformPipeline = new AsyncTransformPipeline.builder({
const context = {
...bundleOptions,
id,
root,
})
};

const transformPipeline = new AsyncTransformPipeline.builder(context)
.setSwcPreset(swcPresets.getReactNativeRuntimePreset())
.setFullyTransformPackages(fullyTransformPackageNames)
.setStripFlowPackages(stripFlowPackageNames)
.setAdditionalBabelTransformRules(additionalBabelRules)
.setAdditionalSwcTransformRules(additionalSwcRules)
.onEnd(async (code, args) => {
const runtimeTransformedCode = await transformRuntimeModule(code, {
...context,
path: args.path,
});
return { code: runtimeTransformedCode, done: true };
})
.build();

return (code: string, path: string) => {
return transformPipeline
.transform(code, {
...DUMMY_ESBUILD_ARGS,
path,
})
return (code: string, path: string) =>
transformPipeline
.transform(code, { ...DUMMY_ESBUILD_ARGS, path })
.then((result) => result.code);
};
};
7 changes: 6 additions & 1 deletion packages/core/lib/bundler/helpers/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type { BundleOptions } from '@react-native-esbuild/config';
export const getTransformedPreludeScript = async (
bundleOptions: BundleOptions,
root: string,
additionalScriptPath?: string[],
): Promise<string> => {
// Dummy context
const context: TransformerContext = {
Expand All @@ -20,7 +21,11 @@ export const getTransformedPreludeScript = async (
dev: bundleOptions.dev,
entry: bundleOptions.entry,
};
const preludeScript = await getPreludeScript(bundleOptions, root);
const preludeScript = await getPreludeScript(
bundleOptions,
root,
additionalScriptPath,
);

/**
* Remove `"use strict";` added by sucrase.
Expand Down
10 changes: 1 addition & 9 deletions packages/core/lib/bundler/plugins/statusPlugin/StatusLogger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,20 +118,12 @@ export class StatusLogger {
async summary({ warnings, errors }: BuildResult): Promise<boolean> {
const duration = (new Date().getTime() - this.buildStartedAt) / 1000;
const isSuccess = errors.length === 0;
const changedFileText =
isSuccess && this.bundlerSharedData.hmr.path
? colors.gray(
`(${this.bundlerSharedData.hmr.path
.replace(this.context.root, '')
.substring(1)})`,
)
: '';

await this.printMessages(warnings, 'warning');
await this.printMessages(errors, 'error');

const resultText = isSuccess
? `${this.platformText} done! ${changedFileText}`
? `${this.platformText} done!`
: `${this.platformText} failed!`;

if (isTTY()) {
Expand Down
17 changes: 3 additions & 14 deletions packages/core/lib/bundler/storages/SharedStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ export class SharedStorage extends Storage<BundlerSharedData> {
}

private getDefaultSharedData(): BundlerSharedData {
return {
watcher: { changed: null, stats: null },
hmr: { id: null, path: null },
};
return { bundleMeta: undefined };
}

public get(key: number): BundlerSharedData {
Expand All @@ -36,21 +33,13 @@ export class SharedStorage extends Storage<BundlerSharedData> {

public setValue(value: Partial<BundlerSharedData>): void {
for (const sharedData of this.data.values()) {
sharedData.watcher.changed =
value.watcher?.changed ?? sharedData.watcher.changed;
sharedData.watcher.stats =
value.watcher?.stats ?? sharedData.watcher.stats;
sharedData.bundleMeta = value.bundleMeta;
}
}

public clearAll(): Promise<void> {
for (const sharedData of this.data.values()) {
// watcher
sharedData.watcher.changed = null;
sharedData.watcher.stats = null;
// hmr
sharedData.hmr.id = null;
sharedData.hmr.path = null;
sharedData.bundleMeta = undefined;
}
return Promise.resolve();
}
Expand Down
11 changes: 2 additions & 9 deletions packages/core/lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { Stats } from 'node:fs';
import type { BuildContext, Plugin } from 'esbuild';
import type {
BabelTransformRule,
SwcTransformRule,
} from '@react-native-esbuild/transformer';
import type { BundleMeta } from '@react-native-esbuild/hmr';
import type { BundleOptions } from '@react-native-esbuild/config';

export interface Config {
Expand Down Expand Up @@ -162,14 +162,7 @@ export type ReactNativeEsbuildPluginCreator<PluginConfig = void> = (
) => Plugin;

export interface BundlerSharedData {
watcher: {
changed: string | null;
stats: Stats | null;
};
hmr: {
id: string | null;
path: string | null;
};
bundleMeta?: BundleMeta;
}

export type BundlerAdditionalData = Record<string, unknown>;
Expand Down
2 changes: 1 addition & 1 deletion packages/dev-server/lib/server/ReactNativeAppServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export class ReactNativeAppServer extends DevServer {
if (!additionalData?.disableRefresh) {
update?.fullyReload
? hmr.liveReload(revisionId)
: hmr.hotReload(revisionId, update.code);
: hmr.hotReload(revisionId, update?.code ?? '');
}
hmr.updateDone();
});
Expand Down
2 changes: 1 addition & 1 deletion packages/dev-server/lib/server/ReactNativeWebServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export class ReactNativeWebServer extends DevServer {
if (!additionalData?.disableRefresh) {
update?.fullyReload
? hmr.liveReload(revisionId)
: hmr.hotReload(revisionId, update.code);
: hmr.hotReload(revisionId, update?.code ?? '');
}
});

Expand Down
Loading

0 comments on commit 081fe18

Please sign in to comment.