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(cli, router, babel): add router root to metro cache #25658

Merged
merged 8 commits into from
Nov 30, 2023
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
3 changes: 1 addition & 2 deletions apps/router-e2e/app.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ module.exports = {
'expo-router',
{
asyncRoutes: process.env.E2E_ROUTER_ASYNC,
// THIS WILL BREAK YOUR APP -- DO NOT USE!
unstable_src: path.join('__e2e__', process.env.E2E_ROUTER_SRC ?? 'static-rendering', 'app'),
root: path.join('__e2e__', process.env.E2E_ROUTER_SRC ?? 'static-rendering', 'app'),
origin: 'https://smart-symbiote.netlify.app/',
},
],
Expand Down
16 changes: 0 additions & 16 deletions apps/router-e2e/metro.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const { createMetroConfiguration } = require('expo-yarn-workspaces');
const { FileStore } = require('@expo/metro-config/file-store');

// Find the project and workspace directories
const projectRoot = __dirname;
Expand All @@ -21,19 +20,4 @@ config.resolver.blockList = [
/node_modules\/pretty-format\/node_modules\/react-is/,
];

config.cacheStores = [
// Ensure the cache isn't shared between projects
// this ensures the transform-time environment variables are changed to reflect
// the current project.
new FileStore({
root: path.join(
projectRoot,
'node_modules/.cache/metro',
process.env.E2E_ROUTER_SRC || 'app',
// TODO: Move app.json to serializer instead of babel plugin.
process.env.EXPO_E2E_BASE_PATH || '/'
),
}),
];

module.exports = config;
25 changes: 23 additions & 2 deletions docs/pages/router/reference/src-directory.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ As your project grows, it can be helpful to move all of the directories containi
files={['src/app/_layout.js', 'src/app/index.js', 'src/components/button.js', 'package.json']}
/>

Simply move your **app** directory to **src/app** and restart the development server with a clear cache:
Simply move your **app** directory to **src/app** and restart the development server.

<Terminal
cmd={['$ npx expo start --clear', '', '# Or when exporting', '$ npx expo export --clear']}
cmd={['$ npx expo start', '', '# Or export for production', '$ npx expo export']}
/>

