BaaS 碎碎念

暂时没时间写完整,零散记一些吧。

BaaS 的核心其实在于 ACL。

因为 BaaS 把获取数据的机制下发到客户端,所以 BaaS 和传统应用最显著的差距就是在哪里处理数据的可视性问题。传统应用里,哪个用户看到哪个数据是后端处理的。而 BaaS 里,则是前端、后端、ACL 一起确定的,而且通常情况下,ACL 设计的好,前端后端的验证步骤都可以省去。

小程序云不支持后台,无法使用。

在 Pug 模板中使用变量

如何在 Pug 里,把变量注入父模板。

我厂使用 Pug 作为 HTML 的预编译工具,写久了发现回不去了……Pug 写起来很高效,看久了习惯了阅读效率也很高,读了读文档,发现还有很丰富的可编程特性。于是我决定抛弃 Handlebars,以后都用 Pug 写模板了。

这次我厂官网改版,我就用 Pug 替换了 Handlebars,于是 build 脚本一下少了几十行,非常爽。其实我早就想这样做,不过卡在一个点:使用变量。

在 Pug 里可以这样使用变量:

- var name = 'meathill'

h1 hello #{ name }

以上代码将输出 <h1>hello meathill</h1>。这种用法比较简单,不过在 extends模板的时候,把变量放到哪里就不知道了,官方文档也语焉不详,我反复试了很多次无果,最终还是靠搜索找到了答案,原来要这样:

// Layout.pug
html
  block vars
    p 注意,这个 block 是重点,它出现在前面,用来注入变量
  head
    title #{ title } | My site
  body
    block content

// page.pug
extends Layout

block vars
  - var title = 'A blog'
  
block content
  h1 Blog title
  p blog content

文档的最佳实践

文档应该写“要干什么”,“为什么要这么干”,“准备怎么干”。不要写“是怎么干的”。因为需求在变、环境在变,如果把实现的细节写到文档里,将来和代码实现不一致,就会让使用者、维护者迷糊。
所以我们应该用格式化的数据来写,用稳定的数据接口,一次性输出文档、测试、mock 数据。本视频简单演示做法。

指导群里的小伙伴做小项目 应用创意:Chrome 共享首页,有两位同学主动领命,分开前后端就开做。结果我发现他们对文档的处理非常幼稚……所以便有了这样一个分享。

我的观点:

  1. 文档当然要写,但不要用自然语言这样写一大篇
  2. 文档如果不好好维护,将来表现和实际代码不一致,会造成更大的问题
  3. 所以开发者应该用更强的方式约束文档和代码,而不是大家主观协作
  4. 所以我们——尤其在前后端协作的时候——应该写格式化数据结构描述,然后通过编译的方式,用数据结构描述输出文档、测试、Mock Data

下面是视频:

\n 与 \r 的区别

所以 \r 换行之后,光标移到此行的 0 位,继续输出,于是新的一行会替代旧的一行,形成的效果就是进度条在更新;而 \n 则会另起一行,形成多行输出的效果。

近期的需求用到命令行输出的解析,在解析类似进度条的内容时,遇到一些问题。经过反复的搜索询问,大概得到答案:主要在于 \r 和 \n 的区别。StackOverflow 的一个答案是这么解释的:

As indicated by Peter, CR = Carriage Return and LF = Line Feed, two expressions have their roots in the old typewriters / TTY. LF moved the paper up (but kept the horizontal position identical) and CR brought back the “carriage” so that the next character typed would be at the leftmost position on the paper (but on the same line). CR+LF was doing both, i.e. preparing to type a new line. As time went by the physical semantics of the codes were not applicable, and as memory and floppy disk space were at a premium, some OS designers decided to only use one of the characters, they just didn’t communicate very well with one another ;-)

所以 \r 换行之后,光标移到此行的 0 位,继续输出,于是新的一行会替代旧的一行,形成的效果就是进度条在更新;而 \n 则会另起一行,形成多行输出的效果。

所以类似我这个需求,直接 line.split('\r').pop() 即可。

另外,new TextDecoder('utf-8').decode(binaryData) 返回的文本都是用 \r\n 做换行的。

解决 PHP 7.2.8 + MySQL 8.0.12 连接失败的问题

今天花3个小时解决了一个升级 PHP + MySQL 导致的连接问题,最后用 caching_sha2_password 插件解决的。

这两天又反复遇到这个问题,先写解决方案:

1. 使用 caching_sha2_password  插件

修改用户密码,并且用插件生成,可以解决 WordPress 的问题。

ALTER USER 'user'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'password';

2. 修改 my.cnf,使用原生密码

