Skip to content

Commit

Permalink
chore(babel): simplify rsc injection code (#27879)
Browse files Browse the repository at this point in the history
# Why

The injection code is a bit of a hack to workaround Metro, this PR
simplifies the transform so we can work on improving it in the future.

---------

Co-authored-by: Expo Bot <34669131+expo-bot@users.noreply.github.com>
  • Loading branch information
EvanBacon and expo-bot committed Mar 28, 2024
1 parent ae0e0ef commit 6245632
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 193 deletions.
1 change: 1 addition & 0 deletions packages/babel-preset-expo/CHANGELOG.md
Expand Up @@ -23,6 +23,7 @@
- Add additional tests for undefined platform minification behavior. ([#27515](https://github.com/expo/expo/pull/27515) by [@EvanBacon](https://github.com/EvanBacon))
- Upgrade `babel-plugin-react-native-web` for latest `react-native-web` aliases. ([#27214](https://github.com/expo/expo/pull/27214) by [@EvanBacon](https://github.com/EvanBacon))
- Directly resolve plugins. ([#27041](https://github.com/expo/expo/pull/27041) by [@EvanBacon](https://github.com/EvanBacon))
- Simplify react server code injection by using more expensive template code. ([#27879](https://github.com/expo/expo/pull/27879) by [@EvanBacon](https://github.com/EvanBacon))

## 10.0.1 - 2023-12-19

Expand Down

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

76 changes: 18 additions & 58 deletions packages/babel-preset-expo/build/client-module-proxy-plugin.js

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

Expand Up @@ -19,12 +19,15 @@ exports[`use server replaces server action exports with React server references
export var greet = function greet(name) {
return \`Hello \${name} from server!\`;
};
;
(function () {
if (typeof module.exports === "function") {
require("react-server-dom-webpack/server").registerServerReference(module.exports, "file:///unknown", null);
if (typeof module.exports === 'function') {
require('react-server-dom-webpack/server').registerServerReference(module.exports, "file:///unknown", null);
} else {
for (var key in module.exports) {
if (typeof module.exports[key] === "function") require("react-server-dom-webpack/server").registerServerReference(module.exports[key], "file:///unknown", key);
if (typeof module.exports[key] === 'function') {
require('react-server-dom-webpack/server').registerServerReference(module.exports[key], "file:///unknown", key);
}
}
}
})();"
Expand Down
146 changes: 21 additions & 125 deletions packages/babel-preset-expo/src/client-module-proxy-plugin.ts
@@ -1,14 +1,10 @@
/**
* Copyright © 2024 650 Industries.
*/
import { ConfigAPI, types } from '@babel/core';
import { template } from '@babel/core';
import url from 'url';

export function reactClientReferencesPlugin(
api: ConfigAPI & { types: typeof types }
): babel.PluginObj {
const { types: t } = api;
const reactServerAdapter = 'react-server-dom-webpack/server';
export function reactClientReferencesPlugin(): babel.PluginObj {
return {
name: 'expo-client-references',
visitor: {
Expand Down Expand Up @@ -44,132 +40,32 @@ export function reactClientReferencesPlugin(
if (isUseClient) {
path.node.body = [];
path.node.directives = [];

// Inject the following:
//
// module.exports = require('react-server-dom-webpack/server').createClientModuleProxy(`${outputKey}#${filePath}`)
// TODO: Use `require.resolveWeak` instead of `filePath` to avoid leaking the file path.
// module.exports = require('react-server-dom-webpack/server').createClientModuleProxy(`${outputKey}#${require.resolveWeak(filePath)}`)
path.pushContainer(
'body',
t.expressionStatement(
t.assignmentExpression(
'=',
t.memberExpression(t.identifier('module'), t.identifier('exports')),
t.callExpression(
t.memberExpression(
t.callExpression(t.identifier('require'), [
t.stringLiteral(reactServerAdapter),
]),
t.identifier('createClientModuleProxy')
),
// `${outputKey}#${require.resolveWeak(filePath)}`
[t.stringLiteral(outputKey)]
)
)
)
template.ast`module.exports = require("react-server-dom-webpack/server").createClientModuleProxy(${JSON.stringify(
outputKey
)});`
);
} else {
// Inject the following:
//
// ;(() => {
// const { registerServerReference } = require('react-server-dom-webpack/server');
// if (typeof module.exports === 'function') registerServerReference(module.exports, moduleId, null);
// else {
// for (const key in module.exports) {
// if (typeof module.exports[key] === 'function') {
// registerServerReference(module.exports[key], moduleId, key);
// }
// }
// }
// })()

const mmexp = t.memberExpression(
t.callExpression(t.identifier('require'), [t.stringLiteral(reactServerAdapter)]),
t.identifier('registerServerReference')
);

// Create the loop body
const loopBody = t.blockStatement([
t.ifStatement(
t.binaryExpression(
'===',
t.unaryExpression(
'typeof',
t.memberExpression(
t.memberExpression(t.identifier('module'), t.identifier('exports')),
t.identifier('key'),
true
)
),
t.stringLiteral('function')
),
t.expressionStatement(
t.callExpression(mmexp, [
t.memberExpression(
t.memberExpression(t.identifier('module'), t.identifier('exports')),
t.identifier('key'),
true
),
t.stringLiteral(outputKey),
t.identifier('key'),
])
)
),
]);

// Create the for-in loop
const forInStatement = t.forInStatement(
t.variableDeclaration('const', [t.variableDeclarator(t.identifier('key'))]),
t.memberExpression(t.identifier('module'), t.identifier('exports')),
loopBody
);

path.pushContainer(
'body',
t.expressionStatement(
t.callExpression(
t.arrowFunctionExpression(
[],

t.blockStatement([
t.ifStatement(
t.binaryExpression(
'===',
t.unaryExpression(
'typeof',
t.memberExpression(t.identifier('module'), t.identifier('exports'))
),
t.stringLiteral('function')
),
// registerServerReference(module.exports, moduleId, null);
t.blockStatement([
t.expressionStatement(
t.callExpression(mmexp, [
t.memberExpression(t.identifier('module'), t.identifier('exports')),
t.stringLiteral(outputKey),
t.nullLiteral(),
])
),
]),
// Else
t.blockStatement([
// for (const key in module.exports) {
// if (typeof module.exports[key] === 'function') {
// registerServerReference(module.exports[key], moduleId, key);
// }
// }
forInStatement,
])
),
])
),
[]
)
)
template.ast`
;(() => {
if (typeof module.exports === 'function') {
require('react-server-dom-webpack/server').registerServerReference(module.exports, ${JSON.stringify(
outputKey
)}, null);
} else {
for (const key in module.exports) {
if (typeof module.exports[key] === 'function') {
require('react-server-dom-webpack/server').registerServerReference(module.exports[key], ${JSON.stringify(
outputKey
)}, key);
}
}
}
})()`
);

//
}
},
},
Expand Down

0 comments on commit 6245632

Please sign in to comment.