美文网首页
vue-cli4 用 image-webpack-loader

vue-cli4 用 image-webpack-loader

作者: AizawaSayo | 来源:发表于2021-04-12 04:16 被阅读0次

    vue-cli4已经默认帮我们做了很多优化处理,包括静态资源输出、样式处理、代码分割等等。我们需要自己手动配置的事情更少了,而图片压缩处理就是其中的一件。
    推荐这个插件,GitHub地址:image-webpack-loader
    安装:npm i image-webpack-loader -D

    很多人直接这样在vue.config.js里面加 image-webpack-loader 配置:

    chainWebpack: config => {
      config.module
        .rule("images")
          .use("image-webpack-loader")
            .loader("image-webpack-loader")
            .options({
              mozjpeg: { progressive: true, quality: 65 },
              optipng: { enabled: true },
              pngquant: { quality: [0.65, 0.9], speed: 4 },
              gifsicle: { interlaced: false }
              // webp: { quality: 75 }
            })
    }
    

    image-webpack-loaderGitHub文档已经明确告诉我们:
    In your webpack.config.js, add the image-loader, chained after the file-loader.
    即:添加 image-loader 的时候,必须要链式地跟在 file-loader 后面。其实是先执行image-webpack-loader,然后再交由file-loader去处理。这很好理解,当然是先压缩后再复制输出到打包的静态资源目录去啦。
    关于 loader 处理顺序可参考 webpack loader 执行顺序

    // 官方示例
    rules: [{
      test: /\.(gif|png|jpe?g|svg)$/i,
      use: [
        'file-loader',
        {
          loader: 'image-webpack-loader',
          options: {
            bypassOnDebug: true, // webpack@1.x
            disable: true, // webpack@2.x and newer
          },
        },
      ]
    }]
    

    然鹅,在 vue-cli4 中 file-loader 的部分已经帮我们像这样配置过了:

    webpackConfig => {
      webpackConfig.module
        .rule('images')
          .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
          .use('url-loader')
            .loader(require.resolve('url-loader'))
            .options({
              limit: 4096,
              fallback: {
                loader: require.resolve('file-loader'),
                options: {
                  name: `static/img[name].[hash:8].[ext]`
                }
              }
          })
    

    那我们可以像如下配置:
    image-webpack-loader 要先执行所以要配置在下面,实测按照 webpack-chain 文档配置 enforce 没有什么卵用(我还故意把顺序弄错),结果都会正常压缩图片,感觉还是老老实实根据需要的先后顺序从下到上配置好了😂
    chainWebpack 配置参考 webpack-chain 配置之 ChainedMap

    chainWebpack: config => {
      if(IS_PROD){
        config.module
          .rule('images')
            .exclude.add(resolve('src/assets/icons')) // 排除icons目录,这些图标已用 svg-sprite-loader 处理,打包成 svg-sprite 了
            .end()
            .use('url-loader')
              .tap(options => ({
                limit: 10240, // 稍微改大了点
                fallback: {
                  loader: require.resolve('file-loader'),
                  options: {
                    // 在这里修改file-loader的配置
                    // 直接把outputPath的目录加上,虽然语义没分开清晰但比较简洁
                    name: 'static/img/[name].[hash:8].[ext]'
                    // 从生成的资源覆写 filename 或 chunkFilename 时,`assetsDir` 会被忽略。
                    // 因此别忘了在前面加上静态资源目录,即assetsDir指定的目录,不然会直接在dist文件夹下
                    // outputPath: 'static/img' 
                  }
                }
            }))
            .end()
            .use('image-webpack-loader')
              .loader('image-webpack-loader')
              .options({
                mozjpeg: { progressive: true, quality: 50 }, // 压缩JPEG图像
                optipng: { enabled: true }, // 压缩PNG图像
                pngquant: { quality: [0.5, 0.65], speed: 4 }, // 压缩PNG图像
                gifsicle: { interlaced: false } // 压缩GIF图像
              })
              .end()
              .enforce('post') // 表示先执行配置在下面那个loader,即image-webpack-loader
      }
    }
    

    图片被 image-webpack-loader 压缩后,小于10kb 的转成base64(by url-loader),大于这个 size 的则被file-loader输出到dist/static/img文件夹了

    static/img目录 完美~

    如果想要图片资源打包输出时保持原有的目录结构,或者根据自定义条件决定不同的输出目录,可以用函数配置 outputPath;如果要让资源引用地址输出为相对路径,可以把 outputPath 的内容拷贝一份放到 publicPath

    .options({
      name: '[name].[hash:8].[ext]',
      // outputPath: 'static/img', // 别忘了加上静态资源目录这个前缀,即assetsDir指定的目录,不然会直接在dist文件夹下
      outputPath: function (url, resourcePath, context) {
        // 返回从项目根目录到该图片的相对路径
        const relativePath = path.relative(context, resourcePath)
        const pathArr = relativePath.split('/')
        // 如果你的静态资源目录结构较为简单(最多二个层级),图片只放在/src/assets/ 或/src/assets/xxx
        // 希望根据assets下的目录结构原样输出,可以这样做
        if (pathArr[3] !== undefined) {
          return `static/img/${pathArr[2]}/${url}` // url 是上面配置的 name 的值,必须加在路径最后
        }
        return `static/img/${url}`
    
        // 这些都可依照个人习惯来安排,个人建议没必要太复杂
        // if (/denglun-bg\.jpg/.test(resourcePath)) {
          // 如果图片以 denglun-bg.jpg 结尾
          // return `static/denglun/${url}`
        // }
        // if (/bg_images\//.test(resourcePath)) {
          // 如果图片路径包含 bg_images 目录
          // return `static/bg_images/${url}`
        // }
        // return `static/img/${url}`
      },
      publicPath: (url, resourcePath, context) => {
        // 如果要让资源引用地址输出为相对路径,把 `outputPath` 的内容拷贝一份到这里即可
      }
    },
    
    如上配置后图片输出在不同的目录

    关于 file-loader 的详细配置说明以及 vue-cli4 涉及图片处理的源码分析:➡️ file-loader 配置详解以及资源相对路径处理(废话连篇预警)

    相关文章

      网友评论

          本文标题:vue-cli4 用 image-webpack-loader

          本文链接:https://www.haomeiwen.com/subject/jertlltx.html