本文由 简悦 SimpRead 转码, 原文地址 mp.weixin.qq.com
大厂技术 高级前端 Node 进阶
点击上方 程序员成长指北,关注公众号
回复 1,加入高级 Node 交流群
前言
很早一段时间,我们前端组做了一些国外系统的小优化 (
集中表现在代码执行速度,系统安全等方面),故新建一篇文章来记录这次优化的经历。如果本文对您有帮助,烦请大家一键三连哦, 蟹蟹大家~
- 减小文件体积 / 网络请求
方法一:删除需要预先加载和预先获取的资源,一般使用这种方法
link 标签中的
preload和prefetch:
preload插件用于预加载资源。 即在当前页面加载完成后,立即加载并缓存指定的资源。预加载的资源被认为是当前页面所需的关键资源,因此会优先下载和缓存。prefetch插件用于预获取资源。 即在当前页面加载完成后,异步地加载并缓存指定的资源,以供将来可能需要的页面使用。预获取的资源被认为是可能会在未来的导航中使用的资源,但不是当前页面所必需的。
`vue.config.js`module.exports = { chainWebpack: (config) => { `删除需要预先加载(当前页面)的资源,当需要这些资源的时候,页面会自动加载` config.plugins.delete('preload') `删除需要预先获取(将来的页面)的资源` config.plugins.delete('prefetch') }}方法二:使用
webpack合并小文件合并
js代码的意义:
减少网络请求: 每个文件都需要通过网络进行单独的请求和响应。通过将多个文件合并为一个文件,可以减少页面需要发起的网络请求次数,从而降低延迟和提高加载速度。
缓存优化: 合并代码可以提高浏览器缓存的效率。当多个页面共享同一个文件时,浏览器只需要下载并缓存一次该文件,而不是针对每个页面都下载一次。这样可以减少整体的重复下载和提高缓存命中率。
减少页面渲染阻塞: 当浏览器下载和执行
js代码时,它会阻塞页面的渲染过程。通过合并js代码,可以减少因为多个js文件的下载和执行而造成的页面渲染阻塞时间,提高页面的响应速度和用户体验。代码优化和压缩: 在合并
js代码之前,可以对代码进行优化和压缩,去除空格、注释和不必要的代码,从而减少文件大小,并提高代码的执行效率。
`vue.config.js: `const webpack = require('webpack')const ENV = process.env.NODE_ENVmodule.exports = { chainWebpack: (config) => { config.when(ENV === 'production', config => { config.plugin('webpackOptimize') .use( webpack.optimize.LimitChunkCountPlugin, `限制生成的代码块(chunks)的数量` [{ maxChunks: 10 }] ) .use( webpack.optimize.MinChunkSizePlugin, `指定代码块的最小字节数` [{ minChunkSize: 50000 }] ) }) }}- 优化效果截图
优化前的本地环境:
image.png
优化后的本地环境 (app.js文件较大,是由于main.js引入了大量的第三方库):
优化后的线上环境 (首先,打包后有对这些文件进行压缩处理,app.js被压缩至1.24MB。"inspect": "vue inspect > output.js",使用npm run inspect可以查看webPack的配置信息。其次,运维都有对这些文件作gzip压缩处理, 所以体积都减小了很多, 最终app.js的体积减小至405KB):
image.png
2. 加减乘除运算集成 big.js[1],解决js小数精度问题
- 前提:
当涉及到浮点数计算时,js中的精度丢失问题, 是由于使用IEEE 754标准来表示和计算浮点数的方式引起的。这个问题不仅仅在js中存在,而是在所有使用IEEE 754标准的编程语言中都会遇到。
IEEE 754标准定义了两种常见的浮点数表示形式:单精度(32位)和双精度(64位)。在 js中,采用的是双精度表示法,即64位。
然而,由于二进制和十进制之间的转换存在差异,某些十进制分数无法精确表示为有限位的二进制浮点数。这导致了舍入误差和精度丢失。
安装依赖:
npm install --save big.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')- 测试:
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}`) }) }}结果展示:
image.png
- 使用
bluebird[2] 提升promise的执行速度
- 前提:
bluebird是一个流行的Promise库,用于处理异步操作。它提供了强大的异步编程工具,使得编写和管理异步代码变得更加简单和可靠。
Promise功能增强:bluebird提供了许多额外的功能和操作,超出了原生Promise的范围。它支持超时控制、并发控制、错误处理、重试、进度报告和取消等功能。这些功能使得处理复杂的异步控制流变得更加容易。性能优化:
bluebird在性能方面进行了优化,比原生Promise更快。 它实现了高效的异步调度和内存管理,以提供更快的执行速度和更低的资源消耗。这使得在大规模异步操作的情况下,bluebird可以提供更高效的性能。错误追踪和调试:
bluebird提供了更好的错误追踪和调试支持。 当使用bluebird进行异步操作时,它会生成详细的错误堆栈跟踪信息,包括异步操作链的每个步骤。这使得在调试和排查错误时更容易定位问题所在。可互操作性:
bluebird的api与原生Promise相似,因此可以与其他使用Promise的库和代码进行互操作。 这使得在现有的代码基础上,迁移到bluebird更加容易,并且可以充分利用bluebird提供的额外功能。
安装依赖:
npm install --save bluebird方法封装 (全局挂载):
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`main.js`import bluebird from '@/utils/bluebird'- 测试
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() }}结果展示
image.png
- 使用
hashids[3] 加密路由id
- 前提:
在网址上应用hashids有以下4点重要意义:
加密隐藏真实 id: 在某些情况下,你可能希望隐藏网址中的真实
id,以增加安全性和防止直接暴露敏感信息。使用hashids,可以将真实的数字id转换为短字符串,并在网址中使用该短字符串代替原始id。这样,外部用户只能看到短字符串,而无法直接推断出真实的id值。可读性和美观性: 长的数字
id在网址中可能显得冗长和难以理解。使用hashids将其转换为短字符串,可以大大提升网址的可读性和美观性。短字符串通常包含字母和数字的组合,更易于记忆和分享。防止猜测和遍历: 使用连续的数字
id在网址中可能导致猜测和遍历的风险,因为攻击者可以通过递增id来尝试访问和暴露数据。通过使用hashids生成的短字符串作为id,可以有效地防止这种攻击。由于短字符串是随机生成的,攻击者无法根据短字符串推断出下一个id。URL 缩短和分享:
hashids生成的短字符串可以用作url缩短服务的替代方案。你可以将长的url转换为短字符串,并在分享时使用该短字符串。这对于限制字符数、简化链接以及在社交媒体和短信中共享链接都非常有用。
安装依赖:
npm install --save hashids方法封装 (全局挂载):
`短码方法封装:`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]}`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) }}`在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)})- 测试:
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)}`) }}结果展示 (在同一个盐值下,不管页面是否刷新,编码结果都不会改变):
image.png
- 登陆时使用
行为验证码[4]
- 前提:
登陆时使用行为验证码有以下5点重要意义:
增强安全性: 传统的验证码可以被自动化的机器人或恶意程序轻易地破解或绕过。而
行为验证码通过分析用户的行为模式,可以更准确地识别是否是真实用户,从而提高安全性,防止恶意活动和机器人攻击。用户友好性: 相比于传统的验证码,
行为验证码通常对用户来说更加友好和便捷。用户无需输入复杂的文本或解析模糊的图像,而是通过正常的交互行为完成验证,例如简单的滑动、点击、拖拽等操作。无感知验证:
行为验证码可以在用户进行正常的操作过程中进行验证,几乎无需用户额外的干预或注意。这样可以减少对用户的干扰和阻碍,提升用户体验。自适应性:
行为验证码可以根据用户的行为模式自适应地进行验证。它可以根据用户的设备、IP 地址、浏览器指纹、鼠标移动轨迹等因素来综合评估用户的真实性,从而提高准确性和安全性。防止数据滥用:
行为验证码可以用于防止恶意用户或攻击者滥用系统或服务。通过分析用户的行为模式和交互方式,可以及时识别和阻止异常行为,保护系统和数据的安全。
前端参考文档:https://github.com/Yunlingfly/vue-captcha/tree/master最终效果:
image.png
作者:沐浴在曙光下的贰货道士
链接:https://juejin.cn/post/7264440609129119804
来源:稀土掘金
结语
Node 社群
我组建了一个氛围特别好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你对Node.js学习感兴趣的话(后续有计划也可以),我们可以一起进行Node.js相关的交流、学习、共建。下方加 考拉 好友回复「Node」即可。
“分享、点赞、在看” 支持一下