分类目录归档:技术

如何在阿里云上申请免费的 SSL 证书

如何在阿里云上申请免费的 SSL 证书

在进行网站建设的时候, SSL 证书是一个可以有效的提升网络数据传输过程安全性的手段。而一般来说,大家可以选择直接购买 SSL 证书或使用 Let’s Encrypt 提供的免费证书。但 Let’s Encrypt 的证书问题在于往往是短期证书(比如三个月),如果要使用在 CDN 上,就会需要经常替换,非常的麻烦。

目前各家云厂商大多都提供了免费的 SSL 证书,方便大家使用,不过有些时候入口比较深,所以大部分人找不到,只能购买付费的证书。写这篇文章就是希望帮助那些希望使用云服务厂商免费证书的同学快速找到入口。

操作步骤

1. 进入阿里云控制台

打开 console.aliyun.com 了,登录进入阿里云控制台。

2. 进入「SSL 证书(应用安全)」页面

在阿里云控制台找到 SSL 证书(应用安全)这个产品,点击进入产品控制台页面。

3. 点击控制台左侧的 「SSL 证书页面」,进入到 SSL 证书页面

4. 在 SSL 证书页面点击上方 Tab,进入到免费证书 Tab

5. 点击「创建证书」按钮,创建新的空白证书

6. 点击操作栏中的「证书申请」,申请证书

这部分需要注意的是:

  1. 证书绑定域名:阿里云免费证书只支持单个域名。不支持多域名和泛域名。
  2. 域名验证方式:如果你的域名使用了阿里云提供的 DNS 服务,就可以使用自动 DNS 验证方式。如果不是用阿里云的 DNS,就需要手动配置 TXT 记录来进行验证。
  3. 联系人:填写具体的信息,如果证书申请过程中有疑问,会联系这个电话。
  4. CSR 生成方式:你可以自己创建 CSR,也可以让系统生成。如果不是特别关注,使用系统生成就行。

7. 下载证书

当你配置完成后,稍等片刻,证书就会生成成功,此时点击操作栏的「下载」即可下载到证书文件,你根据自己的实际情况,下载对应格式的证书即可。

总结

虽然阿里云的免费证书一年只有 20 个证书的名额,但对于绝大多数人来说,已经足够,在你需要 CDN 或其他更新不方便的情况下,使用云厂商提供的免费一年证书还是挺好的。

在 Pug 中实现类似 get_sidebar() 全局方法

在 Pug 中实现类似 get_sidebar() 全局方法

在开发 WordPress 主题时,我们会用到一些全局方法,来帮助我们快速加载特定的区域的代码。如果我们在设计和开发主题的时候,也可以实现类似的功能,则在开发对应的页面和应用的时候,我们就可以根据自己的需求来进行特定区域的代码的封装。这样我们在进行后续的开发的时候,就可以简化自己的代码,同时还可以按照 WordPress 的规范提前拆分代码,在实际进行项目开发的时候,提升效率。

原理

本次实现主要是基于 Pug 自带的 Mixins 机制来实现在主题中提供自定义的函数,从而实现我们想要的内容。在原理上,和 WordPress 的 get_sidebar 之类的方法不完全一样。所以,在体验上还没有做到像 WordPress 那么方便。

实现方式

1. 创建 Mixins

在项目的根目录下创建一个 mixins 目录,并在其中创建一个 includes.pug 文件和一个 getHeader.pug 文件。

includes.pug 文件中添加如下代码

include getHeader

getHeader.pug 文件中添加如下代码

mixin getHeader
    p header

2. 引入 includes.pug

在你的 layouts.pug 文件中加入 includes.pug 的引入。需要注意的是,要加在 doctype 之前。

include ../mixins/includes
doctype html
html
  head

3. 在需要的地方调用

当你完成上述的配置后,即可在需要的地方进行调用。

extends layout

block content
  +getHeader
  h1= title
  p hi to #{title}

调用的效果如下:

如果你希望实现更加强大的功能(比如参数),可以参考 Pug 官网的 Mixins 页面。

为 Express 项目添加文件变更自动刷新

为 Express 项目添加文件变更自动刷新

我最近在准备开发新的 WordPress 的主题的工具,为了方便自己开发主题,正在准备一个脚手架,本文是开发过程中的经验总结。

白宦成

在进行主题开发的时候,一个很好的体验是来自于变更能够实时生效。过去我们想要实现这样的功能需要自己手动刷新浏览器。但随着前端技术的进步,我们可以借助诸如 browser-sync 这样的工具来完成自动的刷新,从而实现无需手动刷新,代码修改后自动刷新。此外,除了 browser-sync, 你还可以选择 webpack-dev-server

原理分析

此类工具的工作模式是比较简单的,一般而言,会要求你设定一个代理的端口,他会将对应端口的请求进行转发,并在其中加入 BrowserSync 的 JS 文件,从而实现可以无需手动操作来刷新。

browser-sync-client.js

而其刷新的能力则是源自于 BrowserSync 本地提供的 WebSocket Server。嵌入的 JS 文件中加入了 WebSocket 的相关链接代码, 从而实现从 Command Line 当中获取刷新指令,前端则在获取到指令后进行刷新。

WebSocket 请求

具体步骤

1. 安装 BrowserSync

首先在项目中引入 browser-sync ,执行如下命令

npm install browser-sync --save-dev

2. 修改启动文件

我是使用 express generator 生成的项目,需要修改 bin/www 文件,如果你是自己建设的项目,则需要自行修改。

在启动文件中找到监听端口的代码, 并在其回调函数中添加如下代码

# 添加前
server.listen(port)
# 添加后
var bs = require('browser-sync').create();
server.listen(port, () => { 
  bs.init({
    open: false,
    ui: false,
    notify: false,
    proxy: 'localhost:' + port,
    files: ['./views/**', './routes/**'],
    port: 8080
  });
});

上述配置中,可以根据你的需要修改 proxy 、files、port 等选项,实现自定义配置。

关于配置的更多信息,你可以参考 https://browsersync.io/docs/options

3. 启动服务,并测试

在命令行中执行 npm start ,在浏览器中打开对应的页面,当可以看到内容后,可以修改文件,等待页面的自动刷新,如果成功刷新了,则表示你已经完成了相关能力的配置。

在开发 Gutenberg 插件时,如何处理防抖?

在开发 Gutenberg 插件时,如何处理防抖?

在开发 Gutenberg 插件时,如果你需要对编辑器的内容进行处理,则需要为其加入防抖措施,避免你的函数被频繁调用。

思路

由于编辑器需要高频处理,因此需要采用防抖策略,避免将多次输入视为不同的事件。这里可以使用 WordPress 提供的 useDebounce 来实现控制。需要注意的是,WordPress 自动的 Debounce 函数传入的参数应当采用 useCallback 来进行包裹。

参考代码

import {subscribe} from "@wordpress/data";
import {useDebounce} from  "@wordpress/compose"
import {useCallback} from "@wordpress/element";

const debounced = useDebounce(
        useCallback(() => {
            // do some thing
        }),500
    );
subscribe(debounced);
针对 WordPress 开发配置 Sublime Text 4

针对 WordPress 开发配置 Sublime Text 4

最近在开发两个自己用的 WordPress 的插件,所以就把 Sublime Text 配置成了适合 WordPress 的开发的状态。以下是我的一些记录。

加入代理

因为 Package Control 在境内访问不是那么的流畅,所以,针对 Package Control 进行相应的 Proxy 配置,你只需要找到相应的配置界面,在其中加入 Proxy 配置即可。

{
  "http_proxy": "http://127.0.0.1:7890",
  "https_proxy": "http://127.0.0.1:7890"
}

代码格式化

Sublime 自带 Reindent

Sublime Text 4 自带缩进格式化的工具,因此,可以不需要安装第三方插件来实现。

在 Sublime Text 4 的 Line — Reindent 当中可以完成相应的操作。

为了更好的使用这个功能,我自己添加了一些配置来简化这个功能的使用:

  1. 安装 Package​Resource​Viewer 用于修改系统配置。
  2. 使用 Package Resource Viewer: Open Resource 命令,打开 Default 包中的 Context.sublime-menu文件,
  3. 在其中添加一行代码 { "command": "reindent","caption":"格式化选中部分" },即可实现在上下文菜单中加入自动的格式化能力。效果见下图

代码辅助编写

Tabnine

由于我使用的是 Sublime Text ,所以 VSCode 才有的 GitHub Copilot 自然是无法使用的,但不代表你不能使用机器来帮助你快速生成代码。这里我选择的是 Tabnine

由于我目前还没有为 Tabnine 付费,所以他只能基于我本地的代码进行学习。

文档快速生成

DoxyDoxygen

虽然是给自己用的插件,还是希望代码写的足够清晰。一个更加简单的插件,可以帮助我更好的去写批注。

使用 Github Action 发布 WordPress 插件

使用 Github Action 发布 WordPress 插件

WordPress 官网的插件系统采用的是 SVN 来进行管理,如果你希望将自己的插件发布至 WordPress 官网,就必须在本地安装 SVN,不太利于项目的管理。此外,WordPress 官网提供的是一个发布系统,而非版本控制系统(只是将 SVN 用作插件管理,并不是真打算让你每一个变更都提交),因此,你还是需要使用另外的版本控制系统(比如 Git)来管理你的代码。

为了简化发布,你可以采用 GitHub Action 来完成你的插件自动发布,这样你就可以使用 Git 来开发和管理你的插件,并让 Github Action 自动进行插件的发布。

具体操作

1. 配置 Action Secrets

因为你需要使用版本控制来进行发布,以及可能存在的协作开发的场景,处于安全的考虑,你应该将你的 SVN 的信息放置在 Action Secrets 当中。

在仓库当中找到 Secrets – Actions ,新建两个 Secrets:SVN_USERNAMESVN_PASSWORD,配置上你的 SVN 账号信息,稍后将会使用你的这个账号信息来进行插件的发布

2. 创建一个 .distignore 文件

.distignore 文件可以帮助你实现忽略不需要发布到 WordPress 插件系统的文件,这样就让你的插件目录变得更加干净一些。在你的仓库根目录创建一个 .distignore 文件,并填写具体要忽略的文件,即可实现部分发布至 WordPress 插件目录。

以下是我的 Example

node_modules/
.github/
.git/
.distignore
.gitignore
package.json
package-lock.json
yarn.lock

3. 创建 Action 文件

在你的项目的 .github/workflows/ 中创建一个 publish.yml文件,并在其中添加如下代码即可。

name: Publish to WordPress Plugin Directory
on:
  push:
    tags:
    - "*"
jobs:
  tag:
    name: New tag
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@master
    - name: Build # 如果没有 NPM 相关构建工作,可以去除这一步。
      run: |
        npm install
        npm run build
    - name: WordPress Plugin Deploy
      uses: 10up/action-wordpress-plugin-deploy@stable
      env:
        SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
        SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
        SLUG: wpstoreapp-spellcheck

4. 发布版本

接下来只需要执行如下操作,既可以发布版本

git add .
git commit -m 'feat: release new version'
git tag 1.0.0
git push && git push origin 1.0.0

上述代码中的 1.0.0 即为具体的版本号,可以根据你的诉求进行修改。

总结

在完成了配置后,后续你的插件发布就变得十分简单了:修改本地的 readme.txt 中的版本号,加入 changelog,并修改插件文件头中的版本,即可提交一个 commit ,添加对应的版本的 tag,然后 Push 到 Github 上,由 Github 来进行插件的发布。

而如果你是以公司/团队的形式来管理插件,也可以用类似的方式,这样虽然每个人都不掌握 SVN 的账号密码,但却可以完成插件的发布,十分方便。

在 WordPress 的插件页面添加更多的连接

在 WordPress 的插件页面添加更多的连接

WordPress 的插件页面提供了不少的 Hooks,可以帮助我们实现自定义的插件页面,让用户在启用插件后,第一时间可以看到我们为其提供的功能,从而降低用户使用的成本。

以上图为例,你可以看到,我在左侧的功能区添加了「配置 Token」和「购买额度」;右侧的更多链接区提供了帮助手册和联系我们,帮助用户优化体验,更快的了解如何使用你的插件。

左侧功能区

首先,在左侧功能,WordPress 提供了两个 Filter来实现这个功能:

一个是 plugin_action_links,这个插件传入两个参数,一个是当前插件的链接构成的数组,另一个则是插件的文件路径,你可以根据传入的参数判断当前是使用哪个插件,并通过返回不同的数组,来实现不同的功能。

另外一个则是 plugin_action_links_wpstore-spellcheck/wpstore-spellcheck.php,是在上一个 filter 的基础之上,加入了插件的路径,从而让你可以无需进行判断,直接针对对应插件来完成链接的修改。

以上图效果为例,具体的代码如下

function wpstoreapp_plugin_action_link($links, $file)
{
	if($file == plugin_basename(dirname(__FILE__) . '/wpstore-spellcheck.php')){
		$links[] = '<a href="./options-writing.php">配置 Token</a>';
		$links[] = '<a href="https://api.wpstore.app/plugins/spell-check/pricing" target="_blank">购买额度</a>';
	}
	return $links;
}

add_filter('plugin_action_links', 'wpstoreapp_plugin_action_link', 10, 2);

这里我选择的是第一种实现方式,主要的原因是我无法保证用户安装插件一定是采用的是 WordPress 插件目录的安装方式,因此,在这种情况下,第二种带了路径的 filter 的名字是有可能发生变化的。

右侧更多链接区

右侧更多链接区可以用来承载联系我们、帮助文档等入口,从而实现用户在使用时,可以快速找到相应的辅助资料,从而获得更好的体验。

从实现的逻辑上来看,和在左侧功能区添加链接的基本逻辑是一样的,需要判断当前插件是否是目标插件,如果是,则可以根据需要添加功能。

add_filter( 'plugin_row_meta', 'wpstoreapp_plugin_row_meta', 10, 2 );

function wpstoreapp_plugin_row_meta( $links, $file ) {
	if ( plugin_basename( __FILE__ ) == $file ) {
		$row_meta = array(
			'docs'    => '<a href="https://www.wpstore.app/?p=291">帮助手册</a>',
			'contact'    => '<a href="mailto:hi@wpstore.app">联系我们</a>'
		);

		return array_merge( $links, $row_meta );
	}
	return (array) $links;
}

总结

WordPress 为我们提供了方便的 Hook,可以让我们可以自定义我们想要的功能,借助这些功能来降低你的用户的 Landing 成本,从而实现更好的服务用户,是一个不错的选择。

如何“抄”一个 WordPress 插件

如何“抄”一个 WordPress 插件

WordPress 作为 CMS 生态的第一产品,PHP 生态的护城河,可以说,只要 WordPress 不死,PHP 就还能继续活下去。而 WordPress 团队也在不断迭代项目。因此,有不少的开发者以 WordPress 开发为生。

而得益于 WordPress 基于 GPL 开发的,所以,理论上,如果你开发的插件是通过 WordPress 官方的目录分发的,你的插件是需要以 GPL 兼容的协议开源的,这也给了想要开发同款插件的开发者们提供了机会。

PHP in WordPress themes must be GPL, artwork and CSS may be but are not required.

Matt Mullenweg, https://wordpress.org/news/2009/07/themes-are-gpl-too/

