Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion packages/repack/src/loaders/assetsLoader/assetsLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,16 @@ export default async function repackAssetsLoader(
})
);

const largestVariantSize = Math.max(
...assets.map((asset) => asset.data.length)
);
const shouldInlineAsset =
options.inline === true ||
(options.maxInlineSize !== undefined &&
largestVariantSize <= options.maxInlineSize);

let result: string;
if (options.inline) {
if (shouldInlineAsset) {
logger.debug(`Inlining assets for request ${resourcePath}`);
result = inlineAssets({ assets, resourcePath });
} else {
Expand Down
2 changes: 2 additions & 0 deletions packages/repack/src/loaders/assetsLoader/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export interface AssetLoaderOptions {
scalableAssetExtensions?: string[];
scalableAssetResolutions?: string[];
inline?: boolean;
maxInlineSize?: number;
publicPath?: string;
remote?: AssetLoaderRemoteOptions;
}
Expand All @@ -39,6 +40,7 @@ export const optionsSchema: Schema = {
type: 'array',
},
inline: { type: 'boolean' },
maxInlineSize: { type: 'number' },
publicPath: { type: 'string' },
remote: {
type: 'object',
Expand Down
13 changes: 11 additions & 2 deletions packages/repack/src/utils/getAssetTransformRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ interface GetAssetTransformRulesOptions {
*/
inline?: boolean;

/**
* Maximum asset file size in bytes to inline as base64 URIs.
* Assets larger than this threshold will be extracted as separate files.
* Mutually exclusive with `inline`.
*/
maxInlineSize?: number;

/**
* Configuration for remote asset loading.
*/
Expand All @@ -57,14 +64,16 @@ interface GetAssetTransformRulesOptions {
* Creates `module.rules` configuration for handling assets in React Native applications.
*
* @param options Configuration options
* @param options.inline Whether to inline assets as base64 URIs (defaults to false)
* @param options.inline Whether to inline all assets as base64 URIs (defaults to false)
* @param options.maxInlineSize Maximum asset file size in bytes to inline as base64 URIs; larger assets are extracted as separate files
* @param options.remote Configuration for remote asset loading with publicPath and optional assetPath function
* @param options.svg Determines how SVG files should be processed ('svgr', 'xml', or 'uri')
*
* @returns Array of webpack/rspack rules for transforming assets
*/
export function getAssetTransformRules({
inline,
maxInlineSize,
remote,
svg,
}: GetAssetTransformRulesOptions = {}) {
Expand All @@ -85,7 +94,7 @@ export function getAssetTransformRules({
test: getAssetExtensionsRegExp(extensions),
use: {
loader: '@callstack/repack/assets-loader',
options: { inline, remote: remoteOptions },
options: { inline, maxInlineSize, remote: remoteOptions },
},
});

Expand Down
46 changes: 44 additions & 2 deletions website/src/latest/docs/guides/inline-assets.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,55 @@ import image from './image.png';

The value of `image` in this example would be either an object with `uri`, `width`, `height` and `scale` or an array of such objects, in case there are multiple scales.

## Selective inlining
## Size-based inlining

Instead of inlining all assets unconditionally, you can use `maxInlineSize` to set a file size threshold in bytes. Assets whose **largest scale variant** is smaller than or equal to the threshold will be inlined; larger assets will be extracted as separate files.

```js title="rspack.config.cjs"
const Repack = require("@callstack/repack");

module.exports = {
module: {
rules: [
{
test: Repack.getAssetExtensionsRegExp(),
use: {
loader: "@callstack/repack/assets-loader",
options: { maxInlineSize: 20 * 1024 }, // inline assets up to 20 KB
},
},
],
},
};
```

Or via the helper:

```js title="rspack.config.cjs"
const Repack = require("@callstack/repack");

module.exports = {
module: {
rules: [...Repack.getAssetTransformRules({ maxInlineSize: 20 * 1024 })],
},
};
```

:::info Scale variants and the size threshold

The threshold is compared against the **largest scale variant** of the asset (e.g. `@3x`), not the `@1x` file. This is intentional — when an asset is inlined, all scale variants are embedded into the bundle, so the largest one is what determines the worst-case size impact.

For example, a `@1x` PNG that is 10 KB may have a `@3x` variant of 80 KB. With `maxInlineSize: 20 * 1024` the asset would be extracted, not inlined, because the `@3x` variant exceeds the threshold.

:::

## Selective inlining by path

You can provide multiple rules with Re.Pack's [Assets loader](/api/loaders/assets-loader) - one rule would extract the assets and another would inline them. There's no limit how many of these rules you could have.

Make sure you configure those rules not to overlap, so that any single asset is only processed by one rule (by one [Assets loader](/api/loaders/assets-loader)). Use combination of `include`, `exclude` and `test` (for extensions matching) to configure each rule.

```js title="rspack.config.mjs"
```js title="rspack.config.cjs"
const Repack = require("@callstack/repack");

module.exports = {
Expand Down