这些天,我们前端组一起处理的项目优化

前言

大家好,我是前端贰货道士 。很早一段时间,我们前端组做了一些国外系统的小优化(集中表现在代码执行速度,系统安全等方面),故新建一篇文章来记录这次优化的经历。如果本文对您有帮助,烦请大家一键三连哦, 蟹蟹大家~

1. 使用webpack合并打包生成的js文件

  • 前提:

合并js代码的意义:

  1. 减少网络请求: 每个js文件都需要通过网络进行单独的请求和响应。通过将多个js文件合并为一个文件,可以减少页面需要发起的网络请求次数,从而降低延迟和提高加载速度。
  2. 提高加载速度: 合并js代码可以减少网页中需要下载的总文件大小。较小的文件大小意味着更快的下载速度,因为客户端需要花费更少的时间来获取和接收文件。
  3. 缓存优化: 合并js代码可以提高浏览器缓存的效率。当多个页面共享同一个js文件时,浏览器只需要下载并缓存一次该文件,而不是针对每个页面都下载一次。这样可以减少整体的重复下载和提高缓存命中率。
  4. 减少页面渲染阻塞: 当浏览器下载和执行js代码时,它会阻塞页面的渲染过程。通过合并js代码,可以减少因为多个js文件的下载和执行而造成的页面渲染阻塞时间,提高页面的响应速度和用户体验。
  5. 代码优化和压缩: 在合并js代码之前,可以对代码进行优化和压缩,去除空格、注释和不必要的代码,从而减少文件大小,并提高代码的执行效率。
  • link 标签中的preloadprefetch
  1. preload插件用于预加载资源。 即在当前页面加载完成后,立即加载并缓存指定的资源。预加载的资源被认为是当前页面所需的关键资源,因此会优先下载和缓存。
  2. prefetch插件用于预获取资源。 即在当前页面加载完成后,异步地加载并缓存指定的资源,以供将来可能需要的页面使用。预获取的资源被认为是可能会在未来的导航中使用的资源,但不是当前页面所必需的。
js 复制代码
`vue.config.js: `

`方法一:`
module.exports = {
  chainWebpack: (config) => {
    `删除需要预先加载(当前页面)的资源`
    config.plugins.delete('preload')  
    `删除需要预先获取(将来的页面)的资源`
    config.plugins.delete('prefetch')
  }
}

`方法二:`
const webpack = require('webpack')
const ENV = process.env.NODE_ENV

module.exports = {
  chainWebpack: (config) => {
    config.when(ENV === 'production', config => {
      config.plugin('webpackOptimize')
      .use(
        webpack.optimize.LimitChunkCountPlugin, 
        `限制生成的代码块(chunks)的数量`
        [{ maxChunks: 10 }]
      )
      .use(
        webpack.optimize.MinChunkSizePlugin, 
        `指定代码块的最小字节数`
        [{ minChunkSize: 50000 }]
      )
    })
  }
}

合并前:

合并后:

2. 加减乘除运算集成big.js,解决js小数精度问题

  • 前提:

当涉及到浮点数计算时,js中的精度丢失问题, 是由于使用IEEE 754标准来表示和计算浮点数的方式引起的。这个问题不仅仅在js中存在,而是在所有使用IEEE 754标准的编程语言中都会遇到。

IEEE 754标准定义了两种常见的浮点数表示形式:单精度(32位)和双精度(64位)。在 js中,采用的是双精度表示法,即64位。

然而,由于二进制和十进制之间的转换存在差异,某些十进制分数无法精确表示为有限位的二进制浮点数。这导致了舍入误差和精度丢失。

  • 安装依赖: npm install --save big.js
  • 方法封装:
js 复制代码
import Big from 'big.js'

export function accFactory(method = 'add') {
  return function (...nums) {
    `将传入的参数转换为Number类型,并过滤掉不是Number类型的结果`
    nums = nums.map(Number).filter((num) => num || num === 0)
    `如果过滤后的结果是长度为1的数组,那就返回数组的第一项`
    `如果过滤后的结果为空数组,则返回0`
    if (nums.length < 2) return nums[0] || 0
    `需要为reduce方法赋初值,是因为big.js的运算操作,是基于new Big格式的数字`
    `可以将Big对象转换为浮点数,方便后续Number.toFixed()的操作`
    return parseFloat(nums.slice(1).reduce((prev, num) => prev[method](num), new Big(nums[0]))) || 0
  }
}

`plus、minus、times、div为big.js中的计算方法,分别对应加减乘除这四个运算操作`

`浮点数求和`
export const accAdd = accFactory('plus')
`浮点数相减`
export const accSub = accFactory('minus')
`浮点数相乘`
export const accMul = accFactory('times')
`浮点数相除`
export const accDiv = accFactory('div')
  • 测试:
js 复制代码
import { accAdd, accSub, accMul, accDiv } from '@/utils/calculate'

mounted() {
  this.calTestHandler()
},

methods: {
  calTestHandler() {
    const operations = [
      { operator: '+', method: accAdd, a: 0.1, b: 0.2 },
      { operator: '-', method: accSub, a: 0.1, b: 0.3 },
      { operator: '*', method: accMul, a: 0.1, b: 0.2 },
      { operator: '/', method: accDiv, a: 0.1, b: 0.3 }
    ]
 
    operations.forEach((operation) => {
      const { operator, method, a, b } = operation
      const result = method(a, b)
      console.log(`原生js ${operator} 运算:${a} ${operator} ${b}的值是${eval(a + operator + b)}`)
      console.log(`big.js ${operator} 运算:${a} ${operator} ${b}的值是${result}`)
    })
  }
}

结果展示:

3. 使用bluebird提升promise的执行速度

  • 前提:

bluebird是一个流行的Promise库,用于处理异步操作。它提供了强大的异步编程工具,使得编写和管理异步代码变得更加简单和可靠。

  1. Promise功能增强: bluebird提供了许多额外的功能和操作,超出了原生Promise的范围。它支持超时控制、并发控制、错误处理、重试、进度报告和取消等功能。这些功能使得处理复杂的异步控制流变得更加容易。
  2. 性能优化:bluebird在性能方面进行了优化,比原生Promise更快。 它实现了高效的异步调度和内存管理,以提供更快的执行速度和更低的资源消耗。这使得在大规模异步操作的情况下,bluebird可以提供更高效的性能。
  3. 错误追踪和调试:bluebird提供了更好的错误追踪和调试支持。 当使用bluebird进行异步操作时,它会生成详细的错误堆栈跟踪信息,包括异步操作链的每个步骤。这使得在调试和排查错误时更容易定位问题所在。
  4. 可互操作性:bluebirdapi与原生Promise相似,因此可以与其他使用Promise的库和代码进行互操作。 这使得在现有的代码基础上,迁移到bluebird更加容易,并且可以充分利用bluebird提供的额外功能。
  • 安装依赖: npm install --save bluebird
  • 方法封装(全局挂载):
js 复制代码
import Promise from 'bluebird'

Promise.config({

  `确定是否启用警告输出。当设置为true,bluebird会在控制台输出警告,例如不推荐使用的方法或潜在问题`
  warnings: false,
  
  `确定是否启用长堆栈跟踪, bluebird会生成详细的异步调用堆栈信息,包括Promise链中的每个步骤。`
  `这对于调试和错误追踪非常有用, 但启用长堆栈跟踪,可能会对性能产生一些影响`
  longStackTraces: false,
  
  `确定是否启用取消功能。当设置为true时,bluebird允许取消异步操作。`
  `取消一个Promise将导致其相关的操作被中断或忽略,有助于优化资源使用和控制异步流程。`
  cancellation: true,
  
  `确定是否启用性能监视。当设置为true时,bluebird可以收集异步操作的性能数据,例如执行时间、调用次数等。`
  `这对于分析和优化异步操作的性能非常有用。`
  monitoring: true,
  
  `确定是否启用异步挂钩。异步挂钩是node.js提供的一种机制,可以在异步操作的不同阶段执行回调函数。`
  `当设置为true时,bluebird将使用异步挂钩来跟踪和管理异步操作`
  asyncHooks: false
})
window.bluePromise = Promise
js 复制代码
`main.js`

import bluebird from '@/utils/bluebird'
  • 测试
js 复制代码
mounted() {
 this.proTestHandler()
},

methods: {
  async proTestHandler() {
    const promises = []
    const bluebirds = []
    
    const promiseList = (promise, count, arr) => {
      for (let i = 0; i < count; i++) {
        arr.push(new promise((resolve) => resolve(i)))
      }
    }
    
    const generatePromises = () => {
      promiseList(Promise, 1000000, promises)
      promiseList(bluePromise, 1000000, bluebirds)
    }
    
    generatePromises()
    console.log('promise')
    console.time()
    await Promise.all(promises)
    console.timeEnd()
    console.log('bluebirds')
    console.time()
    await bluePromise.all(bluebirds)
    console.timeEnd()
  }
}

结果展示

4. 使用hashids加密路由id

  • 前提:

在网址上应用hashids有以下4点重要意义:

  1. 加密隐藏真实id: 在某些情况下,你可能希望隐藏网址中的真实id,以增加安全性和防止直接暴露敏感信息。使用hashids,可以将真实的数字id转换为短字符串,并在网址中使用该短字符串代替原始id。这样,外部用户只能看到短字符串,而无法直接推断出真实的id值。
  2. 可读性和美观性: 长的数字id在网址中可能显得冗长和难以理解。使用hashids将其转换为短字符串,可以大大提升网址的可读性和美观性。短字符串通常包含字母和数字的组合,更易于记忆和分享。
  3. 防止猜测和遍历: 使用连续的数字id在网址中可能导致猜测和遍历的风险,因为攻击者可以通过递增id来尝试访问和暴露数据。通过使用hashids生成的短字符串作为id,可以有效地防止这种攻击。由于短字符串是随机生成的,攻击者无法根据短字符串推断出下一个id
  4. URL缩短和分享: hashids生成的短字符串可以用作url缩短服务的替代方案。你可以将长的url转换为短字符串,并在分享时使用该短字符串。这对于限制字符数、简化链接以及在社交媒体和短信中共享链接都非常有用。
  • 安装依赖: npm install --save hashids

  • 方法封装(全局挂载):

js 复制代码
`短码方法封装:`

import Hashids from 'hashids'

const hashids = new Hashids(

  `盐值是一个可选的字符串参数,用于增加生成的短码的唯一性和安全性。每个不同的盐值将产生不同的短码序列,`
  `可以将盐值视为项目的名称或标识符。如果不提供盐值,则默认为一个空字符串。`
  
  'toadditWeb', 
  
  `是一个可选的整数参数,用于指定生成的短码的最小长度。如果生成的短码长度小于指定的最小长度,`
  `hashids会自动填充短码以达到最小长度。这只是一个最小长度的限制,实际生成的短码长度可能更长。`
  `如果不提供最小长度,则默认为0,即没有最小长度限制。`
  8, 
  
  `字母表是一个可选的字符串参数,用于定义生成短码时使用的字符集。该字符串包含所有可用于生成短码的字符。` 
  `通常,字母表中应包含一组不容易混淆的字符,以避免生成的短码产生歧义。如果不提供字母表,则默认为`
  `"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"`。
)

`短码封装`
export function encode(val) {
  return hashids.encode(val)
}

`短码解析`
export function decode(val) {
  return hashids.decode(val)[0]
}
js 复制代码
`glboal.js: 全局注册`

import { encode, decode } from '@/utils/hashids'

export default {
  install(Vue) {
    Vue.prototype.$encode = window.$encode = (data) => encode(data)
    Vue.prototype.$decode = window.$decode = (data) => decode(data)
  }
}
js 复制代码
`在main.js中挂载:`

import Vue from 'vue'
import App from './App'
import globalConst from '@/commons/globalConst'

Vue.use(globalConst)

new Vue({
  el: '#app',
  router,
  store,
  render: (h) => h(App)
})
  • 测试:
js 复制代码
mounted() {
  this.hashTestHandler()
},

methods: {
  hashTestHandler() {
    const testId = 18
    const encode = $encode(testId)
    console.log(`hashids编码前: ${testId}`)
    console.log(`hashids编码: ${encode}`)
    console.log(`hashids解码: ${$decode(encode)}`)
  }
}

结果展示(在同一个盐值下,不管页面是否刷新,编码结果都不会改变):

5. 登陆时使用行为验证码

  • 前提:

登陆时使用行为验证码有以下5点重要意义:

  1. 增强安全性: 传统的验证码可以被自动化的机器人或恶意程序轻易地破解或绕过。而行为验证码通过分析用户的行为模式,可以更准确地识别是否是真实用户,从而提高安全性,防止恶意活动和机器人攻击。
  2. 用户友好性: 相比于传统的验证码,行为验证码通常对用户来说更加友好和便捷。用户无需输入复杂的文本或解析模糊的图像,而是通过正常的交互行为完成验证,例如简单的滑动、点击、拖拽等操作。
  3. 无感知验证: 行为验证码可以在用户进行正常的操作过程中进行验证,几乎无需用户额外的干预或注意。这样可以减少对用户的干扰和阻碍,提升用户体验。
  4. 自适应性: 行为验证码可以根据用户的行为模式自适应地进行验证。它可以根据用户的设备、IP地址、浏览器指纹、鼠标移动轨迹等因素来综合评估用户的真实性,从而提高准确性和安全性。
  5. 防止数据滥用: 行为验证码可以用于防止恶意用户或攻击者滥用系统或服务。通过分析用户的行为模式和交互方式,可以及时识别和阻止异常行为,保护系统和数据的安全。
js 复制代码
前端参考文档:https://github.com/Yunlingfly/vue-captcha/tree/master

最终效果:

结语

往期精彩推荐(强势引流):

面试不面试,你都必须得掌握的vue知识

无论如何,你都必须得掌握的JS知识

无论如何,你都必须得掌握的JS知识(续)

我的css世界

什么?都2022年了,你还在一遍又一遍重复写form表单?

大概就这样吧。更多精彩文章正在快马加鞭创作中,敬请期待哦~

相关推荐
码界奇点几秒前
Java Web学习 第1篇前端基石HTML 入门与核心概念解析
java·前端·学习·xhtml
云枫晖6 分钟前
Webpack系列-开发环境
前端·webpack
Rverdoser10 分钟前
制作网站的价格一般由什么组成
前端·git·github
拉不动的猪11 分钟前
深入理解 JavaScript 中的静态属性、原型属性与实例属性
前端·javascript·面试
linda261819 分钟前
链接形式与跳转逻辑总览
前端·javascript
怪可爱的地球人23 分钟前
骨架屏
前端
用户6778471506227 分钟前
前端将html导出为word文件
前端
前端付豪29 分钟前
如何使用 Vuex 设计你的数据流
前端·javascript·vue.js
李雨泽31 分钟前
通过 Prisma 将结构推送到数据库
前端
前端小万35 分钟前
使用 AI 开发一款聊天工具
前端·全栈