Skip to content

Commit 2c2c303

Browse files
committed
feat: add web support
1 parent 0f0ca1b commit 2c2c303

42 files changed

Lines changed: 1593 additions & 1959 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.npmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
strict-peer-dependencies=false
2-
auto-install-peers=true
2+
auto-install-peers=false
33
node-linker=hoisted

apps/playground/index.html

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>Harness Playground</title>
6+
<meta name="viewport" content="width=device-width,initial-scale=1" />
7+
<style>
8+
html,
9+
body {
10+
height: 100%;
11+
}
12+
13+
body {
14+
overflow: hidden;
15+
}
16+
17+
#root {
18+
display: flex;
19+
height: 100%;
20+
}
21+
</style>
22+
</head>
23+
<body>
24+
<div id="root"></div>
25+
<script src="http://localhost:8081/index.bundle?platform=web&dev=true&entryFile=index.js"></script>
26+
</body>
27+
</html>

apps/playground/index.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@
22
* @format
33
*/
44

5-
import { AppRegistry } from 'react-native';
5+
import { AppRegistry, Platform } from 'react-native';
66
import App from './src/app/App';
77
import { name as appName } from './app.json';
88

99
AppRegistry.registerComponent(appName, () => App);
10+
11+
if (Platform.OS === 'web') {
12+
AppRegistry.runApplication(appName, {
13+
rootTag: document.getElementById('root'),
14+
});
15+
}

apps/playground/metro.config.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,36 @@
11
const { withNxMetro } = require('@nx/react-native');
22
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
33
const path = require('path');
4+
const fs = require('fs');
45

56
const defaultConfig = getDefaultConfig(__dirname);
67

78
const projectRoot = __dirname;
89
const monorepoRoot = path.resolve(projectRoot, '../..');
910

11+
const getCustomResolver = (defaultResolveRequest) => (context, moduleName, platform) => {
12+
if (platform === 'web') {
13+
if (moduleName.includes('NativeSourceCode') ||
14+
moduleName.includes('NativePlatformConstants') ||
15+
moduleName.includes('NativeDevSettings') ||
16+
moduleName.includes('NativeLogBox') ||
17+
moduleName.includes('NativeRedBox')
18+
) {
19+
return {
20+
type: 'empty',
21+
};
22+
} else if (moduleName === 'react-native') {
23+
return {
24+
type: 'sourceFile',
25+
filePath: require.resolve('react-native-web'),
26+
};
27+
}
28+
}
29+
30+
// Everything else: default behavior
31+
return defaultResolveRequest(context, moduleName, platform);
32+
};
33+
1034
/**
1135
* Metro configuration
1236
* https://reactnative.dev/docs/metro
@@ -18,6 +42,30 @@ const customConfig = {
1842
resolver: {
1943
unstable_enablePackageExports: true,
2044
},
45+
server: {
46+
...(defaultConfig.server || {}),
47+
enhanceMiddleware: (middleware) => {
48+
return (req, res, next) => {
49+
if (req.url === '/' || req.url === '/index.html') {
50+
const htmlPath = path.join(projectRoot, 'index.html');
51+
52+
fs.readFile(htmlPath, 'utf8', (err, data) => {
53+
if (err) {
54+
res.writeHead(500, { 'Content-Type': 'text/plain' });
55+
res.end('Error loading index.html: ' + err.message);
56+
return;
57+
}
58+
59+
res.writeHead(200, { 'Content-Type': 'text/html' });
60+
res.end(data);
61+
});
62+
return;
63+
}
64+
65+
return middleware(req, res, next);
66+
};
67+
},
68+
},
2169
};
2270

2371
module.exports = withNxMetro(mergeConfig(defaultConfig, customConfig), {
@@ -26,4 +74,8 @@ module.exports = withNxMetro(mergeConfig(defaultConfig, customConfig), {
2674
path.resolve(projectRoot, 'node_modules'),
2775
path.resolve(monorepoRoot, 'node_modules'),
2876
],
77+
}).then((config) => {
78+
// Nx overrides the resolveRequest, so we need to override it after the merge.
79+
config.resolver.resolveRequest = getCustomResolver(config.resolver.resolveRequest);
80+
return config;
2981
});

apps/playground/package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
},
88
"dependencies": {
99
"react": "19.1.1",
10-
"react-native": "0.82.1"
10+
"react-dom": "19.1.1",
11+
"react-native": "0.82.1",
12+
"react-native-web": "^0.21.2"
1113
},
1214
"devDependencies": {
1315
"react-native-harness": "workspace:*",
@@ -24,6 +26,7 @@
2426
"jest": "^30.2.0",
2527
"@react-native-harness/platform-android": "workspace:*",
2628
"@react-native-harness/platform-apple": "workspace:*",
27-
"@react-native-harness/platform-vega": "workspace:*"
29+
"@react-native-harness/platform-vega": "workspace:*",
30+
"@react-native-harness/platform-web": "workspace:*"
2831
}
2932
}

apps/playground/rn-harness.config.mjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
vegaPlatform,
1313
vegaEmulator,
1414
} from '@react-native-harness/platform-vega';
15+
import { webPlatform, chrome } from '@react-native-harness/platform-web';
1516

1617
const config = {
1718
entryPoint: './index.js',
@@ -48,6 +49,10 @@ const config = {
4849
device: vegaEmulator('VegaTV_1'),
4950
bundleId: 'com.playground',
5051
}),
52+
webPlatform({
53+
name: 'web',
54+
browser: chrome('http://localhost:8081/index.html', { headless: false }),
55+
}),
5156
],
5257
defaultRunner: 'android',
5358
bridgeTimeout: 120000,
1.08 KB
Loading

apps/playground/tsconfig.app.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
],
2828
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.js", "src/**/*.jsx"],
2929
"references": [
30+
{
31+
"path": "../../packages/platform-web/tsconfig.lib.json"
32+
},
3033
{
3134
"path": "../../packages/platform-vega/tsconfig.lib.json"
3235
},

apps/playground/tsconfig.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
"files": [],
44
"include": [],
55
"references": [
6+
{
7+
"path": "../../packages/platform-web"
8+
},
69
{
710
"path": "../../packages/platform-vega"
811
},

packages/bridge/src/shared.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export type {
105105
} from './shared/bundler.js';
106106

107107
export type DeviceDescriptor = {
108-
platform: 'ios' | 'android' | 'vega';
108+
platform: 'ios' | 'android' | 'vega' | 'web';
109109
manufacturer: string;
110110
model: string;
111111
osVersion: string;

0 commit comments

Comments
 (0)