#webpack #webpack-4 #webp #imagemin #imagemin-webp
#webpack #webpack-4 #webp #imagemin #imagemin-webp
Вопрос:
Я настраивал imagemin-webp-webpack-plugin для преобразования всех моих изображений .png и .jpg в мои src/assets/images
dist/assets/images
. Когда я запустил свою команду сборки, преобразование прошло успешно. Все изображения были преобразованы в webp и распространены dist/assets/images
. Я подумал, что «это просто» и что пришло время создать <picture>
теги в моем src/index.html
файле, чтобы начать ссылаться.изображения webp:
src/index.html:
<picture>
<source srcset="assets/images/img-hero-home-attorney.webp" type="image/webp">
...
...
</picture>
Когда я npm run build
снова, на этот раз я получил:
ERROR in ./src/index.html (./node_modules/html-webpack-plugin/lib/loader.js!./src/index.html)
Module not found: Error: Can't resolve './assets/images/img-hero-home-attorney.webp' in '/Users/**/**/**/**/**/**/src'
@ ./src/index.html (./node_modules/html-webpack-plugin/lib/loader.js!./src/index.html) 6:33-87
И для меня это имело смысл. Эти изображения не существуют, src/assets/images/
поэтому Webpack не может их разрешить.
Итак, теперь я столкнулся с препятствием: как я могу ссылаться.изображения webp в моем src/index.html
, когда эти изображения будут существовать только dist/whateverpath
после обработки jpg и png с помощью imagemin-webp-webpack-plugin?
Это мой файл конфигурации на случай, если он может быть полезен:
webpack.config.js
module.exports = {
entry: {
app: [
'./src/index.js'
]
},
output: {
path: path.resolve(__dirname, 'dist/'),
filename: 'assets/js/[name].bundle.js',
},
devtool: 'source-map',
plugins: [
new CleanWebpackPlugin({
dry: false,
cleanOnceBeforeBuildPatterns: ['!index.html']
}),
new HtmlWebpackPlugin({
template: './src/index.html',
filename: './index.html',
minify: false,
chunks: ['app']
}),
new MiniCssExtractPlugin({
filename: 'css/[name].css',
chunkFilename: '[id].css'
}),
new HtmlCriticalWebpackPlugin({
base: 'dist/',
src: 'index.html',
dest: 'index.html',
inline: true,
minify: true,
extract: false,
width: 1351,
height: 1200,
penthouse: {
blockJSRequests: false,
}
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
new ImageminWebpWebpackPlugin({
config: [{
test: /.(jpe?g|png)/,
options: {
quality: 85
}
}],
overrideExtension: true,
detailedLogs: true,
silent: true,
strict: true
})
],
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /.html$/,
loader: 'html-loader',
query: {
minimize: false
}
},
{
test: /.(scss)$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
},
{
loader: 'css-loader',
options: {
sourceMap: true,
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: true,
plugins: function () {
return [
require('autoprefixer')
];
}
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
},
{
test: /.(png|svg|jpg|gif|webp)$/,
use: {
loader: 'file-loader',
options: {
name: 'assets/images/[name].[ext]',
}
}
},
]
},
};
Ответ №1:
Вы можете использовать filemanager-webpack-plugin
для копирования преобразованных изображений обратно в свою assets/images
папку — https://github.com/gregnb/filemanager-webpack-plugin /
const FileManagerPlugin = require('filemanager-webpack-plugin');
plugins: [
new ImageminWebpWebpackPlugin({
config: [{
test: /.(jpe?g|png)/,
options: {
quality: 85
}
}],
overrideExtension: true,
detailedLogs: true,
silent: true,
strict: true
}),
new FileManagerPlugin({
onEnd: {
copy: [
{
source: './dist/**/*.webp',
destination: './src/assets/images/',
},
],
},
}),
],
]
Ответ №2:
У меня такая же проблема, и это довольно неприятно, что она так и не была решена, поэтому вот мое решение.
Как вы сказали, вы не можете ссылаться на свои изображения webp в элементе, если они созданы только ImageminWebpWebpackPlugin во время процесса сборки. Так же, как и вы, мой html-загрузчик выдавал ошибки, потому что файл не существовал. В моем случае я просто добавил шаг предварительной сборки, чтобы сначала преобразовать изображения в webp и просто не использовать ImageminWebpWebpackPlugin в процессе сборки, а просто использовать только плагин imagemin-webp.
Вот конфигурация по умолчанию на их сайте страницы github
const imagemin = require('imagemin');
const imageminWebp = require('imagemin-webp');
(async () => {
await imagemin(['images/*.{jpg,png}'], {
destination: 'build/images',
plugins: [
imageminWebp({quality: 50})
]
});
console.log('Images optimized');
})();
Конечно, я запустил это в Windows 10, и это не сработало, поэтому другой пользователь на вкладке «Проблемы» решил это, преобразовав путь в стиль unix.
const path = require('path');
const imagemin = require('imagemin');
const imageminWebp = require('imagemin-webp');
(async () => {
const img = await imagemin([path.resolve(__dirname, 'img/*.{jpg,png}').replace(/\/g, '/')], {
destination: path.resolve(__dirname, 'dist/webp').replace(/\/g, '/'),
plugins: [imageminWebp({ quality: 70 })],
});
console.log('Images optimized');
console.log(img);
})();
Ответ №3:
У меня такая же проблема. После двухдневных усилий я решаю обработать их во время выполнения…
import html from './content.html';
const parser = new DOMParser();
/**
* @param {string} html
*/
function replaceImgToPicture(html) {
var dom = parser.parseFromString(html, 'text/html');
var images = dom.querySelectorAll('img');
function __setAttribute(source, img, attr, newAttr) {
var value = img.getAttribute(attr);
if (value) {
source.setAttribute(
newAttr || attr,
value.replace(/.(jpe?g|png|gif)/gi, '.webp')
);
}
}
for (var i = 0; i < images.length; i ) {
var img = images[i];
if (img.parentElement amp;amp; img.parentElement.tagName === 'PICTURE') {
continue;
}
var picture = document.createElement('picture');
var source = document.createElement('source');
source.setAttribute('type', 'image/webp');
__setAttribute(source, img, 'sizes');
__setAttribute(source, img, 'srcset');
__setAttribute(source, img, 'media');
if (!source.hasAttribute('srcset')) {
__setAttribute(source, img, 'src', 'srcset');
}
img.parentElement.insertBefore(picture, img);
picture.appendChild(source);
picture.appendChild(img);
}
return dom.documentElement.outerHTML;
}