当 webpackfis 遇到 canvas

Posted 前端新视野

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当 webpackfis 遇到 canvas相关的知识,希望对你有一定的参考价值。


本文摘要

本文主要解决 canvas 脚本文件对资源文件加载路径的特殊要求,从而需要 webpack 和 fis 针对性地做出线上打包优化,同时你会学到如何编写插件来任意地改变输出 index.html 中依赖文件的内容


1
先来看两个问题:



当 webpack、fis 遇到 canvas



错误原因也很直观


canvas 的 API 都不允许跨域等对资源路的径限制操作

比如还包括:getImageData 等

我们的页面文件都存放在 A 域名,静态资源或托管到 B 域名


2
看看如何配置 CDN 路径


webpack 下面:


// webpack.prod.conf.js

// 在 output 里面

output: {

   publicPath:  config.build.publicPath

}


//config/index.js

build: {

  publicPath: 'https://******'

}



fis 下面:


//fis-conf.js 文件的配置

fis.media('prod')

 .match('*.{js,css,less,png,gif,jpg,svg}', {

   domain : 'https://******'

 })


3
打包之后如何关联上 CDN 地址


webpack 下面:


我们分 2 个版本来看,压缩和未压缩的:


1、压缩版本:


// manifest.js


function f() {

   b.onerror = b.onload = null, clearTimeout(r);

   var c = d[e];

   0 !== c && (c && c[1](new Error("Loading chunk " + e + " failed.")), d[e] = void 0)

}


// 这里和我们常面试的 jsonp 类似

// 创建 script 标签,加载一堆 chunk 文件

var   n = document.getElementsByTagName("head")[0],

       b = document.createElement("script");

       b.type = "text/javascript",

       b.charset = "utf-8",

       b.async = !0,

       b.timeout = 12e4,

       c.nc && b.setAttribute("nonce", c.nc),

       b.src = c.p + "static/js/" + e + "." + {

          0: "69e1d542baafddafa73a"

       }[e] + ".js";


var r = setTimeout(f, 12e4);

       return b.onerror =

       b.onload = f,

       n.appendChild(b)


c.p = "https://******"


2、未压缩版本:


/******/ // __webpack_public_path__

/******/ __webpack_require__.p = "https://******";



来,跟着我们一起看源码


// webpack/lib/MainTemplate.js


getPublicPath(options) {

 return this.applyPluginsWaterfall("asset-path",

        this.outputOptions.publicPath || "", options);

}



this.plugin("require-extensions", (source, chunk, hash) => {

  const buf = [];

  if(chunk.chunks.length > 0) {}


  //...


  const publicPath = this.getPublicPath({

     hash: hash

  })

  buf.push("")

  buf.push("// __webpack_public_path__")

  buf.push(`${this.requireFn}.p = ${JSON.stringify(publicPath)};`)

  return this.asString(buf)

}


4
如何局部自定义


网上也有很多人问一个同样的问题


Q

配置 output 的 publicPath 之后,最后编译的时候所有的资源文件都会被替换

但是:有的文件不想被替换


官网也给了很明显的解释:


For loaders that embed <script> or <link> tags or reference assets like images, publicPath is used as the href or url() to the file when it’s different than their location on disk (as specified by path).


5
configuring webpack public path at runtime?


// 在入口文件中使用:__webpack_public_path__


当 webpack、fis 遇到 canvas


注意:但是它只能在 runtime 工作,还是解决不了我们 build 之后的


当 webpack、fis 遇到 canvas

so ~~~


我们再来回顾一下整个 webpack 的编译流程,我们发现最终 index.html 的生成依赖插件:html-webpack-plugin,资源文件通过 inject 配置插入


而且之前我们做了很多自定义 index.html 的需求:


  • 在国际化方案中自定了一些变量

  • inline 了 manifest.js

  • 自定义打包文件写入 json

  • 等等


所以我们又想到了采用 webpack 插件来单独处理最终写入 html 的资源文件的路径:


思路开始:


1.设计一个插件,在输出 html 之前替换全局的 publicPath


2.要告诉插件一个标识,告知当前文件需要局部替换全局的 publicPath




实践开始:


1、在多页应用循环时候匹配模块,插入新的 conf.options


let conf = {

 inject: true,

 template: '**',

 filename: '**'

 ...

}


// 匹配文件模块名

if (filename.indexOf('****') > -1) {

   conf.needReplace = 'yes'

}


// 最终调用插件

new HtmlWebpackPlugin(conf)


2、插件替换


// 核心部分

compilation.plugin('html-webpack-plugin-alter-asset-tags', function (htmlPluginData, callback) {

 if (!htmlPluginData.plugin.options.needReplace) {

    return callback(null, htmlPluginData);

 }


  // 直接替换内容

  htmlPluginData.body.forEach(function (item) {

       if (item.attributes.type == 'text/javascript' && item.innerHTML) {

         item.innerHTML = item.innerHTML.replace('https://***', '***')

       }

     })

}


我们选择在 html-webpack-plugin-alter-asset-tags  判断标识,然后替换 body 里面的内容。


这里为什么是 innerHTML?


是因为我们只是替换 chunk 文件,所以替换  c.p = "https://******"  为  c.p = "******"


效果如图:







下面我们看看 fis 的处理方案:


fis.media('prod')

 .match('*.{js,css,less,png,gif,jpg,svg}', {

   domain : 'https://******'

 })

 // 在替换一次特定目录的喽

 .match('/images/zombie/*.{png,jpg,gif}', {

   domain : '***'

 })




扩展链接:


1、https://github.com/webpack/webpack/issues/443

2、https://developer.mozilla.org/zh-CN/docs/Web/HTML/CORS_enabled_image

以上是关于当 webpackfis 遇到 canvas的主要内容,如果未能解决你的问题,请参考以下文章

当 Json 遇到 Map

当Json遇到Map

当const遇到指针

当 1117 遇到 MLCC 后

当Json遇到Map

当Json遇到Map