我厂技术沙龙

其实是我厂老板的个唱……但仍然非常值得看。

近期我厂老板春哥回国,在北京和深圳分别开了一场技术沙龙,介绍他的职业生涯、开发实践、最新成果等等。作为程序员的终极形态,我觉得这两场演讲非常值得有志于把程序员当成终身职业的同学学习。也可以回答很多类似“35岁的程序员应该怎么走”的问题。

先来是北京场:

然后是深圳场:

两场的内容并不一样,可以理解成上下半场。建议顺序观看。

最后说说最近半年来的工作感受。

首先远程工作还是挺好的。虽然光环褪去,负面感受更多更具体,不过对比普通上下班,感觉还是蛮好的。

其次,春哥是很牛的程序员,但作为老板有不少缺陷;公司也同样不完美。不过世上本就没有完美的老板和公司,在 OpenResty,春哥证明了他的想法的确有前瞻性,我们有机会改变未来,所以在这里工作还是很兴奋的。

希望接下来会更好。

浏览器切换中

最近比较忙,博客有些荒废。忙过这阵子再写吧。

接下来的三周,会强迫自己把开发浏览器切到 Firefox,争取从现有项目中找到兼容性问题,并且修复。

再接下来如是反复,Chrome > Firefox > Edge > Safari > Chrome……

以后客户越来越多了,兼容性得多费心了。

下午4点更新

Firefox 不支持 SourceMap……已经切回 Chrome 了,晚上继续尝试。

8-14 更新

Firefox 团队曾经抱怨 Google Chrome 不正当竞争,故意在几个大型产品中给 Firefox 挖坑,打压他们在用户心目中的地位。然而经过我这一周来的使用,我觉得 Firefox 实在做得不够好,很难让开发者选择它作为主力开发工具。

  1. 使用 Vue Cli 会不停报错,找不到 sw.js,连接不到 sockjs-node 等等
  2. 使用 webpack 无法加载到 sourcemap,无法 debug。(应该是配置问题,因为 Vue Cli 3 可以。
  3. 报错多了就影响性能,各种卡顿。
  4. 断点不会自动跳过去,屏幕没有明显的视觉效果,开始被迫重启好几次
  5. 断点不会自动更新堆栈、变量状态,需要点击一次“Step over”

问题很多,很影响开发效率。可惜我厂老板特别爱用 Firefox,所以我还必须照顾下 Firefox,经过一周的挣扎,现在倒是好一些了,Windows 10 的表现还不错。

crontab 笔记

在服务器上定时跑程序。重点:

  1. 要执行的程序,比如 php,必须全局可用
  2. 执行的程序,必须处理内部的文件结构,因为执行路径不太确定

生成日期时间配置,可以使用这个工具

生成日志

1 0 * * * php /var/www/laravel/artisan check:daily > /var/log/laravel.log

每天凌晨 00:01 执行 php,跑一个 laravel command,并且把日志放在 /var/log/laravel.log

续写日志,而不是覆盖

使用 >> 替换 >

使用 Webpack + Mocha 进行单元测试(二)

作为一名远程工作者,我并不能保证100%的电源供应,就目前的经验来看,我大约有30%的时间靠电池工作。所以我对能耗也比较敏感,把 eslint 和单元测试(mocha)放在 webpack 里做热加载,我觉得实在没什么必要,还是单独写单独跑吧。

查看 mocha-webpack 的 README,它对自己的介绍是:mocha-webpack 基本上等效于 $ webpack test.js output.js && mocha output.js 命令的封装,但是更高效、更强大。

让我们忽略后半句,先不去研究它高效和强大在什么地方,只看前半句。如果本质如此的话,那就不复杂,我只要写一个 webpack 配置文件生成所有的测试,然后跑这些测试就行了。最终方案:

  1. 一个入口文件,import 所有测试文件
  2. 用 webpack 打包入口文件,忽略掉不需要测试的内容(比如 CSS)
  3. 跑这个测试
  4. 平时写测试随便改下 import 路径就行了

测试文件多而杂,一个一个 import 太麻烦,可以写一个脚本帮我们:

const context = require.context('.', true, /.+\.test\.js?$/);
context.keys().forEach(context);
module.exports = context;

然后配合这样的配置文件即可:

const path = require('path');
const nodeExternals = require('webpack-node-externals');
const {resolve} = require('./webpack.base.config');

resolve.alias.test = path.resolve(__dirname, '../test');

const config = {
  target: 'node',
  entry: 'test/index.js',
  output: {
    path: path.resolve(__dirname, '../dist'),
    filename: 'test.build.js',
  },
  externals: [nodeExternals()],
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true,
            },
          },
        ],
      },
      {
        test: /\.ya?ml$/,
        use: [
          'json-loader',
          'yaml-loader',
        ],
        exclude: /node_modules/
      },
      {
        test: /\.(css|styl)$/,
        loader: 'null-loader',
      },
      {
        test: /\.(png|jpg|gif|svg|woff2|eot|woff|ttf|ico)$/,
        loader: 'null-loader',
      },
      {
        test: /\.pug$/,
        loader: 'pug-plain-loader',
      },
    ],
  },
  mode: 'none',
  resolve,
};