使用 Laravel + MySQL 8.0 的时候,遇到

SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client

修改 /etc/mysql/my.cnf (我是 Ubuntu 16.04),添加下面一行:

[mysqld]
default_authentication_plugin= mysql_native_password

然后重置密码:

ALTER USER 'user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
继续阅读“解决 PHP 7.2.8 + MySQL 8.0.12 连接失败的问题”

服务器备份工具

目前维护着几个服务器,所以需要一个备份工具帮忙备份。本文记录一下需求。

目前维护着几个服务器,所以需要一个备份工具帮忙备份。因为都是 wordpress,所以

  1. 可以访问 wordpress 的安装路径
  2. 可以部署在服务器上
  3. 最好是 PHP,方便 require wp-config.php

备份的内容:

  1. 备份数据库,直接访问 wp-config.php 就行
  2. 备份 wp-uploads,这里要支持差异化备份了
  3. 备份服务器配置,包括:
    1. php 配置
    2. nginx 配置
    3. crontab 配置

备份的处理:

  1. 每次备份的内容打一个压缩包,命名为 服务器-站名-日期-时间.zip
  2. 将备份后的内容上传到指定服务器
  3. 还需要开发一个本地工具,用来从制定服务器上下载备份文件到本地(服务器存储有点贵)
  4. 自动删除半年前(可配置)前的备份文件

差不多这样,想起来随时补充

Failed to start php-fpm.service: Unit php-fpm.service is masked.

升级服务器到 Ubuntu 18.04 后,php 的源也升级到 7.2,此时 php7.1 的一些模块已经没了,所以要换用 7.2 的功能。

周末手一抖把服务器从 17.10 升级到了 18.04,然后博客就挂掉了。

根据提示信息,nginx 应该正常工作,问题多半出在 PHP 上。service --status-all 之后,果然 php7.1-fpm 没有启动。然后照常 service php7.1-fpm start,咦,奇怪,报错了:

Failed to start php7.1-fpm.service: Unit php7.1-fpm.service is masked.

换用 service php-fpm start 也一样,区别就是 service 名字不太一样。然后 Google 之,没找到很靠谱的说法,但是找到一个类似的情况,发生于使用 do-release-upgrade 升级到 16.04 时,php5-fpm 启动不了,报类似的错误,解决方案是升级到 php7。

如此一来我也试试好了,因为直接 apt install php-fpm 会解析出来 php7.2,所以我尝试 service php7.2-fpm start,果然可以。既然如此,干脆升级到 7.2 好了,反正我也没啥特殊要求。

于是修改站点配置文件,把 php 接口指向 7.2 的 socket,然后安装几个欠缺的模块,终于又把博客跑起来了。

使用 Pug 和 Stylus 开发小程序的 watch 脚本

小程序开发有两点比较蛋痛:1. 每个页面必须有3个文件,wxml,js,wxss;2. 使用 wxml 替代 html,使用 wxss 替代 css,使得默认的编译失效。这个脚本用来帮助我们使用 pug 和 stylus 进行开发。

首先,我试用了 Wepy,丑的一逼,遂放弃。

小程序开发有两点比较蛋痛:

  1. 每个页面必须有3个文件,wxml,js,wxss
  2. 使用 wxml 替代 html,使用 wxss 替代 css,使得默认的编译失效

Webpack 在这里不太适用,因为 1,我们并非要把所有代码打包到一起。WebStorm 的 File Watcher 也不适用,因为它输出的文件扩展名是固定的(跟 pug 和 stylus 源程序有关)。于是我经过摸索了,使用 gulp 脚本解决了这个问题,代码如下:

import gulp from 'gulp';
import pug from 'gulp-pug';
import rename from 'gulp-rename';

const pugFiles = 'pages/**/*.pug';

// 通用的 pug 处理,可以把 pug 转译并改名为 .wxml 文件
async function doPUG(path) {
  gulp.src(path)
    .pipe(pug())
    .pipe(rename({
      extname: '.wxml',
    }))
    .pipe(gulp.dest('./pages'));
}

// 将所有 pug 进行转译
gulp.task('pug', async () => {
  return doPUG(pugFiles);
});

// 侦听 .pug 文件的变化,并转译被修改的
gulp.task('watch', ['pug'], () => {
  gulp.watch(pugFiles, ({path}) => {
    doPUG(path);
  });
});

接下来,开发的时候,只要运行 gulp watch 即可。

用类似的方式,我们还能处理 stylus -> css,这里就不详述了,大家可以自己试一试。

完整的 gulpfile 在 GitHub 仓库里,请自行取用。