const getEntry = (base: string, port: number) => {
const host: string = location.hostname
return process.env.NODE_ENV === 'development'
? `http://${host}:${port}${base}`
: `${base}/index.html`
}
而getEntry是用于qiankun子应用的加载配置
export const qiankun = {
apps: apps.map(app => {
if (app.name === 'distributed-storage') {
return {
name: app.name,
entry: `/distributed-storage-ui/`,
activeRule: `/distributed-storage`
}
}
return {
name: app.name,
entry: getEntry(`/${app.name}`, app.port)
}
}),
routes: appRoutes,
lifeCycles: {
afterMount: () => {}
},
prefetch: !isDev
}
需要将 getEntry 里面的 host 赋值成location.hostname,修改完成之后在远程可以打开。且功能完善,
此时完成了第一步,但是打开子应用会出现devScript断联的提示。
可以看到在其他机器打开的页面 子应用的 devScript 脚本请求发送到了localhost
而devScript的脚本请求是由 umi 配置的webpack 热更新模块加载引起的
找到源码
function getSocketHost() {
if (process.env.SOCKET_SERVER) {
return stripLastSlash(process.env.SOCKET_SERVER);
}
let host, protocol;
const scripts = document.body?.querySelectorAll?.('script') || [];
const dataFromSrc = scripts[scripts.length - 1]
? scripts[scripts.length - 1].getAttribute('src')
: '';
if (dataFromSrc && dataFromSrc.includes('umi.js')) {
const urlParsed = url.parse(dataFromSrc);
host = urlParsed.host;
protocol = urlParsed.protocol;
} else {
// 某些场景可能没有 umi.js,比如微前端的场景
host = location.host;
protocol = location.protocol;
}
return host && protocol ? url.format({ host, protocol }) : '';
}
可以看到 socket 连接的地址 来源有 process.env.SOCKET_SERVER 以及 url.parse(dataFromSrc) 还有 location
我打开的是10.0.25.102的地址,所以来源不可能是location,但是主应用的socket连接是从location获取的。
ui项目中 scripts 标签也只有 umi.js 的 src 属性。所以解析出来为空。
那么localhost只能是来自 process.env.SOCKET_SERVER 这个环境变量
找到 umijs 插件源码
api.chainWebpack((memo, { webpack }) => {
const port = process.env.PORT;
// source-map 跨域设置
if (api.env === 'development' && port) {
const localHostname = process.env.USE_REMOTE_IP
? address.ip()
: process.env.HOST || 'localhost';
const protocol = process.env.HTTPS ? 'https' : 'http';
// 变更 webpack-dev-server websocket 默认监听地址
process.env.SOCKET_SERVER = `${protocol}://${localHostname}:${port}/`;
// 开启了 devSourceMap 配置,默认为 true
if (api.config.qiankun && api.config.qiankun.slave!.devSourceMap) {
// 禁用 devtool,启用 SourceMapDevToolPlugin
memo.devtool(false);
memo.plugin('source-map').use(webpack.SourceMapDevToolPlugin, [
{
// @ts-ignore
namespace: api.pkg.name,
append: `\n//# sourceMappingURL=${protocol}://${localHostname}:${port}/[url]`,
filename: '[file].map',
},
]);
}
}
return memo;
});
这里可以找到 process.env.SOCKET_SERVER 这个变量赋值的地方。
这里也解释了在执行yarn start的时候赋值环境变量不生效的原因。
因为热更新需要指定子应用的url,包括协议、域名、端口号。脚本执行的时候是在node环境,而非浏览器环境,此时拿不到location的信息。所以只能指定一个固定值。
根源因该是umi配置webpack socket连接的地方,没有提供只 设置 端口的自由度。