Skip to content

Commit 13d99a6

Browse files
committed
add maxInlineSize option for size-based asset inlining
Assets whose largest scale variant is within the threshold are inlined as base64 URIs; larger assets are extracted as separate files. The option is supported in both the assets-loader directly and via getAssetTransformRules.
1 parent 13e7ed5 commit 13d99a6

4 files changed

Lines changed: 66 additions & 5 deletions

File tree

packages/repack/src/loaders/assetsLoader/assetsLoader.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,16 @@ export default async function repackAssetsLoader(
222222
})
223223
);
224224

225+
const largestVariantSize = Math.max(
226+
...assets.map((asset) => asset.data.length)
227+
);
228+
const shouldInlineAsset =
229+
options.inline === true ||
230+
(options.maxInlineSize !== undefined &&
231+
largestVariantSize <= options.maxInlineSize);
232+
225233
let result: string;
226-
if (options.inline) {
234+
if (shouldInlineAsset) {
227235
logger.debug(`Inlining assets for request ${resourcePath}`);
228236
result = inlineAssets({ assets, resourcePath });
229237
} else {

packages/repack/src/loaders/assetsLoader/options.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface AssetLoaderOptions {
1818
scalableAssetExtensions?: string[];
1919
scalableAssetResolutions?: string[];
2020
inline?: boolean;
21+
maxInlineSize?: number;
2122
publicPath?: string;
2223
remote?: AssetLoaderRemoteOptions;
2324
}
@@ -39,6 +40,7 @@ export const optionsSchema: Schema = {
3940
type: 'array',
4041
},
4142
inline: { type: 'boolean' },
43+
maxInlineSize: { type: 'number' },
4244
publicPath: { type: 'string' },
4345
remote: {
4446
type: 'object',

packages/repack/src/utils/getAssetTransformRules.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ interface GetAssetTransformRulesOptions {
3939
*/
4040
inline?: boolean;
4141

42+
/**
43+
* Maximum asset file size in bytes to inline as base64 URIs.
44+
* Assets larger than this threshold will be extracted as separate files.
45+
* Mutually exclusive with `inline`.
46+
*/
47+
maxInlineSize?: number;
48+
4249
/**
4350
* Configuration for remote asset loading.
4451
*/
@@ -57,14 +64,16 @@ interface GetAssetTransformRulesOptions {
5764
* Creates `module.rules` configuration for handling assets in React Native applications.
5865
*
5966
* @param options Configuration options
60-
* @param options.inline Whether to inline assets as base64 URIs (defaults to false)
67+
* @param options.inline Whether to inline all assets as base64 URIs (defaults to false)
68+
* @param options.maxInlineSize Maximum asset file size in bytes to inline as base64 URIs; larger assets are extracted as separate files
6169
* @param options.remote Configuration for remote asset loading with publicPath and optional assetPath function
6270
* @param options.svg Determines how SVG files should be processed ('svgr', 'xml', or 'uri')
6371
*
6472
* @returns Array of webpack/rspack rules for transforming assets
6573
*/
6674
export function getAssetTransformRules({
6775
inline,
76+
maxInlineSize,
6877
remote,
6978
svg,
7079
}: GetAssetTransformRulesOptions = {}) {
@@ -85,7 +94,7 @@ export function getAssetTransformRules({
8594
test: getAssetExtensionsRegExp(extensions),
8695
use: {
8796
loader: '@callstack/repack/assets-loader',
88-
options: { inline, remote: remoteOptions },
97+
options: { inline, maxInlineSize, remote: remoteOptions },
8998
},
9099
});
91100

website/src/latest/docs/guides/inline-assets.md

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,55 @@ import image from './image.png';
6161

6262
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.
6363

64-
## Selective inlining
64+
## Size-based inlining
65+
66+
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.
67+
68+
```js title="rspack.config.cjs"
69+
const Repack = require("@callstack/repack");
70+
71+
module.exports = {
72+
module: {
73+
rules: [
74+
{
75+
test: Repack.getAssetExtensionsRegExp(),
76+
use: {
77+
loader: "@callstack/repack/assets-loader",
78+
options: { maxInlineSize: 20 * 1024 }, // inline assets up to 20 KB
79+
},
80+
},
81+
],
82+
},
83+
};
84+
```
85+
86+
Or via the helper:
87+
88+
```js title="rspack.config.cjs"
89+
const Repack = require("@callstack/repack");
90+
91+
module.exports = {
92+
module: {
93+
rules: [...Repack.getAssetTransformRules({ maxInlineSize: 20 * 1024 })],
94+
},
95+
};
96+
```
97+
98+
:::info Scale variants and the size threshold
99+
100+
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.
101+
102+
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.
103+
104+
:::
105+
106+
## Selective inlining by path
65107

66108
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.
67109

68110
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.
69111

70-
```js title="rspack.config.mjs"
112+
```js title="rspack.config.cjs"
71113
const Repack = require("@callstack/repack");
72114

73115
module.exports = {

0 commit comments

Comments
 (0)