手动封装console插件,并发NPM包全流程

小冀第一次写博客,本着帮助大家,分享自己编码生活的日常。

废话不多说,直接上代码 😂😂😂😂

实现原理:继承主动console.log,监听捕获被动日志(分类:框架日志、静态资源日志、axios日志等)

目标:捕获一切日志,并且预留请求埋点。

实现步骤:

1、定义日志等级

 enum LogLevel {

TRACE = 1,

DEBUG = 2,

LOG = 3,

INFO = 4,

WARN = 5,

ERROR = 6

}

2、区分环境

const env = (params: option) => {

nodeENV = params.env

}

3、log权限

const authLog = (params: option) => {

let data: any

if (params.log && params.log.length > 0) {

params.log.forEach((v: any) => {

if (params.env === v) {

data = v

return data

}

})

}

return data

}

4、上报权限

const authReport = (params: option) => {

let data: any

if (params.axios && params.axios.length > 0) {

params.axios.forEach((v: any) => {

if (params.env === v.env) {

data = v

return data

}

})

}

return data

}

5、过滤出所属环境的baseURL

const filterUrl = (params: any) => {

if (params.axios && params.axios.length > 0) {

let data = params.axios.filter((v: any) => params.env === v.env)

return data

}

}

6、格式化日期

const formatDate = (date: Date): string => {

const year = date.getFullYear()

const month = date.getMonth() < 9 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1

const day = date.getDate() <= 9 ? '0' + date.getDate() : date.getDate()

const hour = date.getHours()

const minute = date.getMinutes()

const second = date.getSeconds()

return ${year}-${month}-${day} ${hour}:${minute}:${second}

}

7、查询打印参数中占位符个数

const getPlaceholderNum = (str: string) => {

if (str == null) {

return 0

}

const arr = str.match(/%[csdifoO]/g)

if (arr == null) {

return 0

}

return arr.length

}

8、上报日志

const apiAxios = async (...data: any) => {

try {

let result: any = await reportAxios(data)

if (result.status == '200') {

}

} catch (e) {}

}

9、生成最终的打印参数数组

const generateMessage = (level: LogLevel, ...args: any) => {

const arr1 = [] // 占位符数组

const arr2 = [] // 对象数组

for (let i = 0; i < args.length; i++) {

const arg = args[i]

if (typeof arg == 'object') {

arr1.push('%o')

arr2.push(arg)

} else if (typeof arg == 'string') {

const num = getPlaceholderNum(arg)

if (num > 0) {

arr1.push(arg)

for (let j = 0; j < num; j++) {

arr2.push(args[i + j + 1])

}

i += num

} else {

arr1.push('%s')

arr2.push(arg)

}

} else {

arr1.push('%s')

arr2.push(arg)

}

}

const obj: any = {}

;(Error as any).captureStackTrace(obj, generateMessage)

const stack = obj.stack || ''

const matchResult = stack.match(/at .*/g) || []

arr1.push('%c')

arr2.push(Style[LogLevel[level]])

const arr = [

'',

'',

调用时间:${formatDate(new Date())},

所属环境:${nodeENV},

日志级别:${LogLevel[level]}

]

// 处理堆栈信息

matchResult.splice(0, 1)

if (matchResult.length > 0) {

arr.push('调用堆栈:%s')

arr2.push(${matchResult.join('\n ')})

}

arr1.push(arr.join('\n'))

return [arr1.join(' '), ...arr2]

}

10、继承主动console

const _log = console.log

const _error = console.error

const _info = console.info

const _trace = console.trace

const _warn = console.warn

const _debug = console.debug

11、封装console

const error = function (...args: any) {

if (level <= LogLevel.ERROR) {

if (showDetail) {

_error(...generateMessage(LogLevel.ERROR, ...args))

apiAxios(...generateMessage(LogLevel.ERROR, ...args))

} else {

_error(...args)

}

}

}

const log = function (...args: any) {

if (level <= LogLevel.LOG) {

if (showDetail) {

_log(...generateMessage(LogLevel.LOG, ...args))

apiAxios(...generateMessage(LogLevel.LOG, ...args))

} else {

_log(...args)

}

}

}

const info = function (...args: any) {

if (level <= LogLevel.INFO) {

if (showDetail) {

_info(...generateMessage(LogLevel.INFO, ...args))

apiAxios(...generateMessage(LogLevel.INFO, ...args))

} else {

_info(...args)

}

}

}

const debug = function (...args: any) {

if (level <= LogLevel.DEBUG) {

if (showDetail) {

_debug(...generateMessage(LogLevel.DEBUG, ...args))

apiAxios(...generateMessage(LogLevel.DEBUG, ...args))

} else {

_debug(...args)

}

}

}

const trace = function (...args: any) {

if (level <= LogLevel.TRACE) {

if (showDetail) {

_trace(...generateMessage(LogLevel.TRACE, ...args))

apiAxios(...generateMessage(LogLevel.TRACE, ...args))

} else {

_trace(...args)

}

}

}

const warn = function (...args: any) {

if (level <= LogLevel.WARN) {

if (showDetail) {

_warn(...generateMessage(LogLevel.WARN, ...args))

apiAxios(...generateMessage(LogLevel.WARN, ...args))

} else {

_warn(...args)

}

}

}

12、console逻辑

const Vconsole = {

params: <option>{},

get version() {

return '1.0.19'

},

get showDetail() {

return showDetail

},

set showDetail(value: boolean) {

if (value) {

_info('开启日志详情')

} else {

_info('关闭日志详情')

}

showDetail = value

},

get level() {

return level

},

set level(value: LogLevel) {

_info(设置日志显示级别为:${LogLevel[value]})

level = value

},

error: error,

log: log,

info: info,

debug: debug,

trace: trace,

warn: warn,

async replaceConsole(app: any, envOption: option) {

//1、监听vue报错

app.config.errorHandler = (err: any, vm: any, info: any) => {

console.error(err, vm, info)

}

//2、过滤参数

let params = JSON.parse(JSON.stringify(envOption))

const data = filterUrl(envOption)

if (data) params.axios = data

Vconsole.params = params

//3、区分环境

env(envOption)

//4、log权限

const state: any = authLog(envOption)

if (state) {

console.log = log

console.error = error

console.debug = debug

console.trace = trace

console.info = info

console.warn = warn

}

//5、上报权限

const status: any = authReport(envOption)

if (status) {

console.log = log

console.error = error

console.debug = debug

console.trace = trace

console.info = info

console.warn = warn

}

}

}

13、提供API的格式

interface option {

env: string //当前运行环境

log: string[] //允许控制台输出的环境

axios: {

env: string

url: string // 请求网址

servicePath: string // 请求路径

path: string // 接口路径

method:

| 'get'

| 'GET'

| 'delete'

| 'DELETE'

| 'head'

| 'HEAD'

| 'options'

| 'OPTIONS'

| 'post'

| 'POST'

| 'put'

| 'PUT'

| 'patch'

| 'PATCH'

| 'purge'

| 'PURGE'

| 'link'

| 'LINK'

| 'unlink'

| 'UNLINK' //请求方式

header?: any[]

}[] //允许日志上报的环境及请求配置

}

14、封装axios

import axios from 'axios'

import Vconsole from '../console/index'

const Axios = axios.create()

// 允许跨域请求发送cookie

Axios.defaults.withCredentials = true

Axios.defaults.timeout = 1000 * 60 * 10

Axios.defaults.headers.post['Content-Type'] = 'application/json' // application/x-www-form-urlencoded , multipart/form-data

// http请求拦截

Axios.interceptors.request.use(

async (config) => {

// @ts-ignore

// config.baseURL = ${Vconsole.params.axios[0].url}${Vconsole.params.axios[0].servicePath}

config.baseURL = ${Vconsole.params.axios[0].servicePath}

if (Vconsole.params.axios[0].header && Vconsole.params.axios[0].header.length > 0) {

Vconsole.params.axios[0].header.forEach((v: any) => {

for (let key in v) {

// @ts-ignore

config.headers[key] = v[key]

}

})

}

return config

},

(error) => {

return Promise.reject(error)

}

)

// http响应拦截器

Axios.interceptors.response.use(

async (res) => {

return res.data

},

(error) => {

return Promise.reject(error)

}

)

export default Axios

15、封装API

import Axios from '../axios/axios'

import Vconsole from '../console/index'

export const reportAxios = (data: any) => {

return Axios.request({

url: Vconsole.params.axios[0].url ? Vconsole.params.axios[0].path : 'xxxx',

method: Vconsole.params.axios[0].method ? Vconsole.params.axios[0].method : 'get',

data

})

}

API介绍

参数

说明

类型

默认值

是否必须

注意项

env

当前运行环境

string

填写:生产环境,或者:dev,必须动态传值。例如:window._env_.NODE_ENV

log

允许控制台输出的环境

string[]

必须和上面一致,要汉字都汉字,要字母都字母

axios

参数对象

{}

axios.env

运行环境

string

必须和上面一致,要汉字都汉字,要字母都字母

axios.url

请求网址

string

axios.servicePath

请求路径

string

axios.path

接口路径

string

xxxx

axios.method

请求方式

string

get

axios.header

请求头参数

any[]

app

vue项目中的app类

不详

插件使用:

1、下载包 yarn add ptm-tool-npm-web

2、main.ts里面引入包,并解构出来

import { Vconsole } from 'ptm-tool-npm-web'

3、在项目入口文件执行

Vconsole.replaceConsole(app,{

env:'开发环境',

log:['开发环境','uat'] ,

axios:[{

env:'开发环境',

url:'https://localhost:4000' ,

servicePath:'/api',

path:'/es/send',

method:"post" ,

header:[]

},{

env:'测试环境',

url:'wwwwsdfhkj' ,

servicePath:'/v/d',

path:'/css/a',

method:"get" ,

header:[]

}]

})

实际效果:

终于写完了,暂无发现bug,欢迎大家提建议!下期给大家讲如何做npm包。🤓🤓🤓🤓🤓🤓🤓,码农小冀

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值