解决阿里qiankun微应用资源无法加载

公司老项目多了,却想用新版本的框架,最好的解决办法就是用微前端。
本文说下我们在用阿里微前端框架qiankun,遇到的一些问题,以及一些巧妙的解决办法。

背景

因为接入微前端很长时间了,导致现在的微应用变成了实际意义上的主应用,主应用反而没有多少功能。于是,想着能不能把两个项目的角色换一下,老的主应用项目,变成微应用;微应用项目变成主应用。这样做有两个好处:

  1. 如果当前需求不涉及老业务,微应用的老代码就不用发版了。
  2. 可以顺便升级项目的路由、鉴权等基础逻辑。

于是,开整。

遇到问题

很快,升级工作进行的差不多了,提测的过程中,发现有些资源文件无法加载,如下图:

alt于是快速定位,发现是老代码变成微应用之后,在加载资源时,路径还是走主应用。比如:

  • 主应用: http: //my.proj.com/main-proj/static/select.png
  • 微应用: http: //my.proj.com/micro-proj/static/select.png

本来应该是下面的路径才对,却显示成上面的路径,所以找不到资源。

官方答疑

其实这个问题很多人有遇到 ,于是去官方看下有没有解决方案:
一看还真有,在官方常见问题中有提到:

解决阿里qiankun微应用资源无法加载_第1张图片添加publicPath 、调整静态资源的地址和转Base64.

尝试解决

首先,我们真实环境,老项目是用vue1.x是5年前的项目,我看了下,vue-router还是0.7.x的版本,那个时候,路由配置还没有base,也就是官方教程里的配置:

解决阿里qiankun微应用资源无法加载_第2张图片vue-router0.7.x版本源码:

解决阿里qiankun微应用资源无法加载_第3张图片即使你按照官方的配置走了,也是不起作用的,因为早期版本不支持。找不到base相关的代码。

那为什么不升级老项目呢?

这个问题我也想过,只是项目太复杂且工作量太大,我情愿找到一个能解决资源路径的办法也不想去动老代码。

继续想办法

如果启动的时候配置不了base,那打包的时候行吗?答案是可以,但是有问题。我尝试在webpack中添加publicpath。

module.exports = function (config) {
    const webpack = require(path.resolve(config.mumbleDir, './node_modules/webpack'));
    const cfg = {
        ......
        module: {
            noParse: [/vue-router\.js/]
        },
        devServer: {
            headers: {
                'Access-Control-Allow-Origin': '*'
            }
        },
        output: {
            filename: '[name].js', // 输出文件名
            library: `${name}-[name]`, // 暴露给全局变量的名称
            libraryTarget: 'umd', // 导出库方式
            umdNamedDefine: true, // 是否将AMD模块命名
            publicPath: `${
            config.env === 'develop' 
            ? 'http://my.proj.com/micro-proj' 
            : 'http://my.prod.proj.com/micro-proj'
            }/static/`
        }
    };
    return cfg;
};

通过这样的配置,可以部分资源能够使用,为啥说部分资源呢?因为老的webpack在打包静态资源的时候有些资源在Css文件中的路径是相对路径。

往后讲,我们也有CDN资源,但是这个只用于对外的项目,内部项目一般都是资源打包,所以不太妥。
base64也解决不了问题,因为有些字体就很大,不适合用这种方式。

新的思路

突然想到,如果我能通过webpack插件来把资源都改成微应用路径不就行了?于是找了个插件string-replace-webpack-plugin

var StringReplacePlugin = require("string-replace-webpack-plugin");
module.exports = {
   module: {
      loaders: [
         // configure replacements for file patterns
         { 
            test: /index.html$/,
            loader: StringReplacePlugin.replace({
                replacements: [
                    {
                        pattern: //ig,
                        replacement: function (match, p1, offset, string) {
                            return secrets.web[p1];
                        }
                    }
                ]})
            }
      ]
   },
   plugins: [
      // an instance of the plugin must be present
      new StringReplacePlugin()
   ]
}

配置好了没有一点反应,不知道是不是因为老项目的webpack版本太低还是其他原因。然后还想到,我们项目有生产和测试环境,测试环境还有好多个,这种绝对路径替换的方案也不太行的通。

巧妙解决

在上面的思路基础上,再回想下现在的现象,就是资源文件总是会跑到主应用的路径上去,那如果把微应用的资源移到主应用中去,不就能找到了?

select{
    width: 200px;
    height: 30px;
    padding: 4px 10px;
    border: $border;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    background-image: url("/select.png");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-color: $white;
}

资源文件用绝对路径,同时,把资源放到主应用的public下面(基于框架,我们的框架放到这个目录会自动打包Copy到Dist)
alt
最后,顺利加载:

alt

总结

在官方的解决方案上找不到想要的结果,就只能自己因地制宜了。希望这个思路可以帮到你们,谢谢!

你可能感兴趣的:(前端,qiankun,微应用,前端)