taro3.x 小程序网络图片loader

小程序和其他环境不一样,打包后的体积真是寸土寸金,图片资源最好是用网络地址,所以写一个loader来上传文件,返回网络地址

url-laoder 或是 postcss-loader

taro 用了 url-laoder 或是 postcss-loader 将图片 base64 打到 js 里,虽说又 limit 参数,但我试了试不好用,就算好用,打到本地图片也不是我希望的。
url-loader 有一个配置是,超出 limit 上线,可以走 fallback 一个自己的 loader

修改 taro 打包配置

需要修改一下 taro 的编译配置
mini.postcss.url

      url: {
        enable: true,
        config: {
          limit: 0, // 设定转换尺寸上限
          url: ''
        },
      },

用 webpackChain 修改 image rule 的 loader 参数
再 url-loader 添加 fallback 让他走自己写的 loader

webpackChain(chain) {
      chain.plugin('WxssImportPlugin').use(WxssImportPlugin)
      chain.module
        .rule('image')
        .use('urlLoader')
        .tap(options => {
          options.fallback = path.resolve(__dirname, '../build/ImageUploadLoader/index.js')
          return options
        })

      // console.log(chain.resolve.plugins)
    }

loader 部分的代码

每次构建都会走 loader 的代码,我不希望每次都上传图片,所以可以用 md5 再本地做一个上传结果的缓存

// index.js
const buf2Url = require('./utils/buf2Url')

/**
 * 因为小程序分包大小问题,我们把所有本地图片上传到fs上,然后用返回网络地址 
 * 
 * 存储一个md5 作为缓存,在memo中的地址,直接使用,不存在的上传fs
 */

module.exports = async function (value) {
  const callback = this.async();

  const raw = this._module.rawRequest.split('/')
  const filename = raw[raw.length - 1]

  const url = await buf2Url(value, filename)

  callback(null, moduleStr(url))
}

function moduleStr(str) {
  return `module.exports='${str}'`
}

url-loader 会传入 buffer,拿着 buffer 上传文件,拿到 url 地址

// utils/buf2url.js
const md5 = require('md5')
const axios = require('axios')
const fs = require('fs')
const path = require('path')
const FormData = require('form-data')

const UploadPath = # 上传地址

module.exports = function (buf, filename) {
  // 获取md5值
  const key = md5(buf)

  console.log('filename', filename)

  let memo
  try {
    memo = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../md5memo.json')))
  } catch (e) {
    memo = {}
  }

  return new Promise(resolve => {
    // 是否在memo中存在
    if (key in memo) {
      resolve(memo[key].fullPath)
    } else {
      // 上传
      try {
        let form = new FormData()
        form.append('file', buf, { filename })
        axios.post(UploadPath, form, {
          headers: {
            'Content-Type': 'multipart/form-data',
            ...form.getHeaders()
          }
        }).then(res => {
          try {
            memo = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../md5memo.json')))
          } catch (e) {
            memo = {}
          }
          // 存json
          memo[key] = {
            # 取网络地址
            fullPath: res.data.data.fullPath,
            filename
          }
          fs.writeFileSync(path.resolve(__dirname, '../md5memo.json'), JSON.stringify(memo, null, 2))
          resolve(res.data.data.fullPath)
        })
      } catch (e) {
        console.log('出错了?')
        resolve()
      }
    }
  })
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容