不过,需要注意的是,只有 PHP 的插件源码才需要以 GPL 兼容协议开源,CSS 和图片文件不需要开源,而随着 Gutenberg 编辑器的不断推广,以后的插件可能不太好“抄”了。

在这篇文章,我们不再讨论 Gutenberg 功能的研究,只谈插件的 PHP 部分。

如何理解 WordPress 的插件开发?

《人人都能学会的 WordPress 课程》当中,我曾经介绍过 WordPress 的插件的运行机制。如果现在用一个更加简单的说法来探讨这个问题的话,WordPress 是通过提供do_actionapply_filter这两个方法,实现了功能的可修改性。而插件则需要 add_actionadd_filter 这个方法来影响 WordPress 的运行表现

当你明白这个问题之后,你就会意识到,如果我们需要解析一个插件的运行机制,来开发自己的同类型插件之时,唯一要做的其实就是找到对应的 Action 和 Filter,修改 WordPress 的运行表现。

因此,你接下来要做的事情就变得简单很多,你需要做的,仅仅是在插件的代码中搜索所有的 add_actionadd_filter,并记录下对应的 action 和 filter 的名字,在 Code Reference 当中搜索对应的 action 的应用场景和用法即可。

Tips

  1. 按照 WordPress 的开发规范,插件的目录中一定有一个和其目录名相同的 PHP 文件,这个文件是 WordPress 插件的入口文件,你只需要从这个插件看起,就能找到你想要了解的实现方式。
  2. WordPress 插件的代码都可以在 WordPress Directory 中找到,你只需要在 Development 目录中,就可以找到对应的插件的源码。
如何从 WordPress 插件目录下架一个插件

如何从 WordPress 插件目录下架一个插件

我在 WordPress 官方上架了不少的插件,但不少的插件如今我已经不再维护了。

再加上现在我开始重新调整 WPStore,因此,决定下架其中一些不再维护的插件,减少 WordPress 官方插件系统中的无用插件。

操作步骤

1. 登陆你的 WordPress.org 的账号,并找到你要下架的插件

比如,我这里希望下架早年为 Payjs 写的付费阅读插件。

2. 点击 右下角的 Advanced View

在 Details 页面找到 Advanced View 的连接,并点击进入 Advanced View 页面。

3. 在 THE DANGER ZONE 中关闭插件

进入 Advanced View 页面之后,向下拖动,在底部的 THE DANGER ZONE 中可以找到 「Close This Plugin」,点击按钮,并在弹出的窗口中,点击确认即可。

4. 删除完成

当你看到如上界面时,就说明你这个插件已经完全关闭了。

总结

其实 WordPress 并没有要求你关闭掉每一个插件,不过从插件的维护角度来看,关闭一个不再维护的插件可以减少你后续的服务的成本,也是一个不错的选择。

WordPress 官方的 Code Reference应该如何使用?

WordPress 官方的 Code Reference应该如何使用?

如果你要开发 WordPress ,必然会用到 WordPress 官方的文档。而在官方文档当中,除了各种 Handbook ,最重要便是 Code Reference

在使用 Code Reference 的时候,也是存在一些技巧的。

搜索你需要的函数、Hooks、Filter、Class

访问 Code Reference 主页,可以看到有一个搜索框,在这里你可以输入你要搜索的关键词,并在下拉框中筛选出你要用的具体的函数/Hooks/Filter/Class

当然,如果你在开发过程中,明确了你要查询的某个特定的函数,也有一个简单的方式来查询,只需要将下方的链接中的 FUNCTIONNAME 替换为你要查询的函数名,就可以直接跳转到对应的函数的详细界面,查看对应的函数的功能。

https://developer.wordpress.org/reference/functions/FUNCTIONNAME/

如果你查询的是 Hooks、Filter 也有类似的方法,WordPress 的单个函数/Hooks/Filter 的URL非常的明确,因此,你可以在写代码的时候,随时把你需要查询的函数直接复制出来,替换浏览器地址栏中的方法名即可。

