Skip to content

通过os模块获取本地主机地址

需求来源

为什么要这么做呢?因为有个需求是用户可以在局域网内通过微信扫码跳转到点餐H5网页进行点餐,考虑到该H5网页可能运行在不同的局域网主机中,因此必须知道获取后端服务运行在哪个主机当中,比如我在本地的电脑通过pm2起了一个node服务,那么通过微信扫码访问的H5网页如果想要能够访问该node服务的接口的话,就不能使用localhost来访问,只能使用主机的ip地址来访问。那么,如何获取主机ip地址呢?

获取本地主机地址的思路以及实现

思路

由于浏览器的限制,在前端获取主机ip并不是一件容易的事情,因此刚开始我的想法就是在后端获取完主机ip地址然后通过接口的方式返回给前端,然后前端将其保存为全局变量。但是由于后端服务有可能运行在局域网的不同主机上,因此他的局限是我前端需要你服务端主机的ip地址来访问接口获取你的主机地址(这方案的可靠之处是我必须知道后端的主机ip),但在这场景之下我并不能知道。这本身就是一件矛盾的事情。因此只能前端来做。但是前端应该怎么做呢?通过vite.config.ts这个配置文件我知道了在前端项目中也能够引入node相对应的模块,比如path,os等,恰巧os模块能够正确的获取主机的ip,到这问题就解决了。获取到主机ip地址之后,我选择将其保存在vite自带的全局变量import.meta.env当中,这样子就能方便的存取了。

实现

javascript
import os from 'node:os'

const getLocalIp =  () => {
    const interfaces = os.networkInterfaces()
    const addresses: string[] = []
    for (const iface in interfaces) {
        if (interfaces[iface]) {
            for (const ifaceDetails of interfaces[iface]) {
                if (ifaceDetails.family === 'IPv4' && !ifaceDetails.internal) {
                    addresses.push(ifaceDetails.address)
                }
            }
        }
    }
    return addresses.length > 0 ? addresses[0] : 'localhost'
}

怎么将获取的主机ip地址保存到vite全局变量呢?vite官方提供了define这个配置选项,我们只需要给这个配置选项新加一个键值对就可以了,键的格式必须为import.meta.env.xxx,值必须为string类型。类似如下:

javascript
export default defineConfig(() => ({
    define: {
        'import.meta.env.BASE_IP': JSON.stringify(address)
    }
}))