Поле output.inlineDynamicImports управляет поведением
Rollup при обработке динамических импортов (import()). По
умолчанию Rollup воспринимает динамический импорт как точку разделения
кода и создаёт отдельные чанки. При включении
inlineDynamicImports все модули объединяются в один
итоговый файл, а динамические импорты перестают генерировать отдельные
чанки.
Поле относится к секции output:
export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.js',
format: 'esm',
inlineDynamicImports: true
}
};
inlineDynamicImportsИсходный код:
// main.js
button.addEventListener('click', async () => {
const module = await import('./dialog.js');
module.openDialog();
});
// dialog.js
export function openDialog() {
console.log('dialog opened');
}
Стандартное поведение Rollup:
dist/
├── main.js
└── dialog-8d1f4.js
Главный файл содержит ссылку на дополнительный чанк:
import('./dialog-8d1f4.js');
Такой режим называется code splitting — разделение кода на независимые части.
inlineDynamicImports: trueЕсли включить опцию:
output: {
file: 'dist/bundle.js',
format: 'esm',
inlineDynamicImports: true
}
Rollup перестанет создавать дополнительные чанки:
dist/
└── bundle.js
Содержимое dialog.js будет встроено в итоговый
бандл.
Rollup:
import()Пример:
await import('./dialog-8d1f4.js');
Rollup:
Пример результирующего кода:
Promise.resolve().then(() => dialogModule);
или:
async function () {
return dialogModule;
}
Асинхронность формально сохраняется, но реальной загрузки файла уже нет.
Главное назначение — получение единственного итогового
файла, даже если проект использует import().
Это особенно важно в следующих случаях:
inlineDynamicImports несовместим с множественными
входными точками.
Ошибка:
Invalid value for option "output.inlineDynamicImports" -
multiple inputs are not supported when "output.inlineDynamicImports" is true.
Нельзя:
export default {
input: {
app: 'src/app.js',
admin: 'src/admin.js'
},
output: {
dir: 'dist',
inlineDynamicImports: true
}
};
Разрешён только один input:
export default {
input: 'src/main.js',
output: {
file: 'dist/bundle.js',
inlineDynamicImports: true
}
};
Обычно inlineDynamicImports используют вместе с
output.file.
Пример:
output: {
file: 'dist/app.js',
format: 'cjs',
inlineDynamicImports: true
}
Использование с output.dir технически возможно, но
теряет смысл, потому что Rollup всё равно генерирует один файл.
Разделение кода — одна из ключевых возможностей Rollup.
Стандартное поведение обеспечивает:
inlineDynamicImports отключает все преимущества code
splitting.
import { api } from './api.js';
Rollup всегда объединяет такой импорт в основной бандл.
const api = await import('./api.js');
По умолчанию создаётся отдельный чанк.
output: {
inlineDynamicImports: true
}
Результат:
api.js встраивается внутрь бандла;src/
├── main.js
├── editor.js
└── preview.js
async function loadEditor() {
const editor = await import('./editor.js');
editor.start();
}
async function loadPreview() {
const preview = await import('./preview.js');
preview.render();
}
export default {
input: 'src/main.js',
output: {
dir: 'dist',
format: 'esm'
}
};
Результат:
dist/
├── main.js
├── editor-4f2a1.js
└── preview-a9c33.js
export default {
input: 'src/main.js',
output: {
file: 'dist/app.js',
format: 'esm',
inlineDynamicImports: true
}
};
Результат:
dist/
└── app.js
inlineDynamicImports почти всегда увеличивает размер
стартового файла.
Причина очевидна:
main.js 80 KB
editor chunk 200 KB
preview chunk 150 KB
Initial load:
80 KB
app.js 430 KB
Initial load:
430 KB
Некоторые среды требуют один JS-файл:
plugin.js
без:
chunk-XYZ.js
CLI-инструменты часто распространяются как единый файл:
node cli.js
Дополнительные чанки усложняют публикацию.
Расширения браузера иногда ограничивают структуру файлов.
Особенно:
Preload-скрипты обычно хотят:
Виджеты для вставки на сторонние сайты часто публикуются так:
<script src="widget.js"></script>
Наличие дополнительных чанков ломает такую модель.
Для фронтенд-приложений почти всегда лучше code splitting.
Иначе:
Пример:
const page = await import('./pages/admin.js');
С inlineDynamicImports административная часть загрузится
сразу, даже если пользователь никогда туда не перейдёт.
Особенно проблемно:
Работает наиболее естественно.
output: {
format: 'esm',
inlineDynamicImports: true
}
Rollup преобразует динамические импорты под CommonJS.
output: {
format: 'cjs',
inlineDynamicImports: true
}
Частый сценарий для standalone-виджетов.
output: {
file: 'dist/widget.js',
format: 'iife',
name: 'Widget',
inlineDynamicImports: true
}
Тоже поддерживается:
output: {
format: 'umd',
inlineDynamicImports: true
}
inlineDynamicImports несовместим с
preserveModules.
Нельзя одновременно:
output: {
preserveModules: true,
inlineDynamicImports: true
}
Причина:
preserveModules сохраняет файловую структуру;inlineDynamicImports объединяет всё в один файл.Это противоположные стратегии сборки.
Rollup не удаляет import() полностью.
Вместо этого создаётся внутренняя обёртка.
const module = await import('./feature.js');
const module = await Promise.resolve().then(function () {
return featureModule;
});
Так сохраняется совместимость с асинхронной моделью.
Tree shaking продолжает работать.
Даже с inlineDynamicImports Rollup:
Однако весь используемый код всё равно попадает в основной файл.
Позволяет вручную разделять код:
output: {
manualChunks: {
vendor: ['react']
}
}
Наоборот, запрещает разделение:
output: {
inlineDynamicImports: true
}
Сохраняет отдельные файлы:
dist/
├── main.js
├── utils.js
└── api.js
Создаёт единый файл:
dist/
└── bundle.js
Ошибка:
multiple inputs are not supported
Ошибка конфликта стратегий сборки.
Многие ошибочно предполагают, что import() продолжит
лениво загружать код.
При inlineDynamicImports этого не происходит.
После включения опции размер initial bundle может вырасти в несколько раз.
export default {
input: 'src/index.js',
output: {
file: 'dist/library.js',
format: 'umd',
name: 'MyLibrary',
inlineDynamicImports: true
}
};
Такой подход обеспечивает:
<script>.export default {
input: 'src/cli.js',
output: {
file: 'bin/cli.js',
format: 'cjs',
banner: '#!/usr/bin/env node',
inlineDynamicImports: true
}
};
Результат:
Опция меняет фундаментальную модель сборки:
entry
├── chunk A
├── chunk B
└── chunk C
entry
└── single bundle
| Поведение | inlineDynamicImports: false | inlineDynamicImports: true |
|---|---|---|
| Code splitting | Да | Нет |
| Дополнительные чанки | Да | Нет |
| Lazy loading | Да | Нет |
| Один итоговый файл | Нет | Да |
| Поддержка multiple input | Да | Нет |
| Совместимость с preserveModules | Да | Нет |
| Размер initial bundle | Меньше | Больше |
| Простота деплоя | Ниже | Выше |