「如何从0到1实现一个基于vite的前端基础库👾」

3,067 阅读5分钟

大家好,我是速冻鱼🐟,一条水系前端💦,喜欢花里胡哨💐,持续沙雕🌲,是隔壁寒草🌿的好兄弟,刚开始写文章。 如果喜欢我的文章,可以关注➕点赞,为我注入能量,与我一同成长吧~

阅读本文📖

1.您将了解到0-1最简单的JS基础库如何快速搭建

2.您将了解到如何快速搭建一个node服务

3.您将了解到如何写一个vite插件并排坑

本文仓库地址:info-js

前言🌵

造这个库源于突然有天同事在写前端web应用的时候提了一个需求,需要获取客户端的一些相关信息,于是便开始这个库的编写

需求💻

  • 获取客户端浏览器相关信息

  • 获取客户端相关信息

  • 获取WebApp相关信息

  • 获取用户所在ip及相关信息

  • ......

开发思路⭐

1.首先是初始化项目啦

npm init 初始化我们的基础库就叫InfoJs吧

2.完成获取客户端浏览器相关信息需求

由于是获取浏览器相关信息,肯定我们的WebAPI都提供了相应的接口,我们只需要把window对象的属性封装到我们的信息对象上,图中省略了部分代码,文章末尾源码地址

class BrowserInfo {

    //客户端浏览器Window对象
    private _window: Window
    //客户端浏览器对象
    private _navigator: Navigator
    //客户端浏览器的平台和版本信息
    private _appVersion: string = 'unknown'
    //客户机浏览器发送给服务器的user-agent头部的值
    private _userAgent: string = 'unknown'
    //客户端运行浏览器的操作系统平台
    private _platform: string = 'unknown'
    //客户端浏览器的分辨率
    private _screenResolution: string = 'unknown'
    //客户端是否为移动设备
    private _isMobileDevice: boolean = false
    //客户端信息对象
    private _client: ClientInfo | null = null

    //当前app包名
    private _appPackageName:string='unknown'
    //当前项目的app版本号
    private _appVersionCode:string='unknown'
    //当前app运行的环境变量
    private _viteMode:string='unknown'
    //客户端ip
    private _appIpAddress:string='unknown'
    //客户端ip所在国家
    private _appIpCountry:string='unknown'
    //WebApp mode
    private _appMode:string='unknown'

   //...

export {BrowserInfo}


3.window对象的信息还好获取,那用户ip如何获取呢

首先我们得知道ip地址是网络中标识主机的地址,那么我们如何获取它呢,那只能通过网络。 那我们就可以在基础库中发送一个请求到后端,后端请求头中就有了携带ip地址的请求头, 获取到ip地址后我们再将它返回就好啦。

前端编写🎃:

 //获取ip和country信息
        fetch('http://infojs.xyz/api/getipaddress')
            .then(response => response.json())
            .then(data =>{
                this._appIpAddress=data.ipAddress;
                this._appIpCountry=data.ipCountry;
            })
            .catch(e=>console.log('获取客户端ip和ip所在地理位置失败~'))

后端编写🐚(node):

这里使用的是express,小伙伴注意一下跨域访问

  //导入express模块
const express = require('express');
//导入跨域访问模块
const cors = require('cors');
// 创建 express 的服务器实例
const app = express();

这里我的后端服务是通过Cloudflare(全球最快CDN)指过来的,所以请求头中携带有"cf-connecting-ip"和"cf-ipcountry"两个请求头,如果没有用CDN可以通过一下请求头获取并返回给客户端:

若HTTP Header 包含Client-IP,就先以它当作真实IP。 若HTTP Header 包含X-Forwarded-For,则取它当作真实IP。 若两者都没有,则取 REMOTE_ADDR 作为真实IP。

//获取客户端的ip地址
module.exports.getClientIpAddress=(req,res) => {
    console.log(req.headers)
    let ipAddress= req.headers["cf-connecting-ip"]??'unKnow'
        let ipCountry= req.headers["cf-ipcountry"]??'unKnow'
    res.json({
        "ipAddress":ipAddress,
        "ipCountry":ipCountry
    })
}

4.如何获取WebApp相关信息呢

webApp相关信息很多我们都可以在项目package.json文件获取,但这些信息我们只能在编译阶段拿到比如环境变量参数等等,如何解决呢?通过开发服务器插件可以解决,这里我们用的vite,于是就写一个vite插件吧

编写插件:

const path = require("path")
const cwd = process.cwd();
let pkgManifest = require(path.join(cwd, 'package.json'));
module.exports = function () {
    let appVersion = pkgManifest.version
    let appPackageName = pkgManifest.name
    let viteMode = undefined
    const virtualFileId = '@infoJs-plugin-virtual-module'
    return {
        name: 'infoJs-plugin', // 必须的,将会在 warning 和 error 中显示
        config: (UserConfig, {mode}) => {
            viteMode = mode;
        },
        resolveId(id) {
            if (id === virtualFileId) {
                return virtualFileId
            }
        },
        load(id) {
            if (id === virtualFileId) {
                return `
                export const appInfo = {
                "appVersion":"${appVersion}",
                "appPackageName":"${appPackageName}",
                "viteMode":"${viteMode}",
                }
                `
            }
        }
    }

}

通过这个插件获取package.json文件对象,然后通过虚拟目录导出我们的对象

 const virtualFileId = '@infoJs-plugin-virtual-module'

这里有个问题我们如何将我们插件导出的虚拟目录注入到另外一个库文件中呢?

这里直接在库文件中引入这个虚拟路径,由于他不存在所以ts会报错,这里我们//@ts-ignore忽略掉

//@ts-ignore
import {appInfo} from '@infoJs-plugin-virtual-module'

关引入了还是会有问题,编译的时候也会报解析这个路径出错的问题

通过查阅资料如果在库中引入了虚拟路径我们应该这个路径排除在打包的范围之外,这样vite就会忽略它了

vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import infoJsPlugin from '@imf/infojs-plugin'
// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(),infoJsPlugin()],
  //优化包依赖
  optimizeDeps:{
    exclude:['@infoJs-plugin-virtual-module']
  }
})

这样我们就完成了所有需求啦,看到这里可能有的小伙伴有点懵逼,我已经将所有代码上传github了,感兴趣的小伙伴可以去查看一下源码^_^

仓库地址:info-js

结束语🌛

那么我的第一篇文章就结束了,文章的目的其实很简单就是对日常工作的总结和输出,不管菜不菜输出总是有意义的,也希望通过文章认识更多志同道合的朋友,如果你也喜欢折腾,欢迎加我好友,一起沙雕,一起进步。

github🤖:sudongyu

个人博客👨‍💻:速冻鱼blog

vx👦:sudongyuer

写在最后

伙伴们,如果喜欢我的口水话给🐟🐟点一个赞👍或者关注➕都是对我最大的支持。

加我微信:sudongyuer,邀你进群,一起学习前端,成为更优秀的工程师~(群二维码在这里->前端要早睡, 二维码过期了的话看链接沸点中的评论,我会把最新的二维码放在评论区,当然也可以加我微信我拉你进群,毕竟我也是有趣的前端,认识我也不赖🌟~)