Модули активов
Модули активов позволяют использовать файлы активов (шрифты, значки и т. д.) без настройки дополнительных загрузчиков.
До webpack 5 было принято использовать:
-
raw-loaderдля импорта файла в виде строки -
url-loaderдля встраивания файла в бандл как URI данных -
file-loaderдля вывода файла в выходную директорию
Типы модулей активов заменяют все эти загрузчики, добавив 4 новых типа модулей:
-
asset/resourceвыводит отдельный файл и экспортирует URL. Раньше это было достижимо с помощьюfile-loader. -
asset/inlineэкспортирует URI данных актива. Раньше это было достижимо с помощьюurl-loader. -
asset/sourceэкспортирует исходный код актива. Раньше это было достижимо с помощьюraw-loader. -
assetавтоматически выбирает между экспортом URI данных и выводом отдельного файла. Раньше это было достижимо с помощьюurl-loaderс ограничением размера актива.
При использовании старых загрузчиков активов (например, file-loader/url-loader/raw-loader) вместе с модулями активов в webpack 5, вы можете захотеть остановить обработку ваших активов модулями активов, так как это может привести к дублированию активов. Это можно сделать, установив тип модуля актива в 'javascript/auto'.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
}
},
],
+ type: 'javascript/auto'
},
]
},
} Чтобы исключить активы, полученные из новых вызовов URL, из загрузчиков активов, добавьте dependency: { not: ['url'] } в конфигурацию загрузчика.
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/i,
+ dependency: { not: ['url'] },
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
},
},
],
},
],
}
} Путь к общедоступным ресурсам
По умолчанию, в скрытом режиме, тип asset выполняет __webpack_public_path__ + import.meta. Это означает, что установка output.publicPath в вашей конфигурации позволит вам переопределить URL, из которого asset загружает.
Переопределение на лету
Если вы установите __webpack_public_path__ в коде, чтобы не сломать логику загрузки asset, необходимо убедиться, что вы запускаете его как первый код в вашем приложении и не используете функцию для этого. Пример - файл под названием publicPath.js с содержимым
__webpack_public_path__ = 'https://cdn.url.com';
А затем в вашем webpack.config.js обновите поле entry следующим образом:
module.exports = {
entry: ['./publicPath.js', './App.js'],
}; В качестве альтернативы, вы можете сделать следующее в вашем App.js без изменения конфигурации webpack. Единственный недостаток заключается в том, что вам нужно навязать порядок, и это может столкнуться с некоторыми инструментами проверки кода.
import './publicPath.js';
Ресурсные активы
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
+ module: {
+ rules: [
+ {
+ test: /\.png/,
+ type: 'asset/resource'
+ }
+ ]
+ },
}; src/index.js
import mainImage from './images/main.png'; img.src = mainImage; // '/dist/151cfcfa1bd74779aadb.png'
Все .png файлы будут выводиться в выходную директорию, а их пути будут внедрены в бандлы. Кроме того, вы можете настроить outputPath и publicPath для них.
Настройка имени выходного файла
По умолчанию, модули asset/resource выводят файлы с именем [hash][ext][query] в выходную директорию.
Вы можете изменить эту шаблон, установив output.assetModuleFilename в вашей конфигурации webpack:
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
+ assetModuleFilename: 'images/[hash][ext][query]'
},
module: {
rules: [
{
test: /\.png/,
type: 'asset/resource'
}
]
},
}; Еще один случай для настройки имени выходного файла - вывести определенные активы в указанную директорию:
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
+ assetModuleFilename: 'images/[hash][ext][query]'
},
module: {
rules: [
{
test: /\.png/,
type: 'asset/resource'
- }
+ },
+ {
+ test: /\.html/,
+ type: 'asset/resource',
+ generator: {
+ filename: 'static/[hash][ext][query]'
+ }
+ }
]
},
}; С этой конфигурацией все html файлы будут выводиться в директорию static внутри выходной директории.
Rule.generator.filename аналогично output.assetModuleFilename и работает только с модулями типа asset и asset/resource.
Встраивание активов
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
- assetModuleFilename: 'images/[hash][ext][query]'
},
module: {
rules: [
{
- test: /\.png/,
- type: 'asset/resource'
+ test: /\.svg/,
+ type: 'asset/inline'
- },
+ }
- {
- test: /\.html/,
- type: 'asset/resource',
- generator: {
- filename: 'static/[hash][ext][query]'
- }
- }
]
}
}; src/index.js
- import mainImage from './images/main.png';
+ import metroMap from './images/metro.svg';
- img.src = mainImage; // '/dist/151cfcfa1bd74779aadb.png'
+ block.style.background = `url(${metroMap})`; // url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDo...vc3ZnPgo=) Все .svg файлы будут внедрены в бандлы как URI данных.
Пользовательский генератор URI данных
По умолчанию, URI данных, выводимые webpack, представляют содержимое файла, закодированное с помощью алгоритма Base64.
Если вы хотите использовать пользовательский алгоритм кодирования, вы можете указать пользовательскую функцию для кодирования содержимого файла:
webpack.config.js
const path = require('path');
+ const svgToMiniDataURI = require('mini-svg-data-uri');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.svg/,
type: 'asset/inline',
+ generator: {
+ dataUrl: content => {
+ content = content.toString();
+ return svgToMiniDataURI(content);
+ }
+ }
}
]
},
}; Теперь все .svg файлы будут закодированы пакетом mini-svg-data-uri.
Исходные активы
webpack.config.js
const path = require('path');
- const svgToMiniDataURI = require('mini-svg-data-uri');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
- test: /\.svg/,
- type: 'asset/inline',
- generator: {
- dataUrl: content => {
- content = content.toString();
- return svgToMiniDataURI(content);
- }
- }
+ test: /\.txt/,
+ type: 'asset/source',
}
]
},
}; src/example.txt
Hello world
src/index.js
- import metroMap from './images/metro.svg';
+ import exampleText from './example.txt';
- block.style.background = `url(${metroMap}); // url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDo...vc3ZnPgo=)
+ block.textContent = exampleText; // 'Hello world' Все .txt файлы будут внедрены в бандлы как есть.
URL-активы
При использовании new URL('./path/to/asset', import.meta.url), webpack также создает модуль актива.
src/index.js
const logo = new URL('./logo.svg', import.meta.url); В зависимости от target в вашей конфигурации, webpack скомпилирует указанный код в другой результат:
// target: web
new URL(
__webpack_public_path__ + 'logo.svg',
document.baseURI || self.location.href
);
// target: webworker
new URL(__webpack_public_path__ + 'logo.svg', self.location);
// target: node, node-webkit, nwjs, electron-main, electron-renderer, electron-preload, async-node
new URL(
__webpack_public_path__ + 'logo.svg',
require('url').pathToFileUrl(__filename)
); Начиная с webpack 5.38.0, Data URLs поддерживаются в new URL() также:
src/index.js
const url = new URL('data:,', import.meta.url);
console.log(url.href === 'data:,');
console.log(url.protocol === 'data:');
console.log(url.pathname === ','); Общие типы активов
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
+ test: /\.txt/,
+ type: 'asset',
}
]
},
}; Теперь webpack автоматически выберет между resource и inline, следуя умолчанию: файл размером менее 8 КБ будет обработан как модуль типа inline, а иначе - как модуль типа resource.
Вы можете изменить это условие, задав Rule.parser.dataUrlCondition.maxSize опцию на уровне правила модуля в вашей конфигурации webpack:
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.txt/,
type: 'asset',
+ parser: {
+ dataUrlCondition: {
+ maxSize: 4 * 1024 // 4kb
+ }
+ }
}
]
},
}; Также вы можете указать функцию для определения встраивания модуля или нет.
Замена синтаксиса Inline Loader
До модулей активов и Webpack 5, было возможно использовать синтаксис inline со старыми загрузчиками, упомянутыми выше.
Теперь рекомендуется удалить весь синтаксис inline loader и использовать условие resourceQuery для имитации функциональности синтаксиса inline.
Например, в случае замены raw-loader на тип asset/source:
- import myModule from 'raw-loader!my-module'; + import myModule from 'my-module?raw';
и в конфигурации webpack:
module: {
rules: [
// ...
+ {
+ resourceQuery: /raw/,
+ type: 'asset/source',
+ }
]
}, и если вы хотите исключить обработку сырых активов другими загрузчиками, используйте отрицательное условие:
module: {
rules: [
// ...
+ {
+ test: /\.m?js$/,
+ resourceQuery: { not: [/raw/] },
+ use: [ ... ]
+ },
{
resourceQuery: /raw/,
type: 'asset/source',
}
]
}, или список oneOf правил. Здесь будет применено только первое совпавшее правило:
module: {
rules: [
// ...
+ { oneOf: [
{
resourceQuery: /raw/,
type: 'asset/source',
},
+ {
+ test: /\.m?js$/,
+ use: [ ... ]
+ },
+ ] }
]
}, Отключение вывода активов
В таких случаях, как рендеринг на стороне сервера, вам может потребоваться отключить вывод активов, что возможно с помощью опции emit в Rule.generator:
module.exports = {
// …
module: {
rules: [
{
test: /\.png$/i,
type: 'asset/resource',
generator: {
emit: false,
},
},
],
},
};
© JS Foundation and other contributors
Licensed under the Creative Commons Attribution License 4.0.
https://webpack.js.org/guides/asset-modules