cpf23333大约 3 分钟

前言

本文适用于 vue-cli 版本小于 5.0 的项目,大于等于 5.0 的就不用看了

内容

众所周知,vue 的 vue.config.js 里 css.loaderOptions 选项提供了更改 css 相关 loader 配置的能力,这个功能在大部分情况下是够用的,但总是有一些特殊情况。

先说下实际需求。项目采用微应用的形式部署,各个页面以子应用的形式在主应用中加载,有组件使用的 css 需要静态资源。

在我们的正常开发中,这一套没有什么可以说的,publicPath 配置正确的情况下一切都会正确运行,但微应用除外,原因如下。

在进行打包时,我们运行的命令是 npm run build ,这个命令定义在 package.json 当中,它去调用了 vue-cli-service build 命令,而 vue-cli-service 则定义在 node_modules/@vue/cli-service/bin/vue-cli-service.js,它会再去调用 webpack,进行打包。

vue-cli 集成一些默认的打包规则,处理各种样式的插件们叫 css-loader,scss-loader,less-loader,postcss-loader,stylus-loader,处理常规静态资源的插件有 file-loader 和 url-loader

查看方式如下

查看方式

输出如下

输出

通过这张图我们可以就看到@vue/cli-service给 webpack 提供的具体配置

第一项是对 vue 文件的处理,用的 vue-laoder,这个不是本文要关注的点,略过

我们需要关注的是对图片和字体和其它一些类型的资源的处理,也就是第二三四项

我们可以看到,@vue/cli-service对图片,字体和音视频的处理模块是 url-loader,配置里有限制最大体积和一个 fallback,fallback 使用的是 file-loader,而 svg 文件则是直接使用 file-loader。

问题就在这个 file-loader 上,图片很少有小于 4kb 的,所以静态文件一般都会交由 file-loader 处理,file-loader 的配置项里有一项叫做 publicPath,它的默认值是__webpack_public_path__ + outputPathopen in new window,在开发环境中,这一默认值并不会起效,项目一切正常,但在打包时这一项就会起作用了,默认情况下它会把所有的资源路径都转为相对路径,听起来没什么不对劲的对吧,部署之后确实也一切正常,但在 qiankun 框架下作为子应用,被主应用加载后就不正常了。

qiankun 的子应用加载逻辑是读取该应用下的 index.html,解析然后预加载相关资源,在一个固定路由下依据该固定路由的下级路由字符匹配出对应的子应用,然后在对应的 div#子应用文件夹名 内加载 index.html 的内容,因此对于子应用的静态资源而言,相对路径的相对对象发生了改变,从子应用变成了主应用,对应的实际地址不同了,自然也就无法顺利加载。

解决办法自然就是把相对路径改成绝对路径,配置如下

if (String(o.test).includes("png" || "mp4" || "ttf")) {
  const use = o.use[o.use.length - 1]
  use.options.fallback.options.publicPath = 该应用的publicPath
}

我们给 file-loader 一个 publicPath,就可以让 file-loader 把所有的资源应用路径从相对路径改成绝对,也就不存在主应用内加载子应用时无法加载静态资源的问题了

总结

与其这么麻烦地去读取 vue-cli 的配置,找到要改的地方去进行修改,还不如提升一下@vue/cli-service的版本号,把它升到 5.0 这个大版本上,就没有这种问题了。

5.0 把 url-loader 和 file-loader 移除了,默认就是绝对路径~

上次编辑于:
贡献者: cpf23333