const getEntry = (base: string, port: number) => {const host: string = location.hostnamereturn 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 配置,默认为 trueif (api.config.qiankun && api.config.qiankun.slave!.devSourceMap) {// 禁用 devtool,启用 SourceMapDevToolPluginmemo.devtool(false);memo.plugin('source-map').use(webpack.SourceMapDevToolPlugin, [{// @ts-ignorenamespace: 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连接的地方,没有提供只 设置 端口的自由度。