**Notes**:
Expand All @@ -27,3 +27,24 @@ Simply move your **app** directory to **src/app** and restart the development se
- The **public** directory should remain in the root directory.
- Static rendering will automatically use the **src/app** directory if it exists.
- You may consider updating any [type aliases](/guides/typescript#path-aliases) to point to the **src** directory instead of the root directory.

## Custom directory

> Changing the default root directory is highly discouraged. We may not accept bug reports regarding projects with custom root directories.
EvanBacon marked this conversation as resolved.
Show resolved Hide resolved

You can dangerously customize the root directory using the Expo Router Config Plugin. The following will change the root directory to `src/routes`, relative to the project root.
EvanBacon marked this conversation as resolved.
Show resolved Hide resolved

```json app.json
{
"plugins": [
[
"expo-router",
{
"root": "./src/routes",
}
]
]
}
```

Again, this may lead to unexpected behavior. Many tools assume the root directory to be either `./app` or `./src/app`, only tools in the exact version of Expo CLI will respect the Config Plugin.
EvanBacon marked this conversation as resolved.
Show resolved Hide resolved
1 change: 1 addition & 0 deletions packages/@expo/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

### 🎉 New features

- Add custom Expo Router root directory support with full cache invalidation on server reset. ([#25658](https://github.com/expo/expo/pull/25658) by [@EvanBacon](https://github.com/EvanBacon))
- Add filenames to metro logs when finished. ([#25575](https://github.com/expo/expo/pull/25575) by [@EvanBacon](https://github.com/EvanBacon))
- Alias `react-native-vector-icons` to `@expo/vector-icons` in the Metro resolver. ([#25512](https://github.com/expo/expo/pull/25512) by [@EvanBacon](https://github.com/EvanBacon))
- Ensure invalid production iOS builds fail more predictably. ([#25410](https://github.com/expo/expo/pull/25410) by [@EvanBacon](https://github.com/EvanBacon))
Expand Down
2 changes: 1 addition & 1 deletion packages/@expo/cli/e2e/__tests__/start-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ describe('server', () => {

// URLs
expect(manifest.launchAsset.url).toBe(
'http://127.0.0.1:8081/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&transform.engine=hermes'
'http://127.0.0.1:8081/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&transform.engine=hermes&transform.routerRoot=app'
);
expect(manifest.extra.expoGo.debuggerHost).toBe('127.0.0.1:8081');
expect(manifest.extra.expoGo.mainModuleName).toBe('node_modules/expo/AppEntry');
Expand Down
8 changes: 2 additions & 6 deletions packages/@expo/cli/src/export/embed/exportEmbedAsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ import { Options } from './resolveOptions';
import { isExecutingFromXcodebuild, logMetroErrorInXcode } from './xcodeCompilerLogger';
import { Log } from '../../log';
import { loadMetroConfigAsync } from '../../start/server/metro/instantiateMetro';
import {
getBaseUrlFromExpoConfig,
getMetroDirectBundleOptions,
} from '../../start/server/middleware/metroOptions';
import { getMetroDirectBundleOptionsForExpoConfig } from '../../start/server/middleware/metroOptions';
import { stripAnsi } from '../../utils/ansi';
import { removeAsync } from '../../utils/dir';
import { setNodeEnv } from '../../utils/nodeEnv';
Expand Down Expand Up @@ -108,13 +105,12 @@ export async function exportEmbedBundleAsync(projectRoot: string, options: Optio

const bundleRequest = {
...Server.DEFAULT_BUNDLE_OPTIONS,
...getMetroDirectBundleOptions({
...getMetroDirectBundleOptionsForExpoConfig(projectRoot, exp, {
mainModuleName: options.entryFile,
platform: options.platform,
minify: options.minify,
mode: options.dev ? 'development' : 'production',
engine: isHermes ? 'hermes' : undefined,
baseUrl: getBaseUrlFromExpoConfig(exp),
isExporting: true,
}),
sourceMapUrl,
Expand Down
2 changes: 2 additions & 0 deletions packages/@expo/cli/src/export/exportApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { Options } from './resolveOptions';
import { ExportAssetMap, getFilesFromSerialAssets, persistMetroFilesAsync } from './saveAssets';
import { createAssetMap, createSourceMapDebugHtml } from './writeContents';
import * as Log from '../log';
import { getRouterDirectoryModuleIdWithManifest } from '../start/server/metro/router';
import { serializeHtmlWithAssets } from '../start/server/metro/serializeHtml';
import { getBaseUrlFromExpoConfig } from '../start/server/middleware/metroOptions';
import { createTemplateHtmlFromExpoConfigAsync } from '../start/server/webTemplate';
Expand Down Expand Up @@ -146,6 +147,7 @@ export async function exportAppAsync(
includeSourceMaps: sourceMaps,
// @ts-expect-error: server not on type yet
exportServer: exp.web?.output === 'server',
routerRoot: getRouterDirectoryModuleIdWithManifest(projectRoot, exp),
});
} else {
// TODO: Unify with exportStaticAsync
Expand Down
30 changes: 18 additions & 12 deletions packages/@expo/cli/src/export/exportStaticAsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { getConfig } from '@expo/config';
import assert from 'assert';
import chalk from 'chalk';
import fs from 'fs';
Expand All @@ -19,10 +18,7 @@ import { DevServerManager } from '../start/server/DevServerManager';
import { MetroBundlerDevServer } from '../start/server/metro/MetroBundlerDevServer';
import { ExpoRouterServerManifestV1 } from '../start/server/metro/fetchRouterManifest';
import { logMetroErrorAsync } from '../start/server/metro/metroErrorInterface';
import {
getApiRoutesForDirectory,
getRouterDirectoryWithManifest,
} from '../start/server/metro/router';
import { getApiRoutesForDirectory } from '../start/server/metro/router';
import { serializeHtmlWithAssets } from '../start/server/metro/serializeHtml';
import { learnMore } from '../utils/link';
import { getFreePortAsync } from '../utils/port';
Expand All @@ -38,6 +34,7 @@ type Options = {
includeSourceMaps: boolean;
entryPoint?: string;
clear: boolean;
routerRoot: string;
};

/** @private */
Expand Down Expand Up @@ -121,10 +118,17 @@ export async function getFilesToExportFromServerAsync(
async function exportFromServerAsync(
projectRoot: string,
devServerManager: DevServerManager,
{ outputDir, baseUrl, exportServer, minify, includeSourceMaps, files = new Map() }: Options
{
outputDir,
baseUrl,
exportServer,
minify,
includeSourceMaps,
routerRoot,
files = new Map(),
}: Options
): Promise<ExportAssetMap> {
const { exp } = getConfig(projectRoot, { skipSDKVersionRequirement: true });
const appDir = getRouterDirectoryWithManifest(projectRoot, exp);
const appDir = path.join(projectRoot, routerRoot);
const injectFaviconTag = await getVirtualFaviconAssetsAsync(projectRoot, {
outputDir,
baseUrl,
Expand All @@ -141,11 +145,13 @@ async function exportFromServerAsync(
minify,
includeSourceMaps,
baseUrl,
routerRoot,
}),
devServer.getStaticRenderFunctionAsync({
mode: 'production',
minify,
baseUrl,
routerRoot,
}),
]);

Expand Down Expand Up @@ -193,7 +199,7 @@ async function exportFromServerAsync(
const apiRoutes = await exportApiRoutesAsync({
outputDir,
server: devServer,
appDir,
routerRoot,
manifest: serverManifest,
baseUrl,
});
Expand Down Expand Up @@ -314,13 +320,13 @@ export function getPathVariations(routePath: string): string[] {
async function exportApiRoutesAsync({
outputDir,
server,
appDir,
routerRoot,
baseUrl,
...props
}: {
outputDir: string;
server: MetroBundlerDevServer;
appDir: string;
routerRoot: string;
manifest: ExpoRouterServerManifestV1;
baseUrl: string;
}): Promise<ExportAssetMap> {
Expand All @@ -330,7 +336,7 @@ async function exportApiRoutesAsync({

const { manifest, files } = await server.exportExpoRouterApiRoutesAsync({
mode: 'production',
appDir,
routerRoot,
outputDir: functionsDir,
prerenderManifest: props.manifest,
baseUrl,
Expand Down
6 changes: 2 additions & 4 deletions packages/@expo/cli/src/export/fork-bundleAsync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ import { loadMetroConfigAsync } from '../start/server/metro/instantiateMetro';
import { getEntryWithServerRoot } from '../start/server/middleware/ManifestMiddleware';
import {
ExpoMetroBundleOptions,
getBaseUrlFromExpoConfig,
getMetroDirectBundleOptions,
getMetroDirectBundleOptionsForExpoConfig,
} from '../start/server/middleware/metroOptions';

export type MetroDevServerOptions = LoadOptions;
Expand Down Expand Up @@ -137,7 +136,7 @@ async function bundleProductionMetroClientAsync(
const bundleOptions: MetroBundleOptions = {
...Server.DEFAULT_BUNDLE_OPTIONS,
sourceMapUrl: bundle.sourceMapUrl,
...getMetroDirectBundleOptions({
...getMetroDirectBundleOptionsForExpoConfig(projectRoot, expoConfig, {
mainModuleName: bundle.entryPoint,
platform: bundle.platform,
mode: bundle.dev ? 'development' : 'production',
Expand All @@ -147,7 +146,6 @@ async function bundleProductionMetroClientAsync(
// serializerOutput: bundle.platform === 'web' ? 'static' : undefined,
serializerOutput: 'static',
serializerIncludeBytecode: isHermes,
baseUrl: getBaseUrlFromExpoConfig(expoConfig),
isExporting: true,
}),
bundleType: 'bundle',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type StaticRenderOptions = {
environment?: 'node';
engine?: 'hermes';
baseUrl: string;
routerRoot: string;
};

const moveStaticRenderFunction = memoize(async (projectRoot: string, requiredModuleId: string) => {
Expand All @@ -66,7 +67,7 @@ const moveStaticRenderFunction = memoize(async (projectRoot: string, requiredMod
async function getStaticRenderFunctionsContentAsync(
projectRoot: string,
devServerUrl: string,
{ dev = false, minify = false, environment, baseUrl }: StaticRenderOptions
{ dev = false, minify = false, environment, baseUrl, routerRoot }: StaticRenderOptions
): Promise<string> {
const root = getMetroServerRoot(projectRoot);
const requiredModuleId = getRenderModuleId(root);
Expand All @@ -83,6 +84,7 @@ async function getStaticRenderFunctionsContentAsync(
minify,
environment,
baseUrl,
routerRoot,
});
}

Expand Down Expand Up @@ -115,6 +117,7 @@ export async function createMetroEndpointAsync(
environment,
engine = 'hermes',
baseUrl,
routerRoot,
}: StaticRenderOptions
): Promise<string> {
const root = getMetroServerRoot(projectRoot);
Expand All @@ -131,6 +134,7 @@ export async function createMetroEndpointAsync(
minify,
baseUrl,
isExporting: true,
routerRoot,
});

const url = new URL(urlFragment.replace(/^\//, ''), devServerUrl).toString();
Expand Down