【问题】
使用 qiankun 微前端框架加载的子应用中使用了 element-ui 框架,icon 图标不显示的问题(单独打开应用 icon 显示没问题,在 qiankun 中打开不显示)
【复现步骤】
使用乾坤框架加载使用了 element-ui 框架的子应用,icon 图标不显示(效果是个识别失败的矩形)
错误效果:
正确效果:
【原因】
经过搜索资料,element-ui 图标 icon 使用的 是 .woff .ttf 格式的字体图标,浏览器加载后以 <style> 标签的方式引入的,且 .woff 的引入方式为相对路径引入,因为 qiankun 框架的主应用地址和子应用地址不一样,导致加载 .woff 文件地址错误,所以图标不显示
为什么本地开发的时候没问题:因为本地启动的时候url被处理成了全路径
【解决】
方案一:配置 url-loader 的 limit 参数大一些,从而使 .woff 和 .fft 等文件直接转成 base64,绕过路径问题。
module.exports = {
chainWebpack: config => {
config.module
.rule('fonts')
.test(/\.(ttf|woff)(\?.*)?$/)
.use('url-loader')
.loader('url-loader')
.tap(options => {
options = {
...options,
limit: 99999999,
name: '[name].[hash:7].[ext]',
}
return options
})
.end()
},
}
方案二: 配置打包时 .woff 等文件的引入路径为 http/https 开头的完整路径。
注意:如果使用 nginx 部署的应用需要配置支持 .woff 和 .ttf 等文件的静态地址访问
const publicPath = process.env.NODE_ENV === 'production' ? 'https://production.com/activeRule/' : `http://localhost:8888/`;
module.exports = {
chainWebpack: config => {
const fontRule = config.module.rule('fonts')
fontRule.uses.clear() // 先清除 vue 默认的配置,不然会有问题
fontRule
.use('file-loader')
.loader('file-loader')
.options({
name: 'static/fonts/[name].[hash:7].[ext]',
publicPath,
})
.end()
},
}
借助 webpack 的 file-loader ,在打包时给其注入完整路径(适用于字体文件和图片体积比较大的项目)
解决完后无意间去查看 qiankun 的官方文档,也给出了类似的解决方案
ps:因为我们的项目子应用地址是动态配置的,环境比较多,所以采用了方案一。
【复盘】:
首先根据错误提示,确定是 .woff 文件的路径错误导致的 然后定位显示错误的 icon 发现 使用的相对路径(../../)引入的,在 style使用相对路径它会根据当前浏览器地址栏域名去拼全路径,因为子应用的域名和主应用的不一样,所以路径错误。
找到了是路径问题,然后就从路径下手去解决,首先的想法是把 相对路径换成绝对路径,解决方式是去配置 url-loader,在 vue.config.js 添加如下配置
const packageName = require('./package.json').name
const getPath = () => {
return process.env.NODE_ENV === 'production' ? `../../${packageName}/` : '/'
}
module.exports = {
chainWebpack: config => {
config.module
.rule('fonts')
.test(/\.(ttf|woff)(\?.*)?$/)
.use('url-loader')
.loader('url-loader')
.tap(options => {
options = {
...options,
// limit: 10000,
publicPath: getPath() ,
name: '[name].[hash:7].[ext]',
}
return options
})
.end()
},
}
意思是把路径加上子应用的前缀,发版,测试,发现这样不行,虽然我加了子应用的前缀,但是子应用和主应用的域名不同,它还是会使用浏览器地址了的域名。 然后再改
options = {
...options,
// limit: 10000,
publicPath: `/`,
// publicPath: getPath() ,
name: '[name].[hash:7].[ext]',
}
把相对路径改为绝对路径,发版,测试,发现这样不行,虽然改了它的路径,但是本质上它还是使用的主应用域名,此方法行不通。
然后就想用其他方法,发现配置了 limit 参数之后,打包出来的url不是文件路径,而是base64,结合以往的知识,小图片打包的时候可以通过配置 limit 配置最大值,小于该值的会被转成 base64,而不是路径,然后修改配置如下:
module.exports = {
chainWebpack: config => {
config.module
.rule('fonts')
.test(/\.(ttf|woff)(\?.*)?$/)
.use('url-loader')
.loader('url-loader')
.tap(options => {
options = {
...options,
limit: 999999,
name: '[name].[hash:7].[ext]',
}
return options
})
.end()
},
}
把 limit 配置的大一些,使 .woff 与 .ttf 等文件直接编译成 base64,从而绕过路径问题,虽然感觉不是很正经,但是因为环境很多,配置配置全路径比较麻烦,算是比较简单省事的方法。如果 .woff 文件过大,转成 base64 较大,可能会存在性能问题(影响首次页面速度),建议使用方案二。
【注意 】:
<style> 标签的方式引入文件的相对路径是取的浏览器地址栏域名,导致的该问题的根本原因、 【总结】: