圆弧派博客 - 专注于网络技术 - JavaScript https://www.iarc.top/group/JavaScript/ zh-CN JavaScript代码分享 Wed, 29 Apr 2026 16:59:00 +0800 Wed, 29 Apr 2026 16:59:00 +0800 Gzip与Brotli压缩配置指南 https://www.iarc.top/520.html https://www.iarc.top/520.html Wed, 29 Apr 2026 16:59:00 +0800 青帝 在现代 Web 性能优化中,传输体积往往是页面加载速度的第一杀手。一个未经压缩的 JavaScript 文件可能高达几百 KB,而启用压缩后传输量能直接下降 70% 以上,这对带宽和首屏时间的影响是立竿见影的。今天我们就来系统梳理一下目前使用最广泛的两种 HTTP 压缩方案——GzipBrotli,从原理、配置到调优,帮你一次性搞懂它们的区别与最佳实践。

mojto9df.png


一、为什么我们需要压缩?

HTTP 压缩的本质,是在服务器端对响应体进行编码,浏览器收到后再解码,从而在网络中传输更少的数据。代价是消耗少量 CPU 做压缩/解压,但在带宽成本远高于 CPU 成本的今天,这笔交易非常划算。

一个典型的 HTML 文件经 Gzip 压缩后可缩减至原大小的 20%-30%;而 Brotli 还能在此基础上再压缩 15%-25%。这不仅能提升首次内容绘制(FCP),还能直接降低 CDN 流量费用。


二、Gzip:老将不老

2.1 背景与原理

Gzip 诞生于 1992 年,基于 DEFLATE 算法(LZ77 + Huffman 编码)。它通过寻找重复字符串(LZ77 滑动窗口)并构建哈夫曼树来压缩文本,几乎所有现代浏览器和服务器都支持,兼容性无与伦比。

2.2 Nginx 配置 Gzip

在 Nginx 中开启 Gzip 非常简单,通常只需在 httpserverlocation 块中加入:

gzip on;
gzip_comp_level 6;                # 压缩级别 1-9,5-6 是性价比之选
gzip_min_length 256;              # 小于此字节不压缩,避免负优化
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
gzip_vary on;                     # 响应头添加 Vary: Accept-Encoding,方便代理缓存
gzip_proxied any;                 # 对所有代理请求启用压缩
gzip_disable "msie6";             # 禁用对 IE6 的压缩(可省略)

重启 Nginx 后,检查响应头是否出现 Content-Encoding: gzip 即可。

2.3 Apache 与 Node.js

  • Apache:启用 mod_deflate,使用 AddOutputFilterByType DEFLATE 指令配置 MIME 类型。
  • Node.js (Express):使用中间件 compression,默认使用 Gzip,可根据 Accept-Encoding 自动协商。

Gzip 的优势在于成熟、CPU 消耗低、兼容性完美,几乎是最低配置成本的基础优化。


三、Brotli:新一代压缩利器

3.1 Google 出品,压缩率更优

Brotli 是 Google 在 2015 年推出的压缩算法,最初用于 WOFF2 字体格式。它结合了 LZ77、Huffman 编码以及一个静态预定义字典——这个字典包含了大量 Web 文本(HTML、CSS、JS)中常见的字符串片段,因此在压缩这类内容时具有天然优势。此外,Brotli 支持更大的滑动窗口(最大 16MB),可以找到更远的重复数据。

相比 Gzip,Brotli 的压缩率通常高出 15-25%,但压缩速度较慢(尤其在高等级),解压速度则与 Gzip 相近,完全适合一次压缩、多次解压的场景(如静态资源)。

3.2 浏览器支持

所有现代浏览器(Chrome、Firefox、Safari、Edge)均通过 Accept-Encoding: br 宣告支持 Brotli。国内除部分老旧浏览器外,覆盖已不成问题。可以放心将其作为优先压缩方案。

3.3 Nginx 安装与配置 Brotli

Nginx 官方并未内置 Brotli,需要额外编译模块 ngx_brotli。以从源码编译为例:

# 下载 Nginx 源码与 brotli 模块
git clone https://github.com/google/ngx_brotli.git
cd ngx_brotli && git submodule update --init

# 编译 Nginx 时加入 --add-module=../ngx_brotli
./configure --add-module=/path/to/ngx_brotli ...
make && make install

安装后即可在配置中使用:

brotli on;
brotli_comp_level 6;             # 压缩级别 0-11,推荐 5-6
brotli_static on;                # 启用预压缩文件检查 (.br)
brotli_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript;
brotli_min_length 256;

brotli_static on 非常实用:如果服务器上同时存在 style.cssstyle.css.br,Nginx 会直接返回预压缩的 .br 文件,避免每次压缩的开销,适合构建流程中提前压缩静态资源。

3.4 Apache 与 CDN

  • Apache 可通过 mod_brotli 模块启用,配置类同。
  • 各大 CDN(阿里云、Cloudflare 等)均默认支持 Brotli 无损压缩,仅需勾选启用。

四、Gzip vs Brotli:核心对比

维度GzipBrotli
压缩率中等高 15-25%
压缩速度较慢(尤其是 level > 6)
解压速度接近 Gzip
CPU 消耗较高
浏览器兼容所有现代浏览器
静态预压缩.gz.br
适合场景动态内容、API 响应静态资源、文本类文件

要点:Brotli 不是 Gzip 的替代品,而是“增强补丁”。我们应该同时启用两者,让浏览器通过 Accept-Encoding 自动协商最优格式。


五、最佳实践与调优建议

5.1 双启用,协商优先

Nginx 可这样配置以同时支持 Gzip 和 Brotli:

# 同时开启
gzip on;
brotli on;

# Brotli 优先级高于 Gzip,浏览器会优先请求 br
# 由 Accept-Encoding 头自动决定,无需额外操作

当客户端发来 Accept-Encoding: br, gzip 时,Nginx 会优先使用 Brotli 压缩(若满足规则)。对于不支持 br 的旧浏览器,则降级为 Gzip。

5.2 哪些内容应该压缩?

  • 文本类型text/htmltext/csstext/javascriptapplication/jsonapplication/xmlimage/svg+xml
  • JavaScript/CSS 文件:未压缩的 application/javascripttext/css
  • 字体文件:WOFF(已压缩)不用压缩,但 font/ttffont/otf 可酌情压缩。

不压缩的类型包括:图片(image/*)、视频、音频、已压缩格式(如 .zip.woff2.wasm)。否则徒增 CPU 且可能越压越大。

5.3 压缩级别选择

  • Gzipcomp_level 5-6 为甜点区间,再高收益递减。若 CPU 资源充裕且流量巨大,可升至 9 换取微小体积优势。
  • Brotlicomp_level 5-6 同样是最佳性价比。静态资源可在构建期使用最高级别 11 生成 .br 文件(如 webpack 插件 brotli-webpack-plugin),线上即可用 brotli_static on 直接分发,兼顾极致压缩率与零 CPU 开销。

5.4 利用缓存与 Conditional Requests

启用压缩后,不要忘记配合 ETag/Last-Modified,并设置合理的 Cache-Control。对于预压缩文件,如果更新了原文件,记得同步更新 .br.gz,否则缓存会出问题。

5.5 安全:BREACH 攻击

Brotli 与 Gzip 都可能面临 BREACH(破解 HTTPS 响应体中的秘密)攻击。若你的站点涉及高度敏感数据(如 CSRF token),需要随机化响应长度或使用防 BREACH 的补丁。大多数普通业务场景下,此项风险较低。

5.6 CDN 层面的配置

如果你使用 CDN,强烈建议在源站先配置好压缩,并在 CDN 侧开启“跟随源站”或“智能压缩”功能。有些 CDN 支持边缘压缩(CDN 自己压缩),可减轻源站压力。


六、总结与展望

Gzip 是旧时代的守护神,Brotli 是新世代的进攻者。对开发而言,最佳策略就是两者全开,优先 Brotli,并为静态资源准备 .br 预压缩文件。整套配置成本极低,却能稳定带来 15-30% 的传输缩减,是性价比最高的 Web 性能优化项之一。

未来,Zstandard(zstd)算法已经在 HTTP 内容编码规范中被讨论,它拥有更快的压缩/解压速度和接近 Brotli 的压缩率,可能会成为下一代标准。但现在,做好 Gzip + Brotli 的兜底配合,你的 Web 应用已经站在了网络传输优化的第一梯队。


博主提示:每次更换服务器或更新静态资源后,记得用 curl -I -H "Accept-Encoding: br" https://yoursite.com/main.js 验证是否正确返回 Content-Encoding: br,这是最简单有效的诊断方式。

压缩即正义,让你的字节飞一会儿!

]]>
0 https://www.iarc.top/520.html#comments https://www.iarc.top/feed/group/JavaScript/
五分钟开发ToDoListAPP后端 https://www.iarc.top/499.html https://www.iarc.top/499.html Thu, 14 Aug 2025 21:15:00 +0800 青帝 使用CodeBuddy IDE五分钟内即可完成ToDoList基础后端开发,在这个AI工具发达的时代,我们已不需要将全部的知识装进大脑,只需有一个大的框架,细节交给AI即可快速建立项目。
环境配置:Node.js

将项目需求描述给codebuddy,我这里模型选的是GPT-5-nano,只需稍等几十秒钟,项目将会完全构建
mebdpi7q.png
以下是codebuddy生成的项目(未进行任何修改)
index.js:

const express = require('express');
const app = express();
const port = process.env.PORT || 3000;

// In-memory storage
let todos = [];
let nextId = 1;

function findTodo(id) {
  return todos.find(t => t.id === id);
}

app.use(express.json());

// Get all todos, with optional filtering by completion status
app.get('/todos', (req, res) => {
  const completed = req.query.completed;
  if (completed !== undefined) {
    const isDone = completed === 'true';
    return res.json(todos.filter(t => t.completed === isDone));
  }
  res.json(todos);
});

// Get a single todo by id
app.get('/todos/:id', (req, res) => {
  const id = parseInt(req.params.id, 10);
  const t = todos.find(t => t.id === id);
  if (!t) return res.status(404).json({ error: 'Todo not found' });
  res.json(t);
});

// Create a new todo
app.post('/todos', (req, res) => {
  const { title, description } = req.body;
  if (!title) return res.status(400).json({ error: 'title is required' });

  const todo = {
    id: nextId++,
    title,
    description: description || '',
    completed: false,
    createdAt: new Date().toISOString(),
    updatedAt: new Date().toISOString()
  };
  todos.push(todo);
  res.status(201).json(todo);
});

// Update an existing todo
app.put('/todos/:id', (req, res) => {
  const id = parseInt(req.params.id, 10);
  const t = todos.find(t => t.id === id);
  if (!t) return res.status(404).json({ error: 'Todo not found' });

  const { title, description, completed } = req.body;
  if (title !== undefined) t.title = title;
  if (description !== undefined) t.description = description;
  if (completed !== undefined) t.completed = completed;

  t.updatedAt = new Date().toISOString();
  res.json(t);
});

// Delete a todo
app.delete('/todos/:id', (req, res) => {
  const id = parseInt(req.params.id, 10);
  const idx = todos.findIndex(t => t.id === id);
  if (idx === -1) return res.status(404).json({ error: 'Todo not found' });
  const removed = todos.splice(idx, 1);
  res.json(removed[0]);
});

// Health check (optional)
app.get('/health', (req, res) => {
  res.json({ status: 'ok', todoCount: todos.length });
});

app.listen(port, () => {
  console.log(`Todo backend listening at http://localhost:${port}`);
});

package.json

{
  "name": "todolist-backend",
  "version": "1.0.0",
  "description": "In-memory Todo List backend using Node.js + Express",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "express": "^4.18.2"
  }
}

接下来进行npm安装项目运行所需的库,安装完后直接开始运行看看能不能正常跑起来
mebdyaqa.png

测试阶段:
测试接口:(内存存储,重启丢失数据)

请求方式路径功能
GET/todos获取所有待办,可通过查询参数 completed=true/false 进行筛选
POST/todos创建待办,body 示例 { "title": "示例", "description": "可选" }
GET/todos/:id获取指定待办
PUT/todos/:id更新待办,支持 title、description、completed
DELETE/todos/:id删除待办
GET/health健康检查

获取所有待办:

mebe8wrx.png
目前初始化成功但还没有添加数据

创建待办

由于我没有进行前端的编写,这里直接在浏览器控制台模拟前端js发送请求完成接下来的测试,js代码如下:

fetch("/todos", {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ "title": "待办名字", "description": "待办描述" })
})

mebebqwl.png
已成功创建两个待办事项,重新get请求todos可查看已成功添加
mebed9yl.png

通过id获取指定待办信息

mebeeegt.png
mebeet8z.png

更新已有待办事项内容

mebehhgu.png
成功更新
mebehygl.png

删除待办事项

mebejchw.png
mebejr8h.png

健康检测

mebekpzb.png

注意事项:
该版本的待办事项数据仅保存在内存,重启后将全部丢失,仅适合开发/测试阶段。不过接下来可以让codebuddy优化成使用json文件存储或者使用数据库(SQLite、PostgreSQL、MongoDB 等)存储数据,交给各位去继续探索了。

评论区留言“CodeBuddy”抽5位送永久体验码!
CodeBuddyIDE官网:https://www.codebuddy.ai/
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=6g36nynyzup

]]>
0 https://www.iarc.top/499.html#comments https://www.iarc.top/feed/group/JavaScript/
萤火虫氛围效果(纯CSS) https://www.iarc.top/376.html https://www.iarc.top/376.html Thu, 15 Feb 2024 00:21:00 +0800 青帝

效果图:

360截图20240215001000165.jpg

纯CSS实现,效果可见本页面从下往上飘得一闪一闪的特效,未引入除CSS代码外任何文件。

代码如下

{hide}

<link rel="stylesheet" href="https://www.iarc.top/css/firefly.css" />
<style>.circle-container {position: fixed;top: 0;left: 0;z-index: 1}</style>
<script>
var firefly = "";
for (var i = 1; i <= 100; i++) {
    firefly = '<div class="circle-container"><div class="circle"></div></div>';
    document.writeln(firefly);
}
</script>

{/hide}

可添加至任何HTML网页,CSS文件建议本地化一下,以免链接失效。
]]>
40 https://www.iarc.top/376.html#comments https://www.iarc.top/feed/group/JavaScript/
在手机端不加载JS文件并根据id删除元素的JS代码 https://www.iarc.top/268.html https://www.iarc.top/268.html Mon, 03 Jul 2023 21:54:11 +0800 青帝 实现代码

续接上篇JS特效,因为那个鼠标背景JS特效啊,他在手机上的效果比较差还吃手机性能会使得网页变卡,所以下面这段JS代码就来了
if (!(/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent))) {
  var script = document.createElement("script");
  script.src = "https://www.iarc.top/CDN/js/sbxg.js?v1";
  document.head.appendChild(script);
} else {
  var canvas = document.getElementById("sbcanvas");
  if (canvas) {
    canvas.parentNode.removeChild(canvas);
  }
}

这样,如果当前设备不是移动设备,则加载js文件;否则,如果sbcanvas元素存在,则从DOM中移除它,这样就直接把它删的彻彻底底不占用手机性能了,而PC端则正常运作。

]]>
0 https://www.iarc.top/268.html#comments https://www.iarc.top/feed/group/JavaScript/
为自己博客or网页加上鼠标流光背景JS特效 https://www.iarc.top/264.html https://www.iarc.top/264.html Sun, 02 Jul 2023 16:06:00 +0800 青帝 鼠标特效

鼠标流光背景特效(乱起的名别太在意 :@(献花) ),canvas画布配合JS即可实现,这个版本是我从一个人单页里面抄下来的,顺便优化了一下后将其加入到了本站夜间模式

{card-default label="快速实现" width=""}

<canvas id="sbcanvas" class="sbcanvas"></canvas>
<script src="https://www.iarc.top/CDN/js/sbxg.js"></script>
<style>
.sbcanvas{
    display: block;
   position: fixed;
   top: 0;
   z-index: -9;
}
</style>

{/card-default}

将特效设为博客夜间模式

1.先在body写入

<canvas id="sbcanvas" class="sbcanvas"></canvas>
<script src="https://www.iarc.top/CDN/js/sbxg.js"></script>

2.更改css属性display为none(日间模式不显示该元素)

.sbcanvas{
    display: none;
   position: fixed;
   top: 0;
   z-index: -9;
}
</style>

3.在joe.mode.css文件夹最下面加入以下代码

html[data-night='night'] .sbcanvas{display:block;}

完成以上操作即可大功告成,快去开启夜间模式试一下吧

]]>
0 https://www.iarc.top/264.html#comments https://www.iarc.top/feed/group/JavaScript/
简单的Joe主题自动切换日夜间模式JS代码 https://www.iarc.top/262.html https://www.iarc.top/262.html Sun, 02 Jul 2023 15:31:00 +0800 青帝 由于我最近给夜间模式美化了很多特效 :@(高兴) arcyejian.gif希望更多的人能够在晚上看到这些,故自己基于Joe的夜间模式按钮写了一个自动根据时间判断进入日/夜间模式的代码
为了实现的效果:每天6~20点默认主题为?日间模式,20~6点为?夜间模式

最终版JS代码

document.addEventListener("DOMContentLoaded", function () {
  var now = new Date();
  var hour = now.getHours();
  if (hour >= 20 || hour < 6) {
    $(".joe_action_item.mode .icon-1").addClass("active");
    $(".joe_action_item.mode .icon-2").removeClass("active");
    $("html").attr("data-night", "night");
    localStorage.setItem("data-night", "night");
  } else {
    $(".joe_action_item.mode .icon-1").removeClass("active");
    $(".joe_action_item.mode .icon-2").addClass("active");
    $("html").removeAttr("data-night");
    localStorage.removeItem("data-night");
  }
});

{card-default label="? 原理:" width=""}
创建一个事件监听函数,它会在网页的DOM内容加载完成后执行。具体来说,它会获取当前时间,并根据时间判断是否处于夜间模式。

如果当前时间在晚上8点到早上6点之间(包括8点但不包括6点),就会执行if语句块内的代码。if语句这部分代码是我根据右边的日/夜间模式切换按钮扒出来的
{/card-default}

]]>
0 https://www.iarc.top/262.html#comments https://www.iarc.top/feed/group/JavaScript/
script标签中的defer和async可提高网页加载速度 https://www.iarc.top/214.html https://www.iarc.top/214.html Wed, 07 Jun 2023 23:59:00 +0800 青帝 HTML展示
运行顺序

普通script:

1.文档解析的过程中,如果遇到script脚本, 停止页面的解析渲染, 下载script脚本。
2.如果是多个script脚本, 近似于同时并行下载script脚本。(虽然说是遇到script脚本, 就停止后面标签的解析渲染; 但chrome做了优化, 遇到script脚本, 会快速的查看后边有没有需要下载其他资源的, 一起并行下载, 为了节省一部分下载的时间。 )
3.不论script脚本哪个先下载好, 都按照html中的先后顺序依此执行。 即如果后面的script脚本先下载好, 要等前面的script脚本下载好并执行后, 才能执行。
4.执行script脚本时, 也是停止页面的解析渲染。
5.执行完script脚本, 继续页面的解析渲染。
6.执行完script脚本和页面解析渲染完, 才会依此触发DOMContentLoaded, loaded事件

总结:

  1. 普通script的 下载和执行 都阻塞页面的解析渲染。
  2. 多个script的下载是并行, 但按照页面中顺序依此执行。
  3. 考虑到不支持defer和async的老浏览器, 最佳实践是script放在body底部, 避免阻塞页面的解析渲染。
  4. 执行完script脚本, 继续页面的解析渲染。页面解析渲染完, 才会触发DOMContentLoaded。所以普通script脚本的下载和执行如果慢, 会延迟DOMContentLoaded事件的触发时间。

no

defer:

  • 文档解析时,遇到设置了defer的script脚本,就会在后台进行下载,下载并不会阻止文档的解析渲染。
  • 如果是多个设置了defer的script脚本, 近似于同时并行下载defer脚本。
  • 当页面解析渲染完毕后, 会等到所有的defer脚本下载完毕并按照顺序执行,执行完毕后会触发DOMContentLoaded事件。
  • 如果defer脚本下载较快, 会等到页面解析渲染完毕后, 才按照顺序执行defer脚本。执行完毕后会触发DOMContentLoaded事件。
  • 如果defer脚本下载较慢, 在下载完前, 页面解析渲染已完毕; 等defer脚本下载完后, 才按照顺序执行defer脚本。执行完毕后会触发DOMContentLoaded事件。

总结:

  1. defer脚本的 下载和执行 都不会阻塞页面的解析渲染。因为等到页面的解析渲染完毕后, defer脚本才执行, 所以defer脚本执行 也不会阻塞页面的解析渲染。
  2. 多个defer脚本的下载是并行, 但按照顺序依此执行。
  3. 等页面的解析渲染完毕后, 触发DOMContentLoaded事件前, defer脚本才依次执行。 所以defer脚本的下载和执行如果慢, 会延迟DOMContentLoaded事件的触发时间。
  4. 考虑有的浏览器不支持 defer场景, 多个defer脚本不一定会按照顺序执行, 最佳实践是只使用一个defer脚本。

推荐场景:

如果你的脚本代码依赖于页面中的DOM元素(文档是否解析完毕),或者被其他脚本文件依赖。

例:
  1. 评论框
  2. 代码语法高亮
  3. polyfill.js

defer

async:

  • 文档解析时,遇到设置了async的script脚本,就会在后台进行下载,下载并不会阻止文档的解析渲染。
  • 如果是多个设置了async的script脚本, 近似于同时并行下载async脚本。
  • async脚本的执行会阻止文档的解析渲染。
  • 哪个async脚本先下载完, 就立刻执行, 执行时阻止文档的解析渲染。async脚本执行顺序不按照页面中的脚本先后顺序。
  • async脚本的下载和执行不计入DOMContentLoaded事件统计。
  • 因async脚本下载不阻塞文档的解析渲染; 如果async脚本下载较快, 趁async脚本下载很短时间内, 文档的解析渲染未完成, async下载后立即执行, 执行时会阻塞文档的解析渲染; 执行后, 继续文档的解析渲染, 等页面的解析渲染完毕后, 触发DOMContentLoaded事件。这种场景, async脚本的执行如果慢, 会延迟DOMContentLoaded事件的触发时间。
  • 如果async脚本下载较慢, 当async还在下载时, 文档的解析渲染已完成, 这时不会等待async的下载, 会直接触发DOMContentLoaded事件。这种场景, async脚本的下载和执行不会延迟DOMContentLoaded事件的触发时间。

总结:

  1. async脚本的 下载 不会阻塞页面的解析渲染。async脚本的 执行 会阻塞页面的解析渲染。

    1. 多个async脚本的下载是并行, 但执行不按照页面中的脚本先后顺序。哪个async脚本先下载完, 哪个async脚本就先立刻执行。
  2. async脚本的下载和执行不计入DOMContentLoaded事件统计。
  3. async脚本的执行有可能在 DOMContentLoaded 事件前, 也有可能在 DOMContentLoaded 事件后。
  4. 当async脚本的执行在 DOMContentLoaded 事件前时, async脚本的执行时间才会影响DOMContentLoaded事件的触发时间。又因为脚本的执行时间一般都比较短, 所以可以认为async脚本基本不影响DOMContentLoaded事件的触发时间。

    推荐场景:

如果你的脚本并不关心页面中的DOM元素(文档是否解析完毕),并且也不会产生其他脚本需要的数据。

例:
  1. 百度统计和Google Analytics
    3f378e5efb315765e2a1adbbe232b85f.png
    3e99a2e3b77a2c56ce2f3db64a79c08f.png

普通script, defer, async同时存在页面中:

  1. 普通script执行完, 继续页面解析渲染; 页面解析渲染完, 才触发DOMContentLoaded事件。
  2. defer脚本是在页面解析渲染完, DOMContentLoaded事件的触发前, 才执行defer脚本。
由于1,2这两点, 所以一定先执行普通script, 再执行defer脚本。
  1. async脚本的下载和执行不计入DOMContentLoaded事件统计。
  2. async脚本下载完, 就立刻执行, 且多个async脚本执行不按照页面中的脚本先后顺序。
由于4,5这两点, 所以async脚本执行与普通script, defer脚本无关, 那个时间点都有可能执行。

ps:
defer,async只对外联script脚本文件有效, 内联script脚本设置无效。

]]>
0 https://www.iarc.top/214.html#comments https://www.iarc.top/feed/group/JavaScript/
动态引入JS文件方法和一个网页狂欢代码 https://www.iarc.top/203.html https://www.iarc.top/203.html Sun, 04 Jun 2023 19:15:00 +0800 青帝 {gird column="2" gap="3"}
{gird-item}

{/gird-item}
{gird-item}

狂欢插件

效果:

使用方法:

在网页头部引入firer.js
{/gird-item}

{/gird}

<script src="https://iarc.top/tool/firer.js"></script>

或者新建一个浏览器书签,地址填下面这个:

javascript:void(function(){var d = document,a = 'setAttribute',s = d.createElement('script');s[a]('type','text/javascript');s[a]('src','https://iarc.top/tool/firer.js');d.head.appendChild(s);})();

动态引入JS文件代码:

用户未点击按钮前不引入JS文件,用户点击按钮后引入外部JS文件并执行
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>动态引入JS文件</title>
</head>
<body>
    <button onclick="loadScript()">点击我加载并执行JS</button>

    <script>
        function loadScript() {
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = 'https://iarc.top/tool/firer.js'; // 外部JS文件路径或者链接
            document.head.appendChild(script);

            script.onload = function() { // JS文件加载完成后执行函数
                testFun(); //调用外部JS文件中的函数
            }
        }
    </script>
</body>
</html>
  • 在 body 标签中添加一个点击按钮触发事件并执行 loadScript() 函数。该函数通过创建一个 script 元素,并设置其 src 属性为外部JS文件的路径,在页面中动态加载了外部JS文件。
  • 同时,使用 onload 事件监听文件加载完毕后执行的操作,这里将调用外部JS文件中的函数(例子中为 testFun())。
]]>
0 https://www.iarc.top/203.html#comments https://www.iarc.top/feed/group/JavaScript/
为typecho joe添加评论区语录 https://www.iarc.top/179.html https://www.iarc.top/179.html Sun, 14 May 2023 14:58:00 +0800 青帝

前言

博客之前经常有人回复一些无意义的内容,导致很多垃圾评论

所以我在想既然很多游客喜欢回复一些垃圾评论,不如我直接设置一个随机一言,让他们省去了垃圾评论的打字时间,同时又能让我的评论区少一些无意义的评论

而且那些真正认真回复的人只需要一键删除即可,也不会很影响评论体验,所以就给自己的评论框添加了随机一言

效果展示

先来一波效果展示

本教程仅以Joe主题为例,其他主题可自行发挥能力,如有技术问题,博主可提供简单的指导

教程开始

一、添加后台控制

Joe/functions.php内添加以下代码

// 评论框随机语录功能
$Comment_Citation = new Typecho_Widget_Helper_Form_Element_Select(
    'Comment_Citation',
    array('off' => '关闭(默认)', 'on' => '开启'),
    'off',
    '是否开启评论框随机语录功能',
    '介绍:开启后,评论框自动随机填充随机语录'
);
$Comment_Citation->setAttribute('class', 'joe_content joe_other'); 
$form->addInput($Comment_Citation->multiMode());

//评论框随机语录链接/文字 
$Comment_Citation__text = new Typecho_Widget_Helper_Form_Element_Textarea(
    'Comment_Citation__text',
    NULL,
    "https://api.vvhan.com/api/ian",
    '评论框随机语录',
    '介绍:用于修改评论框随机语录(可以为api地址) <br />
     格式:一行一个,可以为api地址,也可为文字,可以填写多个API地址<br />
     注意:必须填写JSON格式的API,API需要开启跨域权限才能调取,否则会调取失败!<br />
     如果为api地址可在前台按钮刷新内容,如果为文字只能刷新页面来刷新内容(建议使用api地址)<br />
     推荐API:https://api.vvhan.com/api/ian'
);
$Comment_Citation__text->setAttribute('class', 'joe_content joe_other');
$form->addInput($Comment_Citation__text);

二、添加刷新按钮(可省略)

Joe/public/comment.php 添加以下代码,不添加则不设置刷新按钮

三、添加内容获取

1、添加后端获取

Joe/core/function.php 添加以下代码

2、添加前端获取

Joe/public/config.php 添加以下代码

四、添加核心代码

{hide}

Joe/assets/js/joe.global.min.js 添加以下代码

if ($(".Comment_Citation").length) {function e() {let e = Joe.CITATION,t = /(https?:\/\/[^\s]+)/g;t.test(e)? $.ajax({url: e,dataType: "text",success: (e) => $(".joe_comment__respond-form .body textarea").val(e),}) : $(".joe_comment__respond-form .body textarea").val(e);}e(),$(".Comment_Citation").click(function () { e(); });}

{/hide}

五、添加刷新按钮样式(可省略)

这是刷新按钮样式,如果前面没添加刷新按钮,可跳过此步骤

Joe/assets/css/joe.global.min.css添加以下代码

.joe_owo__contain {
      position: static;
      .box { 
        position: absolute;
        bottom: 100%;
        margin-bottom: 6px;
        left: 0px;
        padding-top: 5px;
        border: 1px solid rgba(0, 0, 0, 0.15);
        border-color: transparent;
        box-shadow: 0 0 10px 8px rgb(116 116 116 / 8%);
      }
    }
.comment_box {
      cursor: pointer;
      text-align: center;
      color: var(--routine);
      height: 26px;
      line-height: 26px;
      background: var(--background);
      opacity: 0.85;
      border-radius: 13px;
      width: 70px;
      margin-left: 5px;
      &:hover {
        background: var(--theme);
        color: #fff;
      }}

结语

教程稍有点复杂,但其实是沿用侧栏随机一言的方法,所以如果你能看懂核心js的话,可以仅修改 第四步 中ajax的 url 来实现,那样会简单很多很多

]]>
19 https://www.iarc.top/179.html#comments https://www.iarc.top/feed/group/JavaScript/
「公益」MetingApi接口(可解网易云音乐黑胶歌曲) https://www.iarc.top/149.html https://www.iarc.top/149.html Sun, 05 Feb 2023 21:12:00 +0800 青帝 我们都是苦旅人,因为一点善念、一丝感动、一处荫蔽走在山水间,也曾发宏愿把世界走遍,却止步于尘烟。
2023年应是改变的一年,势必遇见新的自己!
给各位拜个晚年,元宵节快乐!

Github开源地址:https://github.com/metowolf/Meting
Meting自带的接口目前无法解析网易云黑胶音乐了(只能放40秒),所以圆弧免费为广大站长提供一个能解析网易云黑胶和QQ音乐VIP歌曲的MetingApi接口:https://v.iarc.top/

在Meting.js文件里第40行左右的API替换成上面的即可

再附上一个第三方接口:https://api.mizore.cn/meting/api.php
第个直接请求会403,并非接口失效,带上参数请求即可,例:https://api.mizore.cn/meting/api.php?server=netease&type=playlist&id=7783760543&r=:r
参数 默认 描述
id require 歌曲 ID / 播放列表 ID / 专辑 ID / 搜索关键字
server require 音乐平台: netease, tencent, kugou, xiami, baidu
type require song, playlist, album, search, artist
auto options 音乐链接,支持: netease, tencent, xiami
fixed false 固定模式
mini false 迷你模式
autoplay false 自动播放
theme #2980b9 主题色
loop all 播放器循环播放,值: 'all', 'one', 'none'
order list 播放顺序: 'list', 'random'
preload auto 预加载值: 'none', 'metadata', 'auto'
volume 0.7 默认音量,注意播放器会记住用户设置,用户自己设置音量后默认音量将不起作用
mutex true 防止同时播放,当这个播放开始时暂停其他播放
lrc-type 0 歌词类型
list-folded false 指示列表是否应该首先折叠
list-max-height 340px 列出最大高度
storage-name metingjs 存储播放器设置的 localStorage 键

{abtn icon="fa-bandcamp" color="#ff6800" href="https://www.iarc.top/57.html" radius="17.5px" content="Meting使用方法"/}

该解析接口的网易云黑胶不会到期。

绿钻到期了,QQ音乐只能解析非会员音乐了。
music.jpg

]]>
8 https://www.iarc.top/149.html#comments https://www.iarc.top/feed/group/JavaScript/