首页 > 编程学习 > umi项目本地开发环境远程打开的问题

umi项目本地开发环境远程打开的问题

发布时间:2022/11/16 17:47:37
  1. qiankun主应用加载子应用时,url指定了localhost
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连接的地方,没有提供只 设置 端口的自由度。

Copyright © 2010-2022 dgrt.cn 版权所有 |关于我们| 联系方式