module.exports = config;

执行的时候,直接用 shell 脚本来跑就行。

使用 Webpack + Mocha 进行单元测试(一)

我厂产品经过两年的打磨,目前功能基本稳定了,接下来的工作重点是用测试保证质量。除了继续丰富 E2E 测试,我还计划添加一些单元测试,用来确保一些重要函数和类正常工作。

所以就要选择框架。开始想试试近期比较热门的 Jest,找了些文章看了看,发现也没啥吸引我的特色,E2E 和 UI 我厂的 Navlang 目前独步江湖,无出其右者,考虑到以前用 Mocha 写过一些单元测试,所以决定继续用 Mocha。

但是已经很长时间没写了,所以想先研究下工具链。如果只是单文件的话,直接 mocha test.js 就好;如果测试文件用了 ESM,那么加上 @babel/register 也就够了,mocha —require @babel/register test.js

但是我们项目用到了 Vue,还用 Webpack 里的 resolve 定义了很多目录,所以为了能够兼容项目代码,我必须要 Mocha 结合 Webpack,用这个关键词一搜索,得到两个结论:mocha-webpack 和 mocha-loader。

前者已经一年多没更新了,而且要求 mocha@5,所以我就不想用了。转过头研究 mocha-loader,经过反复试验,加上阅读源码,我得出结论:

mocha-loader 的目标是在 Webpack 里继承测试,比如边开发边测试,并不是我想要的,打包测试内容,整合测试框架,方便用户在 CI 系统里集中进行测试。

所以我真正需要的,其实是:

  1. 创建一个独立的 webpack 配置文件,用来打包单元测试
  2. 打包后执行测试,返回测试结果

基本上,今天大半天的工作是白费了。mocha-loader 的作者应该把目的写在 README 里的……

解决 load-scripts.php jQuery is not defined 的问题

不知道从哪天起,我的博客后台就坏了。没错,就是这个后台。写文章变成非常困难的一件事。各种功能都不好使,页面布局也混乱不堪。于是我打开开发者工具,看到一大堆报错,基本上都是 load-scripts.php jQuery is not defined。看起来是某些 jQuery 插件启动的时候 jQuery 还没完成加载。

这就有点蛋疼了。我应该没有手动调整过这些脚本的加载,但是也说不定,我好像有把本地的 jQuery 换成 CDN 上的版本,但也不是很确定。不过我有好几台电脑,有些电脑上保留着可用的 JS 的缓存,我就勉强用着,反正也不常写文章。我试着 Google 这个问题,但可能关键词组合没选好,没能找到答案。WordPress 历史太悠久,跟 jQuery 相关的问题不胜枚举,搜索结果里噪音太多。

结果前两天终于所有缓存都失效了,然后我就没法写文章了,于是必须解决这个问题了。没想到这次我很快找到了解答:

Try adding define('CONCATENATE_SCRIPTS', false); to your wp-config.php file just below the define('DB_HOST' line.

https://wordpress.org/support/topic/failed-to-load-jquery-at-load-scripts-php/

使用后台的时候,WordPress 会试图把所有 JS 合并到一起,以便节省 HTTP 请求。这个设计思路没问题,但看起来他们的实现比较简单粗暴,只是简单的合并,并没有很好的检查依赖顺序,以至于可能导致后台功能失败。

解决 composer global install 失败的问题

今天突发奇想,打算写会儿 PHP,按照 Laravel 文档,准备先安装 laravel/installer,结果 composer global require laravel/install 安装失败,提示错误信息:

Your requirements could not be resolved to an installable set of packages.

出问题的包是 symfony/console,需要的版本和已安装版本不一致,安装新版本失败。简单搜了一下,答案比较多,有说版本问题,有说权限问题,有说 PHP 模块问题。

我看了一眼权限,应该没问题。然后 composer help 看了看命令参数,发现有一个命令,可以查看所有已安装,现在版本有些旧了,可以升级的包:composer global outdated。执行之,发现以前安装过 laravel/installer 1.x,自然也安装了 1.x 需要的 symfony/console 作为依赖。那么,多半是这个旧版本阻止了新版本的安装,导致新版 laravel/installer 安装失败。

于是 composer global remove laravel/installer 先删除就版本,然后安装新版本,就 OK 了。

然后,折腾了半天,我又不想写 PHP 了……