理解 Code Reference 的内容

download_url 为例,在 Code Reference 当中,大体上会分为以下几个区域

Description
Parameters
Return
Source
Related
 - Uses
 - Used By
Changelog
User Contributed Notes
 - Feedback

Description

这里介绍了这个函数的基本介绍,一些时候,也会在这个区域加入一些使用的 Tips。

不过这个描述并非每一个函数都会有。

Parameters

参数区域说明了这个函数的入参有哪些,你可以对着入参的介绍调用函数,从而避免传入错误的参数

Return

返回值定义了具体的返回值,你可以根据返回值来判断具体的结果。不仅如此,点击里面的链接,可以跳转到对应的类,查看对应返回结果的类型。

Source

Source 部分则给你了函数的具体的代码,对于一些你在开发过程中百思不得其解的函数,读一下这个函数的源码可能会让你茅塞顿开。

对于比较长的函数,点击 Expand 就可以展开看。如果你希望在本地看,左上角也告诉你了这个函数在具体哪个文件可以查看。你可以直接按图索骥,找到本地的对应函数来查看。

Related

Related 当中分为两个区块,分别是 Uses 和 Used By ,分别介绍当前这个函数是基于哪些函数实现的(Uses)和其他哪些函数使用了当前这个函数(Used By)

有了 Uses 和 Used By,你就可以自己封装一个类似的函数,也可以看看其他的函数是如何调用当前这个函数,心中更有数。

Changelog

Changelog 当中记录了这个函数的具体的变更历史,你就可以非常方便的去了解到一个函数的发展历史,可能某个功能你过去用的好好的,最近不能用了,就是因为函数发生了更新。

User Contributed Notes

在 User Contributed Notes 当中,记录了别人对于这个函数使用的反馈,你可以看到其他开发者是如何使用这个函数的。当你在使用这个函数/Hook出现问题时,就可以参考一下其他人贡献的笔记,可能会更好的帮助你来理解这些 Notes。

总结

用好 WordPress 自带的 Code Reference 可以帮助大家更好的开发 WordPress 的各种功能,花点时间了解一下 Code Reference ,相信可以帮到你~

Livewire.js 404 的问题的处理思路和解决方式

Livewire.js 404 的问题的处理思路和解决方式

在使用 Laravel Livewire 的时候一个常见问题是生成的 Livewire.js 文件会报错。

一般来说,解决思路有两种

  1. 看看你生成的 URL 是否是正确的。
  2. 看看你的 Nginx 配置是否是正确的。

生成的 URL 是否正常

在 Livewire 的配置当中,存在一个 asset_url 选项,这个选项会用于在页面中嵌入 Livewire.js 文件的功能,因此。如果你在使用过程中,修改了这个值,导致生成的地址是错误的,就有可能报错。

Nginx 配置是否正确

这个问题往往会导致报错的页面是 Nginx 的 404 页面。

在你的 Nginx 配置当中,如果你针对 JS 文件或 CSS 文件有单独处理,你需要将对应的处理注释掉,确保所有请求转发给 Laravel 进行处理。

 # location ~ .*\.(js|css)?$ {
 #   expires 7d;
 #   access_log off;
 # }
Laravel 9 单元测试报错 An email must have a “From” or a “Sender” header

Laravel 9 单元测试报错 An email must have a “From” or a “Sender” header

在 Laravel 9 当中,引入了新的 Mailer 组件,随之而来的是一些过去没有的 Bug。

如果你在开发过程中出现了 An email must have a "From" or a "Sender" header 的报错,需要在 PHPUnit 当中配置 MAIL_FROM_ADDRESS 属性,用于通过测试。

<env name="MAIL_FROM_ADDRESS" value="from@example.com" />

来源:https://laracasts.com/discuss/channels/laravel/for-reference-an-email-must-have-a-from-or-a-sender-header