目录
1.子应用vue.config中的headers设置成可跨域请求
2.output设置成library,打包成umd库格式
3.父应用使用了babel-pollfill,子应用不要在在bable-pollfill
4.iconfont.js要取消样式隔离才能生效
5.关于nginx的配置
6.主应用和各应用相同依赖的版本号一定要一样,不然会有莫名其妙的BUG
7.项目中使用了三方插件时涉及跨域的问题
8.主应用、微应用部署在不同的服务器上,微应用更新后,浏览器读取缓存问题
9.主应用、微应用部署在不同服务器上,主应用读取不到微应用静态资源文件,读取的时主应用的静态资源文件
10.hash模式下无法激活子应用
11.微应用文件更新之后,访问的还是旧版文件
12.微应用打包之后 css 中的字体文件和图片加载 404
13.微应用 JSONP 跨域错误怎么处理?
最近博主在开发一个微服务架构搭建的编程导航,方便大家学习交流。程序员导航是一个以Angular13.0,vue3.x, React16前端技术框架开发的一站式程序员学习工作娱乐导航网站,以让程序员更便捷为使命,始终围绕程序员需求,为程序员提供最新工具导航的便捷性服务网站!
下面说说本人在做qiankun微前端改造时遇到的一些坑,希望对大家有帮助。
1.子应用vue.config中的headers设置成可跨域请求
headers: {
//因为qiankun内部请求都是fetch来请求资源,所以子应用必须允许跨域
"Access-Control-Allow-Origin": "*",
},
2.output设置成library,打包成umd库格式
configureWebpack: {
output: {
// 把子应用打包成 umd 库格式
library: `${name}`,
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${name}`,
},
}
3.父应用使用了babel-pollfill,子应用不要在在bable-pollfill
config.entry.app = [./src/main.ts]
4.iconfont.js要取消样式隔离才能生效
sandbox - boolean | { strictStyleIsolation?: boolean } - 可选,是否开启沙箱,默认为 true。
5.关于nginx的配置
# 主应用
location / {
if ($request_uri ~* '/$|\.html$') {
add_header Cache-Control no-store;
}
root /opt/pumpkin/fronted/;
index index.html;
try_files $uri $uri/ /index.html;
}
# cloud子应用
location /cloud/ {
if ($request_uri ~* '/$|\.html$') {
add_header Cache-Control no-store;
}
alias /opt/pumpkin/fronted/;
index index.html;
try_files $uri $uri/ /index.html;
}
# mall子应用
location /mall/ {
if ($request_uri ~* '/$|\.html$') {
add_header Cache-Control no-store;
}
alias /opt/pumpkin/fronted/;
index index.html;
try_files $uri $uri/ /index.html;
}
# portal子应用
location /portal/ {
if ($request_uri ~* '/$|\.html$') {
add_header Cache-Control no-store;
}
alias /opt/pumpkin/fronted/;
index index.html;
try_files $uri $uri/ /index.html;
}
由于都是history的路由模式,所以:
每个应用配置都要加上try_files $uri $uri/ /index.html;否则会出现刷新报404错误
每个子应用都要单独配置location,否则在访问/cloud,/mall,/portal时刷新会报404
6.主应用和各应用相同依赖的版本号一定要一样,不然会有莫名其妙的BUG
7.项目中使用了三方插件时涉及跨域的问题
项目中使用了三方组件,会出现在子应用中无法使用的情况 ,在看源码时发现子应用的document.body中添加script标签失败没报错,但无法正确添加到body中,类似性质的问题还有美洽客服的引用,pdfjs的引用两种解决方法。
// 方脚本调用解决沙箱跨域问题
const opts: any = {
prefetch: false,
singular: true,
fetch: window.fetch,
excludeAssetFilter: (assetUrl: string) => {
console.log("三方件扩展应用", assetUrl);
if (
assetUrl.includes("changyan") ||
assetUrl.includes("zone.js") ||
assetUrl.includes("kuaizhan")
) {
return true;
}
},
};
start(opts);
8.主应用、微应用部署在不同的服务器上,微应用更新后,浏览器读取缓存问题
解决方案:服务器需要给微应用的配置一个响应头,意思就是每次请求都检查是否更新。
Nginx为例:
location = /index.html {
add_header Cache-Control no-cache;
}
9.主应用、微应用部署在不同服务器上,主应用读取不到微应用静态资源文件,读取的时主应用的静态资源文件
module.exports = {
output: {
publicPath: `/app1/`,
},
};
10.hash模式下无法激活子应用
const getActiveRule = (hash) => (location) => location.hash.startsWith(hash);
11.微应用文件更新之后,访问的还是旧版文件
服务器需要给微应用的 index.html 配置一个响应头:Cache-Control no-cache,意思就是每次请求都检查是否更新。
以 Nginx 为例:
location = /index.html {
add_header Cache-Control no-cache;
}
12.微应用打包之后 css 中的字体文件和图片加载 404
原因是 qiankun 将外链样式改成了内联样式,但是字体文件和背景图片的加载路径是相对路径。
而 css 文件一旦打包完成,就无法通过动态修改 publicPath 来修正其中的字体文件和背景图片的路径。
主要有以下几个解决方案:
所有图片等静态资源上传至 cdn,css 中直接引用 cdn 地址(推荐)
借助 webpack 的 url-loader 将字体文件和图片打包成 base64(适用于字体文件和图片体积小的项目)(推荐)
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif|webp|woff2?|eot|ttf|otf)$/i,
use: [
{
loader: 'url-loader',
options: {},
},
],
},
],
},
};
vue-cli3 项目写法
module.exports = {
chainWebpack: (config) => {
config.module.rule('fonts').use('url-loader').loader('url-loader').options({}).end();
config.module.rule('images').use('url-loader').loader('url-loader').options({}).end();
},
}
13.微应用 JSONP 跨域错误怎么处理?
qiankun 会将微应用的动态 script 加载(例如 JSONP)转化为 fetch 请求,因此需要相应的后端服务支持跨域,否则会导致错误。
在单实例模式下,你可以使用 excludeAssetFilter 参数来放行这部分资源请求,但是注意,被该选项放行的资源会逃逸出沙箱,由此带来的副作用需要你自行处理。
若在多实例模式下使用 JSONP,单纯使用 excludeAssetFilter 并不能取得好的效果,因为各应用被沙箱所隔离;你可以在主应用提供统一的 JSONP 工具,微应用调用主应用提供的该工具来曲线救国。
14.如何解决拉取微应用 entry 时 cookie 未携带的问题
因为拉取微应用 entry 的请求都是跨域的,所以当你的微应用是依赖 cookie (如登陆鉴权)的情况下,你需要通过自定义 fetch 的方式,开启 fetch 的 cors 模式:
如果你是通过 registerMicroApps 加载微应用的,你需要在 start 方法里配置自定义 fetch,如:
import { start } from 'qiankun';
start({
fetch(url, ...args) {
// 给指定的微应用 entry 开启跨域请求
if (url === 'http://app.alipay.com/entry.html') {
return window.fetch(url, {
...args,
mode: 'cors',
credentials: 'include',
});
}
return window.fetch(url, ...args);
},
});
如果你是通过 loadMicroApp 加载微应用的,你需要在调用时配置自定义 fetch,如:
import { loadMicroApp } from 'qiankun';
loadMicroApp(app, {
fetch(url, ...args) {
// 给指定的微应用 entry 开启跨域请求
if (url === 'http://app.alipay.com/entry.html') {
return window.fetch(url, {
...args,
mode: 'cors',
credentials: 'include',
});
}
return window.fetch(url, ...args);
},
});
如果你是通过 umi plugin 来使用 qiankun 的,那么你只需要给对应的微应用开启 credentials 配置即可:
export default {
qiankun: {
master: {
apps: [
{
name: 'app',
entry: '//app.alipay.com/entry.html',
+ credentials: true,
}
]
}
}
}
微服务体验连接:富朝阳的博客
欢迎在评论区交流。
如果文章对你有所帮助,❤️关注+点赞❤️鼓励一下!博主会持续更新。。。。
我的博客原文:qiankun微服务搭建遇到的坑