Skip to content

feat: add asset handling plugin for esbuild-service using Metro's getAssetData()#4018

Draft
Copilot wants to merge 3 commits intomainfrom
copilot/analyze-metro-bundler-replacements
Draft

feat: add asset handling plugin for esbuild-service using Metro's getAssetData()#4018
Copilot wants to merge 3 commits intomainfrom
copilot/analyze-metro-bundler-replacements

Conversation

Copy link
Contributor

Copilot AI commented Mar 9, 2026

Implements the asset handling plugin for @rnx-kit/esbuild-service, completing the Metro → esbuild replacement story for production bundling. The plugin reuses Metro's own getAssetData() implementation for scale variant discovery, MD5 hashing, and image dimension reading — only the code generation step is reimplemented as a JS string instead of a Babel AST.

incubator/esbuild-service

  • src/plugins/assets.ts — new reactNativeAssets esbuild plugin:
    • Intercepts imports of image/font/media files (all Metro-default asset extensions via DEFAULT_ASSET_EXTS)
    • Calls metro/src/Assets.getAssetData() directly when Metro is available; falls back to a minimal implementation otherwise
    • Emits module.exports = require(assetRegistryPath).registerAsset({...}) — identical output to metro-transform-worker's assetTransformer
    • getCollectedAssets() is attached as a non-enumerable property so esbuild's plugin-option validator doesn't reject it
  • src/bundle.ts — wires in the assets plugin; after bundling, copies assets to assetsDest via @rnx-kit/metro-service/assets
  • src/types.ts — adds assetsDest, assetCatalogDest, assetDataPlugins to BundleServiceOptions
const assetsPlugin = reactNativeAssets({ platform: "ios", projectRoot });

await esbuild.build({ plugins: [assetsPlugin], ... });

// CollectedAssets can be passed to saveAssets() to copy files to disk
const assets = assetsPlugin.getCollectedAssets();

packages/metro-service

  • src/assets.ts — new file re-exporting saveAssets, getSaveAssetsPlugin, and related types
  • package.json — adds "./assets" subpath export so esbuild-service can consume these utilities without importing from internal paths

Test plan

cd incubator/esbuild-service
yarn test

9 new tests in test/assets.test.ts cover: registerAsset code generation, asset collection, @2x/@3x scale variant discovery, custom assetRegistryPath, blocklisted properties (files, fileSystemLocation) excluded from output, and custom publicPath.

Original prompt

Analyze Metro bundler (https://github.com/facebook/metro) and outline which parts can be replaced by esbuild (https://github.com/evanw/esbuild). Which parts needs to be reimplemented, and how much code can be reused to reimplement said parts.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Analyze Metro bundler parts for replacement with esbuild feat: add @rnx-kit/esbuild-service — Metro-independent esbuild bundler for React Native Mar 9, 2026
Copilot AI changed the title feat: add @rnx-kit/esbuild-service — Metro-independent esbuild bundler for React Native feat: add asset handling plugin for esbuild-service using Metro's getAssetData() Mar 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants