作者: ianzhi

  • WordPress生成缩略图优化

    WordPress默认情况下会给上传的每一张图片都生成几个不同大小的缩略图,一般情况下问题不大,但是如果存在短时间上传大量图片的场景,会导致服务器整体卡顿。

    这个问题也很好解决,直接将生成缩略图任务扔进队列慢慢处理就好了,毕竟加载/使用缩略图使用也不是很着急的事情,不必在上传完的时候就直接生成出来。

    考虑实现一个插件,上传图片成功后将缩略图生成任务扔进任务队列,然后由队列来逐步执行。唯一的问题是WordPress原生是没有任务队列集成的,不过官方也提供了一个任务队列插件Action Scheduler,那这件事情就简单了。

    1. 安装Action Scheduler

    2. 关闭上传过程中的缩略图生成

    翻了翻WordPress的文档,可以通过`intermediate_image_sizes_advanced`这个钩子来实现,直接返回一个空数组,上传时就不会生成缩略图了。

    // 禁用默认的缩略图生成
    add_filter( 'intermediate_image_sizes_advanced', function () {
        return [];
    } );

    3. 上传成功后,将缩略图生成任务放进任务队列。

    // 添加上传后的钩子,将生成缩略图任务加入到Action Scheduler队列中
    add_action('add_attachment', function ($attachment_id) {
        as_schedule_single_action(
            time(),
            'generate_thumbnails_for_attachment',
            [
                'attachment_id' => $attachment_id
            ],
            'ianzhi-thumbnail-optimise'
        );
    });

    4. 缩略图生成任务钩子。

    // 辅助函数:获取指定尺寸的具体设置
    function image_get_size($attachment_id, $size) {
        global $_wp_additional_image_sizes;
    
        $width = get_option("{$size}_size_w");
        $height = get_option("{$size}_size_h");
        $crop = (bool) get_option("{$size}_crop");
    
        if (isset($_wp_additional_image_sizes[$size])) {
            $width = $_wp_additional_image_sizes[$size]['width'];
            $height = $_wp_additional_image_sizes[$size]['height'];
            $crop = $_wp_additional_image_sizes[$size]['crop'];
        }
    
        return array(
            'width' => $width,
            'height' => $height,
            'crop' => $crop
        );
    }
    
    // 定义缩略图生成任务
    add_action('generate_thumbnails_for_attachment', function ($attachment_id) {
        // 获取附件元数据
        $metadata = wp_get_attachment_metadata($attachment_id);
        if (!$metadata) return;
    
        require_once(ABSPATH . 'wp-admin/includes/image.php');
    
        // 获取WordPress中所有已注册的图像尺寸
        $sizes = get_intermediate_image_sizes();
    
        foreach ($sizes as $size) {
            // 获取每个尺寸的具体设置(宽度、高度、裁剪)
            $size_array = image_get_size($attachment_id, $size);
            if (!$size_array) continue; // 如果获取失败,跳过这个尺寸
    
            // 生成对应尺寸的缩略图
            $resized = image_make_intermediate_size(
                get_attached_file($attachment_id),
                $size_array['width'],
                $size_array['height'],
                $size_array['crop']
            );
    
            if ($resized) {
                // 将新生成的缩略图信息添加到元数据中
                $metadata['sizes'][$size] = $resized;
            }
        }
    
        // 更新附件的元数据
        wp_update_attachment_metadata($attachment_id, $metadata);
    }, 10, 1);

  • 创建strapi插件

    需要开发一个插件来实现一些自定义功能,官方文档写的实在是难以理解了。

    1. 创建基础的目录结构

    # 作为项目根目录
    mkdir xxx
    
    # 进入项目目录
    cd xxx
    
    # 创建strapi 项目
    npx create-strapi@latest strapi
    
    # 创建插件
    npx @strapi/sdk-plugin init strapi-plugin


    2. 配置工作区

    # xxx目录中添加workspace配置
    {
        "workspaces": [
            "strapi",
            "strapi-plugin"
        ],
        "dependencies": [
            "strapi-plugin": "workspace:*"
        ]
    }


    3. strapi目录引入依赖

    {
        ...
        "dependencies": {
            ...
            "strapi-plugin": "0.0.0"
        }
    }



    4. 插件目录监听文件修改

    # 根目录执行
    npm run watch --workspace=strapi-plugin


    5. 运行strapi

    npm run develop --workspace=strapi
  • WordPress添加关键词和描述标签

    关键词和描述标签作为SEO的基础配置,在wordpress中没有默认添加,这里记录一下在Wordpress中自动添加关键词和描述标签的方法。

    (更多…)
  • Google Chrome扩展开发

    Chrome扩展开发者控制台

    1. 需要支付一次性的5美元
    2. 需要使用非国内卡

    参考:

    1. Chrome开发者网站
  • Go语言获取指定年份生肖

    根据给定年份,返回生肖字符串,公元前使用负值即可。(比如2022年,调用使用GetShengXiao(2022),公元前21年,调用使用GetShengXiao(-21))。

    (更多…)
  • 使用SSH转发服务器端口到本地

    注意远程地址、远程端口号、本地地址、本地端口号需要按照实际情况修改。

    (更多…)
  • Electron中数据持久化的选择

    Electron是一个基于Chromium的桌面应用程序框架,它可以让开发人员在不需要熟练掌握Web开发技术的情况下,快速地开发出高质量的桌面应用程序。在Electron中,开发人员可以使用各种各样的数据存储方式,包括文件系统、数据库等。其中,数据库是一种非常常见的数据存储方式,它可以方便地存储和管理各种数据,包括文本、图片、音频、视频等。

    (更多…)
  • Shell遍历文件夹下所有文件,并将文件内容写入一个文件中

    软件著作权要求提供代码文档,这里提供使用Shell遍历文件夹下所有文件,并将文件内容写入一个文件中的方法。

    (更多…)
  • PostgreSQL常用SQL语句

    PostgreSQL与MySQL语法有一些细微差异,记录一下PostgreSQL常用的SQL语句。

    (更多…)
  • 使用微信小程序来实现扫码登录网站

    微信小程序本身提供了openid等信息的无感知获取,基于此来实现微信扫码登录,主要包含以下几个步骤:

    (更多…)
  • MySQL常用SQL语句

    记录一些常用的MySQL语句,方便查找翻阅。

    (更多…)
  • MySQL8 GTID双主配置

    记录一下MySQL8中配置GTID双主的方式。

    (更多…)
  • Linux有线未托管问题

    今天发现在用的一个Linux开发机一直不能自动连接有线网络,显示“有线未托管”,查找测试了很多文章的解决方案都无法使用,可能更新后有了一些变化或者各自情况不同,这里记录一下个人生效的处理方式。

    sudo vim /etc/netplan/00-installer-config.yaml
    
    #文件中添加
    renderer: NetworkManager
    
    sudo netplan generate
    sudo netplan apply
    sudo reboot
  • PHP内置服务器与Serverless

    PHP从5.4版本开始就提供了一个内置的WEB服务器,可以通过一个简单的命令`php -S`启动一个WEB服务器,极大简化了开发环境的搭建。

    到目前为止,官网文档对于内置服务器的使用依然建议用于开发环境,不建议用于生产环境,原因倒是很容易理解,主要有两个方面:

    1. 支持的MIME类型很少,5.4版本放出时只支持.htm和.svg(从5.5版本完善了大部分常见的MIME类型支持)

    2. 仅实现了基本功能,基本没有任何优化,是一个单线程进程(不过从7.4版本开始,内置服务器支持多进程的运行方式)

    从传统开发角度看,这样性能和功能的服务器确实很难应用于生产环境,但是伴随着Serverless的发展,感觉内置服务器的限制突然不是那么重要了。

    使用Serverless服务,不管是AWS Lambda,Google Function,还是国内阿里云的函数计算、腾讯云的云函数,我们关注的点不再聚焦于单机性能释放,而是变成了以下四个方面,我们要做的本质上变成了降低单请求的资源占用和执行时间

    1. 调用次数

    2. CPU时间

    3. 内存占用

    4. 执行时间

    5. 带宽

    我们可以逐个对比以下,

    1. 调用次数显然很难因为WEB服务器的变化有什么变化

    2. CPU时间上,内置服务器作为一个单进程应用,同样的逻辑在函数计算这样的环境下,较少了Nginx与FPM交互的网络开销、Nginx的运行开销,理论上内置服务器应该表现更好

    3. 内存占用方面,内置服务器不再需要运行Nginx,同样逻辑,应该也比传统部署方式占用更少一些

    4. 执行时间,Nginx+FPM需要启动两个进程,需要两个进程间的通信,很难与直接启动PHP进程更快

    5. 带宽基本不用对比,应该不会有什么变化,gzip完全可以在CDN层来实现

    从Serverless的角度看,内置服务器并不算是一个很差的选择,对比传统的运行方式可能更加合适一些,就是不太清楚不建议生产环境使用是否有除性能外的其他原因,回头去翻一翻PHP的issue。

    参考文章

    1. PHP-Built-in web server(https://www.php.net/manual/en/features.commandline.webserver.php

  • Linux服务器Swap配置

    简单记录文件形式的Swap使用与配置方式。

    1. 交换文件大小配置原则

    1. 内存<2G,配置实际内存的两倍
    2. 内存>2G,配置为4G即可
    3. 内存>4G,追求极致性能,不需要配置交换

    2. 创建交换文件

    # 创建一个名称为swap的文件,大小为1GB
    # if 输入文件名称,此处使用/dev/zero即可
    # of 输出文件名称,使用期望的文件名即可
    # bs 同时设置读入/输出的块大小为多少个字节
    # count 拷贝多少个块,块大小等于bs指定的字节数
    dd if=/dev/zero of=/swap bs=1M count=1024
    
    # 配置交换文件权限
    chmod 0600 /swap
    
    # 将文件设置为交换文件
    mkswap /swap
    
    # 启用指定交换文件
    swapon /swap
    
    # 查看交换文件状态
    swapon -s
    
    # 添加交换文件自动挂载
    echo "/swap swap swap defaults 0 0" >> /etc/fstab

    3. 删除交换文件

    # 关闭指定交换文件
    swapoff /swap
    
    # 删除文件
    rm /swap
    
    # 删除自动挂载配置
    vi /etc/fstab
  • 在WordPress中给没有封面图的文章增加默认缩略图

    
    /**
     * 增加默认的文章特色图
     */
    add_filter( 'post_thumbnail_html', 'my_post_thumbnail_html' );
    function my_post_thumbnail_html( $html ) {
        if ( empty( $html ) ) {
            $default_images = [
                get_theme_root_uri() . '/twentytwentythree/assets/images/default-featured-image-1.jpg',
                get_theme_root_uri() . '/twentytwentythree/assets/images/default-featured-image-2.jpg',
                get_theme_root_uri() . '/twentytwentythree/assets/images/default-featured-image-3.jpg'
            ];
            $index = mt_rand(0, count($default_images) - 1);
            $html = "<img src="{$default_images[$index]}"/>";
        }
        return $html;
    }

  • Linux服务器的安全相关配置

    记录一下Linux服务器一般常用的安全相关配置,避免被简单的黑掉,更复杂的配置暂不考虑深入研究了。

    (更多…)
  • PHP文件上传$_FILES无内容

    一般是以下两个参数的配置问题。

    upload_max_filesize='100M'
    post_max_size='100M'

  • 网页、APP跳转应用商店

    安卓

    1. 跳转到应用页面:market://details?id=
    2. 跳转到搜索:market://search?q=

    IOS

    1. 应用页面:itms-apps://itunes.apple.com/app/id 114211089
  • 1.0.5

    1. fix: 数据表格使用筛选后分页显示错
    2. chore: 更新Windows应用图标
    3. chore: 代码分割,优化首屏加载速度