Skip to content

202307

INFO

7 月了,还不知道路在哪儿? 要做长久打算!

  • 20230522

0701/0702

0703

  • front end interview 不能荒废,留与不留只在一瞬间.怎样才能让自己一直保持足够的核心竞争力?

  • 又开始写总结,好好回顾,寄希望奇迹 web 端

  • 不会爬虫是硬伤,需要学一学?

0705

  • A future version of React will block javascript: URLs as a security precaution. Use event handlers instead if you can. If you need to generate unsafe HTML try using dangerouslySetInnerHTML instead. React was passed "javascript:;".
js
<a href={undefined} />

href 的值 给 undefined 即可

  • 工作复盘又开始了,回顾半年来的工作重点和成效,真不理解一个搞技术的要背业务绩效的指标,难以理解
  • 配置网关有什么作用,如果不配置网关会有什么后果 访问 xxx.bythewayer.com/xx -> nginx -> 网关 -> 应用服务器
  • node 服务治理

0706

  • 宝贝生日快乐,25 岁了

0707

  • H1 工作总结和项目回归,讲的还是有点急躁,下次一定要慢一点说
  • 工作内容产出不是很多,我感觉杰哥一个人搞得定所有 seo 相关的开发,他一个人绰绰有余,我显得有点多余

0710

  • 跟对象一起去看了电影《消失的她》
  • 最近工作任务蛮重,好像没啥时间来记录生活的琐碎
  • http 请求 header 中的x-powered-by不是 Apache 或者 Nginx 输出的,而是由语言解析器或者应用程序框架输出的, 这个值的意义用于告知网站是用何种语言或框架编写的,如果使用 php 写的,即输出是:X-Powered-By: PHP/7.0.27; 如果使用 nodejs 中的 Nextjs 框架运行的页面,则会显示 X-Powered-By: Next.js

0711

js
const fetch = require("node-fetch");

fetch("https://api.github.com/users/github")
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((error) => console.log(error));

如果不使用第三方库的话,使用原生 fecth api 的话,需要满足 1.nodejs 版本大于 17.5 2.执行 nodejs 脚本的时候带上实验性参数

js
node --experimental-fetch your_code.js
  • 读取 excel 表格,完成数据请求, 然后写入表格新内容, ,需要用到一个 nodejs 库node-xlsx
js
/**
 * node读取excel数据
 * 请求接口 然后填充数据
 */
import fetch from "node-fetch";
import fs from "fs";
import os from "os";
import xlsx from "node-xlsx";

const homedir = os.homedir() + "/Desktop/";
const outputName = "albumId-output.xlsx";

// 读取文件
const fileName = "albumId2.xlsx";
const workSheetsFromBuffer = xlsx.parse(fs.readFileSync(homedir + fileName));

// 请求后端数据
const getData = async (kw) => {
  const url = `http://xxx.xx?&kw=${kw}`;
  const data = await fetch(url);
  return data;
};
async function genData() {
  const sheetData = workSheetsFromBuffer[0].data; // 第一个sheet表单的数据
  for (let i = 1; i < sheetData.length; i++) {
    const item = sheetData[i];
    try {
      const response = await getData(item[1]);
      const data = await response.json();
      const docs = data.data.album.docs;
      const albumId = docs[0].albumId;
      const title = docs[0].title;
      sheetData[i].push(albumId);
      sheetData[i].push(title);
    } catch (e) {
      console.log(e, "eee");
    }
  }
  return [{ name: "test1", data: sheetData }];
}

genData().then((res) => {
  // 自定义列宽
  const sheetOptions = {
    "!cols": [{ wch: 6 }, { wch: 7 }, { wch: 10 }, { wch: 20 }],
  };
  // 生成表格数据对象
  const buffer = xlsx.build(res, sheetOptions);
  // 生成excel 写入表格
  fs.writeFile(homedir + outputName, buffer, (err) => {
    if (err) throw err;
    console.log(`
    --------- ---------生成完毕--------- ---------
        请在桌面查找 ${outputName}
    ---------如需配置生成路径或文件名,请配置output---------
    `);
  });
});

0712

  • document.all 输出当前页面的所以节点,typeof document.all === undefined

  • 反向代理 客户端无法感知代理,因为客户端访问网络不需要配置,只要把请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据,然后再返回到客户端。此时反向代理服务器和目标服务器对外就是一个服务器,暴露的是代理服务器地址,隐藏了真实服务器 IP 地址

  • 基于 upstream 做负载均衡,中间会涉及一些相关的策略比如 ip_hash、weight。nginx 负载均衡方式如下: 1.轮询(默认)。 2.weight,代表权,权越高优先级越高。 3.fair,按后端服务器的响应时间来分配请求,相应时间短的优先分配。 4.ip_hash,每个请求按照访问 ip 的 hash 结果分配,这样每一个访客固定的访问一个后端服务器,可以解决 Session 的问题。

  • 好文推荐React Context 的核心实现,就 5 行代码

0713

  • 手写六月份背诵的面试题
js
Array.prototype.myReduce = function (fn, init) {};
Function.prototype.mockApply = function (fn, ...rest) {};
Function.prototype.mockBind = function (fn, ...rest) {};
function mockNew(fn, context) {}
class LRU {}
function curry(fn) {}
var add = function (...rest) {
  return rest.reduce((a, b) => a + b);
};

function compose(middlewares) {}
function bigInt(a, b) {}
function rgbToHex(str) {}
function hexToRgb(str) {}
  • 匹配 url 里的参数信息
js
var url = "?tt=111&uid=123&shareTime=123";
var regex = /[?&]uid=([^&]+)/;
var match = regex.exec(url);
var uid = match && decodeURIComponent(match[1]);

console.log(uid); // 输出:123

0714

  • HttpDNS 是一种用于解析域名(Domain Name System)的替代方案,它通过使用HTTP 协议而不是传统的 DNS 协议来获取域名对应的 IP 地址。

传统的 DNS 解析过程中,客户端通过向 DNS 服务器发送 DNS 请求,获取域名对应的 IP 地址。然而,DNS 请求的过程可能会受到网络环境的影响,例如 DNS 劫持、DNS 污染等问题,导致域名解析不准确或延迟。

HttpDNS 的工作原理是将域名解析的过程放在了 HTTP 请求中完成。客户端发送一个 HTTP 请求到 HttpDNS 服务器,其中包含需要解析的域名信息。HttpDNS 服务器根据接收到的 HTTP 请求中的域名信息,返回对应的 IP 地址作为响应。客户端接收到 IP 地址后,可以直接使用该地址进行网络通信,无需再进行传统的 DNS 解析过程。

使用 HttpDNS 的好处是可以避免传统 DNS 解析过程中可能遇到的劫持、污染等问题,提高域名解析的准确性和速度。特别是在移动设备网络环境不稳定或存在防火墙限制的情况下,HttpDNS 可以提供更好的解析效果。

要使用 HttpDNS,您需要访问相应的 HttpDNS 服务提供商,并根据其提供的文档和 API,将 HTTP 请求发送到 HttpDNS 服务器,并解析返回的 IP 地址。每个 HttpDNS 服务提供商可能有不同的实现细节和要求,因此具体的使用方式可能会有所差异。

以下是一个简单的示例,展示如何使用 HttpDNS 来获取域名对应的 IP 地址:

js
var dnsUrl = "http://your-httpdns-provider.com/dns-query";
var domain = "example.com";

// 发送HTTP请求到HttpDNS服务器
fetch(dnsUrl + "?name=" + domain)
  .then(function (response) {
    return response.json();
  })
  .then(function (data) {
    var ipAddress = data.ips[0]; // 假设返回的IP地址数组中的第一个为主IP地址
    // 使用获取到的IP地址进行网络通信
    // ...
  })
  .catch(function (error) {
    console.log("Error: " + error);
  });

在上面的示例中,我们使用了 Fetch API 来发送 HTTP 请求到 HttpDNS 服务器,并解析返回的 JSON 格式数据,获取域名对应的 IP 地址。然后可以使用获取到的 IP 地址进行后续的网络通信操作。

请注意,上述示例仅为演示 HttpDNS 的基本原理,实际使用中您需要根据具体的 HttpDNS 服务提供商的要求来构建和发送 HTTP 请求,并处理返回的数据。

0715

js
const server = new Koa();
server.use(async (ctx, next) => {
  if (ctx.request.url === "/cpp") {
    ctx.status = 302;
    ctx.redirect("/ranking");
    ctx.body = "Redirecting to shopping cart";
  } else {
    await next();
  }
});

0716

人生中的第 32 个生日,199107-202307

大学毕业的第九个年头,2014-2023 23-32 明年就是毕业第十年了,依然还是一无所有,碌碌无为

41 + 43 + 26 110 个月 不知道在现在的处境下 还能呆多久

0717

  • 梦到自己失业了,被自己惊醒,在这个不上不下的年纪,失业是早晚的事,我要做的就是在失业前有足够的底气,也就是资本。

现在处境很尴尬,什么都是一成不变,我不允许自己这样。总要学点东西,不能辜负这大美光阴,之前心心念的爬虫抓取,阔以学习下

  • atob() 对经过 base-64 编码的字符串进行解码。你可以使用 window.btoa() 方法来编码一个可能在传输过程中出现问题的数据,并且在接受数据之后,使用 atob() 方法再将数据解码。例如:你可以编码、传输和解码操作各种字符,比如 0-31 的 ASCII 码值。
js
let encodedData = window.btoa("Hello, world"); // 编码
let decodedData = window.atob(encodedData); // 解码

0718

Nextjs 13.0 版本里的数据预取方式 Static Data Fetching

  • Static Data Fetching 静态数据获取

By default, fetch will automatically fetch and cache data indefinitely.

js
fetch("https://..."); // cache: 'force-cache' is the default 相当于之前的getStaticProps
  • Revalidating Data 重新验证数据 To revalidate cached data at a timed interval, you can use the next.revalidate option in fetch() to set the cache lifetime of a resource (in seconds). next.revalidate 选项设置资源的缓存生存期(以秒为单位)
js
fetch("https://...", { next: { revalidate: 10 } });
  • Dynamic Data Fetching 动态获取数据 相当于之前的 getServerSideProps To fetch fresh data on every fetch request, use the cache: 'no-store' option 每次请求的时候都用最新的数据 阔以设置 fetch 中的 no-store 选项
js
fetch("https://...", { cache: "no-store" });
  • 查看当前登录者 npm who am i —registry http://npmjs.com

  • 添加管理员 npm owner add chendapeng @chendap/ui

0719

  • vue 中 css scoped 原理 为组件实例生成一个唯一标识,给组件中的每个标签对应的 dom 元素添加一个标签属性,data-v-xxxx,然后给<style scoped>中的每个选择器的最后一个选择器添加一个属性选择器,原选择器[data-v-xxxx],如:原选择器为.container #id div,则更改后选择器为.container #id div[data-v-xxxx]

  • 专业回答: Scope CSS 的本质是基于 HTML 和 CSS 属性选择器,即分别给 HTML 标签和 CSS 选择器添加  data-v-xxx; 具体来说,它是 通过 vue-loader 实现 的,实现过程大致分 3 步:

    1.首先 vue-loader 会解析 .vue 组件,提取出  template、script、style  对应的代码块;

    2.然后构造组件实例,在组件实例的选项上绑定 ScopedId;

    3.最后对  style  的 CSS 代码进行编译转化,应用 ScopedId 生成选择器的属性;

作者:掘金安东尼

  • rollup Rollup 是一个 JavaScript 模块打包工具,可以将多个小的代码片段编译为完整的库和应用。与传统的 CommonJS 和 AMD 这一类非标准化的解决方案不同,Rollup 使用的是 ES6 版本 Javascript 中的模块标准
  • rollup 配置打包参数
js
rollup src/index.js -f umd -o dist/bundle.js
  • -f 是--format 的缩写,它表示生成代码的格式,-f 的值可以为 amd、cjs、system、esm/es、iife 或 umd 中的任何一个

  • -o 指定了输出的路径,这里我们将打包后的文件输出到 dist 目录下的 bundle.js

  • -c 指定 rollup 的配置文件。

  • -w 监听源文件是否有改动,如果有改动,重新打包。

  • 为什么需要 @rollup/plugin-commonjs 插件

rollup.js 编译源码中的模块引用默认只支持 ES6+的模块方式 import/export。然而大量的 npm 模块是基于 CommonJS 模块方式,这就导致了大量 npm 模块不能直接编译使用。

因此使得 rollup.js 编译支持 npm 模块和 CommonJS 模块方式的插件就应运而生:@rollup/plugin-commonjs。

  • 为啥需要使用@rollup/plugin-node-resolve 插件 @rollup/plugin-node-resolve 插件来处理外部模块(rollup 默认无法处理外部模块,也就是说无法解析打包从 npm 上下载使用的包,使用这个插件可以帮助我们使用)。

  • 为了兼容不同浏览器对 js 的支持,我们必须借助 babel 插件对 es6 代码进行降级转换。

shell
 npm install --save-dev @rollup/plugin-babel @babel/preset-env @babel/core

根目录下创建.babelrc 文件

js
   { "presets": [ [ "@babel/preset-env", { "modules": false, // "useBuiltIns": "usage" } ] ] }
  • 对象参数通过 & 拼接
js
var obj = {
  name: "cpp",
  age: 30,
};
function makeQuery(obj) {
  return Object.keys(obj)
    .filter((k) => obj[k])
    .map((k) => `${k}=${obj[k]}`)
    .join("&");
}
makeQuery(obj); //'name=cpp&age=30'

0720

  • 组织架构再次调整,不知道经过第几次架构调整了,变来变去,不知道这一次是好是坏,作为最底层的员工决定了不了,自己只能决定是自己的态度,有这个想法没这个行动不行

  • 2023 年上半年 GDP 增速 5%,什么时候工资也能超过 gdp 增速?来这边,没有任何荣誉和奖励,没有价值和存在感,算是比较失败的。有得有失,唯一得到的是自己有相对自由的时间和健康的体魄,所以面对没有未来的未来,32 岁的年纪不上不下,如何破局?

  • 控制贪欲,保持理性

  • webpack 如何处理样式文件 less-loader:解析 less 为 css css-loader:将 css 解析为 webpack 能识别的有效模块 style-loader:将解析出来的 css 插入到 header 中

js
// webpack.config.js
module.exports = {
    ...,
    module: {
        rules: [
            {
                test: /.(css|less)$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'less-loader',
                ],
            },
        ]
    }
}

loader 的解析是逆序执行(或从右到左),因此这个配置会按照(less-loader → css-loader → style-loader)以下顺序执行:

1.将 less 解析成 css

2.再将结果传给 css-loader,解析成 webpack 认识的有效模块

3.再将结果传给 style-loader,将解析出来的样式插入到 header)的顺执行。

0721

  • 写复盘总结,如果只是技术层面也很好,就怕是写无关技术方面的总结,好难挤

  • 可以使用一个 useReducer 来代替使用多个 useState,这样写起来可能比较麻烦,但是这样既可以避免不必要的渲染,又可以让逻辑更容易理解。一旦有了 useReducer,向组件添加新逻辑和状态就会容易得多。转自React 最佳实践

js
// bad
import { useState } from "react";

const Component = () => {
  // ❌
  const [text, setText] = useState(false);
  const [error, setError] = useState("");
  const [touched, setTouched] = useState(false);

  const handleChange = (event) => {
    const value = event.target.value;
    setText(value);

    if (value.length < 6) {
      setError("Too short");
    } else {
      setError("");
    }
  };

  return (
    <>
      {!touched && <div>Write something...</div>}
      <input type="text" value={text} onChange={handleChange} />
      <div>Error: {error}</div>
    </>
  );
};

下面这种方式推荐

js
import { useReducers } from "react";

const UPDATE_TEXT_ACTION = "UPDATE_TEXT_ACTION";
const RESET_FORM = "RESET_FORM";

const getInitialFormState = () => ({
  text: "",
  error: "",
  touched: false,
});

const formReducer = (state, action) => {
  const { data, type } = action || {};
  switch (type) {
    case UPDATE_TEXT_ACTION:
      const text = data?.text ?? "";
      return {
        ...state,
        text: text,
        error: text.length < 6,
        touched: true,
      };
    case RESET_FORM:
      return getInitialFormState();
    default:
      return state;
  }
};

const Component = () => {
  // ✅
  const [state, dispatch] = useReducer(formReducer, getInitialFormState());
  const { text, error, touched } = state;

  const handleChange = (event) => {
    const value = event.target.value;
    dispatch({ type: UPDATE_TEXT_ACTION, text: value });
  };

  return (
    <>
      {!touched && <div>Write something...</div>}
      <input type="text" value={text} onChange={handleChange} />
      <div>Error: {error}</div>
    </>
  );
};
  • 当 react 组件不在重新渲染时,使用 useRef 代替 useState
js
import { useRef } from "react";

const Component = () => {
  const triggeredRef = useRef(false);

  useEffect(() => {
    if (!triggeredRef.current) {
      triggeredRef.current = true;

      // ...
    }
  }, []);
};

那为什么需要使用 useRef,而不简单地使用组件外部的变量呢?

js
const triggered = false;

const Component = () => {
  useEffect(() => {
    if (!triggered) {
      triggered = true;

      // ...
    }
  }, []);
};

使用组件外部的变量时,如果组件卸载了,当组件再次挂载时,triggered 变量仍然会被设置为true,因为 triggered 变量并没有绑定到 React 的生命周期中。当使用 useRef 时,React 将在组件卸载并再次安装时重置其值。在这种情况下,就可以要使用 useRef。

0722-0723

周末在家躺平,总是想着看电影,但是没有任何可看的电影,想着锻炼身体,但就是太懒了,啥也不想干!! 谈谈干前端四年的几点感受

0724

  • 手写防抖和节流
js
// 防抖 一段时间内多次触发只会执行一次
function dobounce(fn, time) {
  let timer = null
  return function () {
    var arg = Array.prototype.slice.call(arguments)
    if(timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      fn.apply(this, arg)
      timer = null
    }, time)
  }
}
function throttle(fn, timer) [
  let date = 0
  return function() {
    var arg = Array.prototype.slice.call(arguments)
    var now = new Date().getTime()
    if (now - date >= timer) {
      fn.apply(this, arg)
      date = now
    }
  }
]
  • 手写排序
js
// 冒泡排序 20230724
// 每次冒泡的时候都会比较相邻的两个元素,看是否满足大小关系,不满足就两两互换
function bubbleSort(arr) {
  var len = arr.length;
  for (let i = 0; i < len; i++) {
    for (let j = 0; j < len - i - 1; j++) {
      if (arr[j] > arr[j + 1]) {
        let temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
      }
    }
  }
  return arr;
}
// 选择排序
/**
 * 将数组最小的元素放在数组最前面,再从剩下的未排序中寻找最小的元素,然后将其放到以排序的后面,以此类推,直到排序完成
 */
function selectSort(arr) {
  var temp;
  let minIndex = 0;
  for (let i = 0; i < arr.length; i++) {
    minIndex = i;
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[minIndex] > arr[j]) {
        minIndex = j;
      }
    }
    let temp = arr[i];
    arr[i] = arr[minIndex];
    arr[minIndex] = temp;
  }
}
// 归并排序
/*
天生资质不行,硬记不行,还需要理解!!!
将排序数组分解为规模更小的子问题进行处理m,再将处理好的子问题合并起来
分解:将原问题分解成一系列子问题。
解决:递归求解各个子问题,若子问题足够小,则直接求解。
合并:将子问题的结果合并成原问题。
*/
function mergeSort(arr) {
  var merge = (right, left) => {
    var res = [];
    var i = 0,
      j = 0;
    while (i < left.length && j < right.length) {
      if (left[i] < right[j]) {
        res.push(left[i++]);
      } else {
        res.push(right[j++]);
      }
    }
    while (i < left.length) {
      res.push(left[i++]);
    }
    while (j < right.length) {
      res.push(right[j++]);
    }
    return res;
  };
  const sort = (arr) => {
    if (arr.length === 1) return arr;
    var base = Math.floor(arr.length / 2);
    var left, right;
    left = arr.slice(0, base);
    right = arr.slice(base);
    return merge(mergeSort(left), mergeSort(right));
  };
}
// 快速排序
/**
 * 从数组中挑一个作为基准,将元素比基准小的放到基准前面,大的放在基准后面,然后递归调用quickSort方法
 */
function quickSort(arr) {
  if (arr.length <= 1) return arr; // 递归结束条件
  var mirror = arr[0];
  let left = [],
    right = [];
  for (let i = 1; i < arr.length; i++) {
    let cur = arr[i];
    if (cur > mirror) {
      right.push(cur);
    } else {
      left.push(cur);
    }
  }
  return [...quickSort(left), mirror, ...quickSort(right)];
}
// 插入排序
/**
 * 对于未排序的数据在已排序的序列中从后往前扫描 找到相应的位置插入,保持已排序的数组一直有序
 */
function insertSort(arr) {
  var len = arr.length;
  for (let i = 1; i < len; i++) {
    let j = i;
    let temp = arr[i];
    while (j >= 0 && arr[j - 1] > temp) {
      arr[j] = arr[j - 1];
      j--;
    }
    arr[j] = temp;
  }
  return arr;
}

插入排序

  • 20 行手写 promise
js
class MyPromise {
  constructor(executor) {
    this.cbs = [];
    this.value = undefined;
    const resolve = (val) => {
      setTimeout(() => {
        this.data = val;
        this.cbs.forEach((cb) => cb(val));
      }, 0);
    };
    executor(resolve);
  }
  then(onFulfilled) {
    return new MyPromise((resolve) => {
      this.cbs.push(() => {
        const res = onFulfilled(this.data);
        if (res instanceof MyPromise) {
          res.then(resolve);
        } else {
          resolve(res);
        }
      });
    });
  }
}

var p1 = new MyPromise((resolve) => {
  setTimeout(() => {
    resolve("11");
  });
});
p1.then((res) => {
  console.log(res);
  return new MyPromise((resolve) => {
    setTimeout(() => {
      resolve(222);
    }, 500);
  });
}).then((res) => {
  console.log(res);
});
  • 手写二分法
js
// 给定一个  n  个元素有序的(升序)整型数组  nums 和一个目标值  target  ,写一个函数搜索  nums  中的 target,如果目标值存在返回下标,否则返回 -1。
// left 和 right 是一个区间,由base所决定的期间大小
function binary(arr, target) {
  var left = 0;
  var right = arr.length - 1;
  while (left <= right) {
    var base = left + Math.floor((right - left) / 2);
    if (arr[base] > target) {
      right = base - 1;
    } else if (arr[base] < target) {
      left = base + 1;
    } else {
      return base;
    }
  }
  return -1;
}

0725

  • 都喜欢画大饼,听多了感觉就是愚蠢至极,难以兑现的大饼就算了,做人还是需要真诚

  • 潮水即将褪去,看谁还在裸泳?论程序员的自我修养

  • 手写题,颜色模式转换

js
// hexToRgb #fffff => rgb(255,255,255)
function hexToRgb(str) {
  var hex = str.replace("#", "0x");
  var r = hex >> 16;
  var g = (hex >> 8) & "0xff";
  var b = hex & "0xff";
  return `rgb(${r}, ${g}, ${b})`;
}
// rgbToHex rgb(255,255,255) => #ffffff
function rgbToHex(str) {
  str = rgb.split(/[^\d]+/);
  var [, r, g, b] = str;
  var toHex = (val) => {
    var hex = (+val).toString(16);
    return hex.length === 1 ? "0" + hex : hex;
  };
  return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}
// cpp-wmh => cppWmh
function toUpper(str) {}

0726

  • 微信小程序更新版本,去掉一键登录功能
  • 一测试人员离职,硬性指标,所以未来说不准
  • 手写 vue 模板解析函数
js
// 输入: render({{msg}}-{{name}}, {msg: 'chendap', name: 'wmh'}) 输出: 'chendap-wmh'
function render(str, data) {
  var reg = /\{\{(\w+)\}\}/;
  if (reg.test(str)) {
    const name = RegExp.$1.trim();
    str = str.replace(reg, data[name]);
    return render(str, data);
  }
  return str;
}
render(`{{msg}}-{{name}}`, { msg: "chendap", name: "wmh" });
  • Service Worker 是什么,具体有哪些使用场景

0727

浏览器缓存优先级

  • memory cache 内存缓存,读取内存中的数据,速度最快,但缓存可持续性会很短,会随着进程的释放而释放,一旦我们关闭 Tab 页面,内存中的缓存也就被释放了

  • service worker 是运行在浏览器背后的独立线程,一般可以用来实现缓存功能

  • Disk Cache 磁盘缓存 读取速度慢一点,但是什么都能存储到磁盘中,比之 Memory Cache 胜在容量和存储时效性上,相同地址的资源一旦被缓存起来,就不会再次请求数据,主要是根据 http 中的 Header 来判断哪些资源需要缓存,哪些资源可以不请求直接使用,哪些资源已经过期需要重新请求

  • Push Cache Push Cache 是 HTTP/2 中的内容,当以上三种缓存都没有命中时,它才会被使用,并且缓存时间也很短暂,只在会话(Session)中存在,一旦会话结束就被释放

0728

  • 779
  • 周五 小程序继续开发

0729/0730

0731

  • 782,每天都有压迫感和紧迫感,主要还是没有足够的底气和自信来源于工作和未来
  • 从来没有过的节约和窘迫感,感觉回到了刚毕业的 2014/2015 年