了解可定制的不同 Metro 打包器配置。
Expo CLI 在 npx expo start
和 npx expo export
期间使用 Metro 来打包你的 JavaScript 代码和资源。Metro 是针对 React Native 构建和优化的,用于 Facebook 和 Instagram 等大型应用。
¥Expo CLI uses Metro during npx expo start
and npx expo export
to bundle your JavaScript code and assets. Metro is built and optimized for React Native and used for large-scale applications such as Facebook and Instagram.
¥Customizing
你可以通过在项目根目录下创建 Metro.config.js 文件来自定义 Metro 打包程序。该文件应导出扩展 expo/metro-config
的 Metro 配置。导入 expo/metro-config
而不是 @expo/metro-config
,以保证版本一致性。
¥You can customize the Metro bundler by creating a metro.config.js file at the root of your project. This file should export a Metro configuration that extends expo/metro-config
. Import expo/metro-config
instead of @expo/metro-config
to ensure version consistency.
运行以下命令生成模板文件:
¥Run the following command to generate the template file:
-
npx expo customize metro.config.js
Metro.config.js 文件如下所示:
¥The metro.config.js file looks as below:
const { getDefaultConfig } = require('expo/metro-config');
const config = getDefaultConfig(__dirname);
module.exports = config;
请参阅 Metro.config.js 文档 了解更多信息。
¥See metro.config.js documentation for more information.
¥Assets
Metro 将文件解析为源代码或资源。源代码是 JavaScript、TypeScript、JSON 和应用使用的其他文件。资源 是不应由 Metro 转换的图片、字体和其他文件。为了适应大规模代码库,Metro 要求在启动打包器之前显式定义源代码和资源的所有扩展。这是通过将 resolver.sourceExts
和 resolver.assetExts
选项添加到 Metro 配置来完成的。默认情况下,包含以下扩展:
¥Metro resolves files as either source code or assets. Source code is JavaScript, TypeScript, JSON, and other files used by your application. Assets are images, fonts, and other files that should not be transformed by Metro. To accommodate large-scale codebases, Metro requires all extensions for both source code and assets to be explicitly defined before starting the bundler. This is done by adding the resolver.sourceExts
and resolver.assetExts
options to the Metro configuration. By default, the following extensions are included:
assetExts
添加更多文件扩展名¥Adding more file extensions to assetExts
最常见的定制是包含 Metro 的额外资源扩展。
¥The most common customization is to include extra asset extensions to Metro.
在 Metro.config.js 文件中,将文件扩展名(不带前导 .
)添加到 resolver.assetExts
数组:
¥In the metro.config.js file, add the file extension (without a leading .
) to resolver.assetExts
array:
const { getDefaultConfig } = require('expo/metro-config');
const config = getDefaultConfig(__dirname);
config.resolver.assetExts.push(
// Adds support for `.db` files for SQLite databases
'db'
);
module.exports = config;
¥Aliases
有时你希望将导入重定向到另一个模块或文件。这称为别名。由于 Metro 同时为多个平台打包的方式,我们建议使用自定义解析器来处理别名。
¥Sometimes you want an import to be redirected to another module or file. This is called an alias. Due to the way Metro bundles for multiple platforms simultaneously, we recommend using a custom resolver to handle aliases.
在下面的示例中,我们将为 old-module
到 new-module
添加一个别名:
¥In the following example, we'll add an alias for old-module
to new-module
:
const { getDefaultConfig } = require('expo/metro-config');
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);
const ALIASES = {
'old-module': 'new-module',
};
config.resolver.resolveRequest = (context, moduleName, platform) => {
// Ensure you call the default resolver.
return context.resolveRequest(
context,
// Use an alias if one exists.
ALIASES[moduleName] ?? moduleName,
platform
);
};
module.exports = config;
如果你只想在某个平台上应用别名,你可以检查 platform
参数:
¥If you want to only apply the alias on a certain platform, you can check the platform
argument:
config.resolver.resolveRequest = (context, moduleName, platform) => {
if (platform === 'web') {
// The alias will only be used when bundling for the web.
return context.resolveRequest(context, ALIASES[moduleName] ?? moduleName, platform);
}
// Ensure you call the default resolver.
return context.resolveRequest(context, moduleName, platform);
};
你将在下次重新启动开发服务器时看到更改。解析永远不会被缓存,不需要 --clear
标志来更新。如果你使用像 babel-plugin-module-resolver
这样的基于转换的系统,则需要清除缓存才能看到应用的更改。
¥You will see the changes the next time you restart the dev server. Resolutions are never cached and do not need the --clear
flag to update. If you use a transform-based system like babel-plugin-module-resolver
, you will need to clear the cache to see changes applied.
了解有关项目中高级 Metro 解析的更多信息。
¥Bundle splitting
从 SDK 50 开始,Expo CLI 根据异步导入(仅限 Web)自动拆分打包包。
¥From SDK 50, Expo CLI automatically splits bundles based on async imports (web-only).
此技术可与 Expo Router 一起使用,根据应用目录中的路由文件自动拆分包。它将仅加载当前路由所需的代码,并推迟加载其他 JavaScript,直到用户导航到不同的页面。请参阅 异步路由 了解更多信息。
¥This technique can be used with Expo Router to automatically split the bundle based on route files in the app directory. It will only load the code required for the current route, and defer loading additional JavaScript until the user navigates to different pages. See Async Routes for more information.
¥Tree shaking
了解 Expo CLI 如何优化生产 JavaScript 包。
¥Minification
了解如何使用 Metro 打包程序在 Expo CLI 中自定义 JavaScript 缩小流程。
¥Web support
Expo CLI 支持使用 Metro 打包网站。这与用于原生应用的打包器相同,并且它被设计为跨平台通用。它是 Expo SDK 50 及更高版本中 Web 项目的推荐打包程序。
¥Expo CLI has support for bundling websites using Metro. This is the same bundler used for native apps, and it is designed to be universal across platforms. It is the recommended bundler for web projects in Expo SDK 50 and greater.
¥Expo webpack versus Expo Metro
如果你之前使用已弃用的 @expo/webpack-adapter
编写网站,请参阅 迁移指南 和 对比图。
¥If you previously wrote your website using the deprecated @expo/webpack-adapter
, see the migration guide and comparison chart.
¥Adding Web support to Metro
使用 expo.web.bundler
字段修改你的 应用配置 以启用该功能:
¥Modify your app config to enable the feature using the expo.web.bundler
field:
{
"expo": {
"web": {
"bundler": "metro"
}
}
}
¥Development
要启动开发服务器,请运行以下命令:
¥To start the development server run the following command:
-
npx expo start --web
或者,在 Expo CLI 终端 UI 中按 W。
¥Alternatively, press W in the Expo CLI terminal UI.
¥Static files
Expo 的 Metro 实现支持通过将静态文件放置在根 public/ 目录中来托管来自开发服务器的静态文件。它与许多其他 Web 框架类似。
¥Expo's Metro implementation supports hosting static files from the dev server by putting them in the root public/ directory. It is similar to many other web frameworks.
使用 npx expo export
导出时,public 目录的内容被复制到 dist/目录中。这意味着你的应用可以获取相对于主机 URL 的这些资源。最常见的示例是 public/favicon.ico,网站使用它来渲染选项卡图标。
¥When exporting with npx expo export
, the contents of the public directory are copied into the dist/ directory. It means your app can expect to fetch these assets relative to the host URL. The most common example of this is the public/favicon.ico which is used by websites to render the tab icon.
你可以通过在项目中创建 public/index.html 文件来覆盖 Metro web 中的默认 index.html。
¥You can overwrite the default index.html in Metro web by creating a public/index.html file in your project.
将来,这将通过 EAS 更新托管在跨平台上普遍使用。目前,该功能仅限于 Web,基于用于原生应用的静态主机,例如,旧版 Expo 服务更新不支持此功能。
¥In the future, this will work universally across platforms with EAS Update hosting. Currently, the feature is web-only based on the static host used for the native app, for example, the legacy Expo service updates do not support this feature.
在 SDK 49 及更高版本中可用。
¥Available in SDK 49 and higher.
Expo 的 Metro 配置支持项目的 tsconfig.json(或 jsconfig.json)文件中的 compilerOptions.paths
和 compilerOptions.baseUrl
字段。这可以在项目中启用绝对导入和别名。有关详细信息,请参阅 TypeScript 指南。
¥Expo's Metro config supports the compilerOptions.paths
and compilerOptions.baseUrl
fields in the project's tsconfig.json (or jsconfig.json) file. This enables absolute imports and aliases in the project. See TypeScript guide for more information.
此功能需要在裸项目中进行额外设置。请参阅 Metro 设置指南 了解更多信息。
¥This feature requires additional setup in bare projects. See the Metro setup guide for more information.
了解如何在与 Expo CLI 和 Metro 打包程序打包的网站中使用 CSS。