【问题标题】:How can I load webp images after these are generated by imagemin-webp-webpack-plugin?在 imagemin-webp-webpack-plugin 生成这些图像后,如何加载 webp 图像?
【发布时间】:2021-01-05 18:19:57
【问题描述】:

我正在配置 imagemin-webp-webpack-plugin 以将我的 src/assets/images 中的所有 .png 和 .jpg 图像转换为 dist/assets/images。当我运行构建命令时,转换成功。所有图像都已转换为 webp 并分发到 dist/assets/images。我认为“这很简单”,是时候在我的 src/index.html 文件中创建 <picture> 标记以开始引用 .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 无法解析这些图像。

所以现在我遇到了一个障碍:当 imagemin-webp-webpack- 处理了 jpg 和 png 后,这些图像仅存在于 dist/whateverpath 上时,如何在我的 src/index.html 中引用 .webp 图像插件

这是我的配置文件,以防万一:

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]',
                    }
                }
            },
        ]
    },
    
};

【问题讨论】:

    标签: webpack webpack-4 webp imagemin imagemin-webp


    【解决方案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】:

      我也有同样的问题,但很令人沮丧,它从未得到解决,所以这是我的解决方案。

      正如您所说,如果它们仅由 ImageminWebpWebpackPlugin 在构建过程中制作,则无法在元素中引用您的 webp 图像。和你一样,我的 html-loader 抛出错误,因为文件不存在。在我的情况下,我只是添加了一个预构建步骤,首先将图像转换为 webp,并且在构建过程中不使用 ImageminWebpWebpackPlugin,而只是单独使用 imagemin-webp 插件。

      这是他们 github 页面上的默认配置Site

      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);
      })();
      

      Link to issues page here

      【讨论】:

        【解决方案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 && 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;
            }
        

        【讨论】:

          猜你喜欢
          • 2019-11-18
          • 2020-04-30
          • 2013-08-03
          • 1970-01-01
          • 2013-09-21
          • 1970-01-01
          • 1970-01-01
          • 2019-11-16
          • 2012-01-09
          相关资源
          最近更新 更多