1. Mores小栋博客!
    回答:

    原因在于 flex 子元素的 min-width 默认值是 auto:子元素不会收缩到比它内容的最小宽度更窄。一段没有空格的长链接,最小宽度就是它的整个长度,于是 flex: 1 也压不住它。

    给这个子元素加上 min-width: 0 就行:

    CSS
    .main {
      flex: 1;
      min-width: 0;
    }

    然后再按内容决定怎么处理溢出:

    • 长链接、长单词:overflow-wrap: anywhere; 允许在任意位置换行。
    • 表格、代码块:外面包一层 overflow-x: auto 的容器,让它在自己的区域里横向滚动。

    grid 布局里也有同样的现象:1fr 的最小值同样是 auto。把列写成 minmax(0, 1fr) 就能解决。

  2. Mores小栋博客!
    回答:

    反向代理以后,和应用建立连接的是 Nginx,应用看到的来源地址自然是 Nginx 所在的地址。需要 Nginx 把真实 IP 放在请求头里转发给应用:

    Nginx
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    应用这边读取这些请求头。很多框架有专门的设置,比如 Express 的 app.set("trust proxy", 1),设置后 req.ip 就是真实 IP。

    如果 Nginx 前面还有 CDN,$remote_addr 拿到的是 CDN 节点的地址。这时要用 realip 模块,从 CDN 传来的请求头里取出用户 IP:

    Nginx
    set_real_ip_from 10.0.0.0/8;   # 换成 CDN 公布的回源 IP 段
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;

    注意安全:X-Forwarded-For 可以被客户端伪造,只能信任来自你自己的代理或 CDN 的那部分。不要直接拿请求里原始的 X-Forwarded-For 做限流或者风控判断。

  3. Mores小栋博客!
    回答:

    对大多数 Web 项目来说,两个都完全够用,选团队更熟悉的那个就不会错。如果没有明显的偏好,可以参考下面几点。

    PostgreSQL 的优势

    • 功能更丰富:jsonb 和 GIN 索引、数组类型、部分索引、表达式索引、CTE 和窗口函数都很成熟。
    • 对标准 SQL 的支持更严格,数据约束(CHECK、排除约束)更完善。
    • 扩展生态丰富,比如做向量检索的 pgvector、做地理数据的 PostGIS。

    MySQL 的优势

    • 国内的资料、托管服务和运维经验更多,招人也更容易。
    • 大量开源程序(如 WordPress)默认就用 MySQL。
    • 主从复制、读写分离的方案非常成熟。

    建议

    要部署的开源程序只支持 MySQL,那就用 MySQL;新写的业务系统,特别是数据结构比较复杂、需要 JSON 查询或者扩展功能的,可以优先考虑 PostgreSQL。无论选哪个,备份方案和慢查询分析都要从第一天就做好。

  4. Mores小栋博客!
    回答:

    按照“先测量、再优化”的顺序来,避免盲目地装一堆优化插件。

    1. 区分是服务器慢还是页面资源慢。 在浏览器开发者工具的 Network 面板里看第一个 HTML 请求的等待时间(TTFB)。TTFB 很长,说明 PHP 和数据库慢;TTFB 正常但整体加载慢,就是图片、脚本这些资源的问题。
    2. 升级 PHP 版本。 新版本的 PHP 比老版本快很多,先确认主题和插件兼容,再升级到主机支持的较新版本。
    3. 找出慢插件。 安装 Query Monitor,看每个页面执行了哪些数据库查询、各花了多长时间,以及是哪个插件发起的。停用用不到的插件。
    4. 加缓存。 页面缓存(缓存插件或者 Nginx 的 fastcgi_cache)能让大部分访问不再经过 PHP;对象缓存(Redis)可以减少重复的数据库查询。
    5. 处理图片。 上传前压缩,使用 WebP 格式,开启懒加载,大图不要直接用原图。
    6. 清理数据库。 删除多余的文章修订版本和过期的临时数据,检查 wp_options 表里自动加载(autoload)的数据是否过大。

    每改一项都重新测一次,才知道哪一项真正起了作用。

  5. Mores小栋博客!
    回答:

    两种方式都可以:

    1. 在这篇文章下方的评论区留言,写明是哪个下载地址失效了。
    2. 给站长发私信:电脑上点页面右侧工具栏的「客服」,附上文章链接。

    反馈时说明一下具体的提示,比如“链接不存在”“提取码错误”还是“文件已被删除”,可以更快定位问题。补好以后会在原文章里更新下载地址。

  6. Mores小栋博客!
    回答:

    这就是布局偏移(CLS)。只要浏览器在图片下载完成之前就知道它的宽高比,就会提前留出位置。

    最简单的办法是给 img 写上图片的原始宽高,再配合 CSS 让它自适应:

    HTML
    <img src="/uploads/cover.webp" width="1200" height="675" alt="封面">
    
    <style>
      img {
        max-width: 100%;
        height: auto;
      }
    </style>

    现代浏览器会根据 width 和 height 算出宽高比,在图片加载前就按这个比例占好位置。

    宽高不确定,但希望统一显示成固定比例时(比如卡片封面),用 aspect-ratio 配合 object-fit:

    CSS
    .card-cover {
      width: 100%;
      aspect-ratio: 16 / 9;
      object-fit: cover;
    }

    同样的道理也适用于广告位、嵌入的视频和异步加载的模块:先给容器一个确定的高度或比例,内容加载完成后才不会把页面挤开。

  7. Mores小栋博客!
    回答:

    Let's Encrypt 证书的有效期只有几十天,必须让工具自动续期,不要依赖手动操作。

    使用 certbot

    用系统包管理器或 snap 安装的 certbot,一般会自动创建续期的定时任务。确认一下:

    Bash
    systemctl list-timers | grep certbot
    # 模拟续期,检查整个流程能否走通
    certbot renew --dry-run

    证书续期以后,Nginx 需要重新加载才会用上新证书。可以加一个部署钩子:

    Bash
    certbot renew --deploy-hook "systemctl reload nginx"

    使用 acme.sh

    acme.sh 安装时会自动添加每天运行的 cron 任务。安装证书时用 --reloadcmd 指定重新加载命令,之后每次续期都会自动执行。

    再加一道保险

    用监控服务或者一个简单的定时脚本检查证书的剩余天数,少于两周就发提醒。续期失败的常见原因是 80 端口被防火墙拦截、DNS 解析变更,或者 DNS 验证用的 API 密钥失效了。

  8. Mores小栋博客!
    回答:

    差 8 个小时,基本可以确定是 UTC 和北京时间(UTC+8)混用了:某一个环节把北京时间当成 UTC 处理,或者反过来。

    比较稳妥的做法是全链路统一:

    1. 数据库里存 UTC。PostgreSQL 用 timestamptz 类型;MySQL 的 DATETIME 不带时区信息,要约定好存的都是 UTC。
    2. 接口返回带时区的 ISO 8601 字符串,比如 2026-10-20T12:00:00Z 或 2026-10-20T20:00:00+08:00,不要返回 2026-10-20 20:00:00 这种不带时区的格式。
    3. 前端只在显示时按用户所在时区转换。

    在前端格式化时可以明确指定时区:

    JavaScript
    new Date("2026-10-20T12:00:00Z").toLocaleString("zh-CN", {
      timeZone: "Asia/Shanghai",
    });
    // "2026/10/20 20:00:00"

    另外检查一下服务器、Docker 容器和数据库连接各自的时区设置。容器默认是 UTC,同一份代码在本机运行正常、部署后就差 8 小时,多半是这个原因。

  9. Mores小栋博客!
    回答:

    只在从搜索引擎进入时跳转,是很典型的挂马手法,目的是不让站长自己发现。建议按下面的顺序处理:

    1. 先备份现场。 把当前的网站文件和数据库完整打包一份,方便之后分析入侵途径。
    2. 修改所有密码。 网站后台、数据库、FTP、SSH、主机控制面板都要改,并删除不认识的管理员账号。
    3. 找出被篡改的文件。 对比官方原版程序,或者列出最近修改过的文件:find . -name "*.php" -mtime -30。重点检查上传目录、缓存目录里的 PHP 文件,以及 index.php、.htaccess 和主题的 functions.php。
    4. 用干净的源码覆盖。 程序、主题和插件都从官方渠道重新下载覆盖,不要只删除自己发现的那几个恶意文件,后门往往不止一个。
    5. 检查数据库和定时任务。 文章内容里是否被插入了恶意脚本,crontab -l 里有没有陌生的任务。
    6. 堵住入口。 更新程序和所有插件,删除不用的插件和主题,上传目录禁止执行 PHP。

    处理完成以后,在百度搜索资源平台和 Google Search Console 里检查网站的安全状态,必要时申请重新审核。以后定期备份,出了问题可以直接回滚到干净的版本。

  10. Mores小栋博客!
    回答:

    在网址导航页点「申请入驻」,或者直接打开申请入驻页面,按下面的步骤操作:

    1. 填写你的网站地址,点「识别网站」。系统会读取你的网站,自动填好名称、图标和介绍,你可以再修改。
    2. 查看识别结果里列出的检查项,比如网站能否正常访问、首页有没有指向本站的链接。没通过的项目按提示处理后点「重新识别」。
    3. 选择入驻类别,提交后等待审核。

    有检查项没通过也可以直接提交,由管理员决定是否收录。网站内容需要健康合法,长期无法访问的网站会被移出导航。

  11. Mores小栋博客!
    回答:

    核心思路是把所有颜色写成 CSS 变量,深色模式只重新定义这些变量的值,组件样式本身不用改。

    CSS
    :root {
      --bg: #ffffff;
      --text: #1f2328;
      --line: #e5e7eb;
    }
    
    /* 跟随系统:用户没有手动选择浅色时生效 */
    @media (prefers-color-scheme: dark) {
      :root:not([data-theme="light"]) {
        --bg: #17181a;
        --text: #d5d7db;
        --line: #2d2f33;
      }
    }
    
    /* 用户手动选择深色 */
    :root[data-theme="dark"] {
      --bg: #17181a;
      --text: #d5d7db;
      --line: #2d2f33;
    }
    
    body {
      background: var(--bg);
      color: var(--text);
    }

    几个细节:

    • 手动切换时在 html 元素上设置 data-theme,并把选择存进 localStorage。
    • 读取设置的脚本要放在 head 里同步执行,否则刷新页面时会先闪一下浅色。
    • 加上 color-scheme: light dark,滚动条和表单控件也会跟着变成深色。
    • 深色背景不要用纯黑,正文也不要用纯白,对比度太强看久了累眼睛。
    • 图片、代码高亮、图表的配色要单独检查一遍。
  12. Mores小栋博客!
    回答:

    删除文件再提交,只是在最新版本里没有了,历史提交里依然保存着。要从历史中彻底去掉,需要改写历史。

    第一步:先处理泄露的密码

    密码一旦推送到远程,就要当作已经泄露:先去修改密码或者作废密钥,再清理历史。只清理历史是不够的,别人可能早已克隆或者 fork 了仓库。

    第二步:用 git filter-repo 改写历史

    Bash
    # 先单独克隆一份干净的副本来操作
    git clone --mirror git@example.com:me/project.git
    cd project.git
    
    # 从所有历史中删除指定文件
    git filter-repo --path backup.zip --invert-paths
    git filter-repo --path config/database.php --invert-paths
    
    # 改写后强制推送
    git push --force --mirror

    git filter-repo 需要单独安装,它是 Git 官方文档推荐的工具,比旧的 git filter-branch 快得多,也更不容易出错。

    第三步:通知协作者

    历史改写以后,其他人本地的仓库和远程不再一致,需要重新克隆。托管平台上已有的 fork 和缓存可能仍然保留旧数据,必要时联系平台清理。

    以后可以在 .gitignore 里排除压缩包和本地配置文件,敏感配置改用环境变量。