01月15, 2019

art-template-loader处理srcset

关于srcset,之前有文章提及过对它的处理,大概是这样的:

{
  test: /\.html$/,
  loader: 'html-srcsets-loader',
  options: {
    attrs: ['img:src', ':srcset'],
    minimize: true,
    caseSensitive: true,
    removeAttributeQuotes: false,
    minifyJS: false,
    minifyCSS: false
  },
  exclude: /^node_modules$/,
}

让我没想到的是,在打包出来后的页面中,还是有srcset没做处理的情况。分析了一把,发现原因是:

import xx from './xx.tpl'

const html = xx({a: 1, b: 2});
// 再把这个html片断插入某个DOM节点

一开始我也想不到怎么处理,比较压抑。后来在大牛的指点下,恍悟过来,这个应该是需要在art-template-loader里面加一层处理的:

alt

于是我尝试将其变成一个数组的loader,但事实证明是我想多了。(每个loader转出来的结果可能是不一样的,art的这个loader最后的结果必须是一个function)。

所以我尝试着去看art-template-loader里面的源代码:

alt

这一段是重点,它做的事情就是处理src,但它没将srcset给考虑进去,所以我要做的事,就是加上srcset的处理逻辑。

在实际填坑的过程中,发现还是自己太年轻了,就是我以为srcset的写法都是这样的:

<img src="" srcset="~assets/images/empty@2x.png 2x, ~assets/images/empty@3x.png 3x" />

结果发现开发的用法,有些是只有2倍图,有些3x后面还有,,有些2倍图3倍图之前没有空格,所以得去想方设法兼容各种情况:

let result;
let options = loaderUtils.getOptions(this) || {};
let htmlResourceRules = [/\bsrcset="([^"]*)"/, /\bsrc="([^"]*)"/];
const htmlResourceRoot = options.htmlResourceRoot;
const callback = this.callback;
const use = (match, url) => {
  let isSrc = true, isSrcset = false;
  if (url.indexOf(' 2x') > 0 || url.indexOf(' 3x') > 0) {
    isSrc = false;
    isSrcset = true;
  }
  let code;
  const output = 'raw';
  match = match.toString();

  if (isSrc && loaderUtils.isUrlRequest(url, htmlResourceRoot)) {
    const urlRequest = loaderUtils.urlToRequest(url, htmlResourceRoot);
    const attr = match.split(url);
    const codes = [attr[0], urlRequest, attr[1]].map(JSON.stringify);
    code = codes[0] + `+require(${codes[1]})+` + codes[2];
  } else if (isSrcset) {
    // 如果是srcset,就走这里
    const srcsetArr = url.split(",");
    const url1 = srcsetArr[0].trim().split(' ')[0];
    let url2 = "";
    if (srcsetArr.length > 1 && srcsetArr[1] !== "") {
      url2 = srcsetArr[1].trim().split(' ')[0]; 
    }
    if (loaderUtils.isUrlRequest(url1, htmlResourceRoot) || (url2 != "" && loaderUtils.isUrlRequest(url2, htmlResourceRoot))) {
      const attr = match.split(url);
      const urlRequest1 = loaderUtils.urlToRequest(url1, htmlResourceRoot);
      let urlRequest2 = "";
      if (url2 !== "") {
        urlRequest2 = loaderUtils.urlToRequest(url2, htmlResourceRoot);
      }
      const codes = [attr[0], urlRequest1, urlRequest2, attr[1]].map(JSON.stringify);
      if (url2 != "") {
        code = codes[0] + `+require(${codes[1]})` + '+" 2x, "+' + `require(${codes[2]})` + '+" 3x"+' + codes[3];
      } else {
        code = codes[0] + `+require(${codes[1]})` + '+" 2x"+' + codes[3];
      }
    }
  } else {
    code = JSON.stringify(match);
  }

  return {
    output,
    code
  };
};

这里的难点还有一个是最后组装2倍图和3倍图的时候,字符串拼接搞得我蛋疼死了。

好在顺利完成开发!!

本文链接:www.my-fe.pub/post/art-template-loader-handle-srcset.html

-- EOF --

Comments

评论加载中...

注:如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理。