Puppeteer 笔记

记录使用 Puppeteer 的一些经验。

记录使用 Puppeteer 的一些经验。

安装使用

puppeteer 是一个“库”,没有自带的命令行功能。所以要使用的话必须写一个文件,然后实现对应的功能。

npm i puppeteer

在 WSL 下使用

因为 WSL 的环境比较特殊,直接使用会报错:

No usable sandbox! Update your kernel or see https://chromium.googlesource.com/chromium/src/+/master/docs/linux_suid_sandbox_development.md for more information on developing with the SUID sandbox. If you want to live dangerously and need an immediate workaround, you can try using –no-sandbox.

所以需要禁用 sandbox:

const browser = await puppeteer.launch({
  args: ['--no-sandbox', '--disable-setuid-sandbox'],
});

试用后抓图成功,汉字变成方框,可能跟我 WSL 里的字体配置有关,先不管了。

关于 sandbox,可以看这个文档,我其实也不太了解……

我的测试仓库和工具

参见 GitHub puppeteer-tool

Laravel 开发笔记:环境搭建

记录 Laravel 的一些笔记,随时更新。

文档

英文官网:https://laravel.com/
英文文档:https://laravel.com/docs/5.5
中文文档:https://d.laravel-china.org/docs/5.5/packages

建议两边都打开,对比阅读。

配合 PHPStorm 使用

Laravel 里面定义了很多别名,直接放在 PHPStorm 里会有很多黄色曲线,看起来非常不爽。关键是影响代码补全,所以最好用一个库来搞一下。

安装 barryvdh/laravel-ide-helper:

composer require --dev barryvdh/laravel-ide-helper

注册服务。编辑 app/Providers/AppServiceProvider.php:

public function register() {
  if ($this->app->environment() !== 'production') {
    $this->app->register(IdeHelperServiceProvider::class);
  }
}

生成 meta 文件:

php artisan ide-helper:meta

MediaElement 笔记

贵司官网需要放视频,于是需要用播放器,最后选定 MediaElement。然后就开始踩坑之旅。当然,有些是我的问题,不过也有不少是文档没说清楚。这里记录一下。

贵司官网需要放视频,于是需要用播放器。然后就产生如下需求:

  1. 协议好,支持免费商用,最好 MIT
  2. 支持 SRT 字幕
  3. 支持尽可能多的平台

经过筛选,最后选定 MediaElement,一看 WordPress 在用基本就放心了。然后就开始踩坑之旅。当然,有些是我的问题,不过也有不少是文档没说清楚。这里记录一下。


全屏和弹性宽度

当前版本 4.2.5 有个 Bug,如果设置宽度为 100%,那么从全屏恢复到内嵌状态时,会留着全屏的宽度,撑开页面。如果设定一个特定的宽度就不会。但我们的页面是响应式的,需要允许它随页面变化而变化。

这个时候只好手工来做,我的选择是让它 100%,然后侦听从全屏返回的事件,发生后就把宽度恢复。另外,因为 fullscreenchange 事件还没有统一标准,所以不同浏览器里的事件名称也不一样,更不爽的是,IE 下是驼峰,其它浏览器是全小写,我也懒得再写函数转化了,反正就3种情况,全写一遍好了。

// fix MediaElement's issue
  let fitVideo = function() {
    setTimeout(() => {
    $('.mejs__container').width('100%')
      .find('video').width('100%')
      .end().find('.mejs__layers')
      .children().width('100%');
  }, 50);
};
if ('onwebkitfullscreenchange' in document) {
  document.onwebkitfullscreenchange = function() {
    if (!document.webkitFullscreenElement) {
       fitVideo();
    }
  };
} else if ('onmozfullscreenchange' in document) {
  document.onmozfullscreenchange = function() {
    if (!document.mozFullScreenElement) {
      fitVideo();
    }
  };
} else if ('MSFullscreenChange' in document) {
  document.MSFullscreenChange = function() {
    if (!document.msFullscreenElement) {
      fitVideo();
    }
  };
}

默认字幕

Web 标准是有默认字幕的,<track defualt> 即可。但是 MediaElement 没有,最后在 StackOverflow 上找到答案,原来有个未记录在文档里的初始化属性可以控制:

let player = new MediaElementPlayer('intro-video', {
  startLanguage: 'cn', // 这里的名字应该和 <track> 种的 srclang 属性一致
});

插件与生态

MediaElement 把一些有用但不太常用的功能抽出来做成了插件,放在 MediaElement Plugins。不过看起来这个项目有些属于维护,使用的时候很多问题。比如,直接在 features 里开启特定功能,即使对应的插件没有加载,也不会报错,就是没反应,很令人迷茫。

避免发起又取消请求

网站上线后,老板发现一个问题:从 Chrome 的 Network 面板可以看到,网页打开后,对视频文件发起了一到多个不等的请求,并且都取消了。

经过研究,我认为这个请求是 <video> 发起的,因为 preload 的默认值是 auto(参见:MDN),也即打开页面就预加载。而此时 MediaElement 被初始化,为了正确显示 UI,它会把 <video> 标签挪到自己创建的 <div> 里,这个过程就会导致“预加载 -> 取消”。因为视频默认不播放,所以我给 <video> 加上了 preload="none",问题解决。


其它大体上文档都能找到,就不多说了。

Vue 笔记:事件

记一些 Vue 的笔记。本篇均与事件处理相关。

onload

需要侦听 load

<template>
  <img src="/path/to/img" @load="onLoad">
</template>

<script>
export default {
  methods: {
    onLoad(event) {
      // do something
    }
  }
}
</script>

drop

需要阻止 dragover 的默认行为,不然不触发。

<template>
  <div class="drop-area" @dragover.prevent="onDragOver" @drop="onDrop">
</template>

<script>
export default {
  methods: {
    onDragOver(event) {
      // 此时仍然可以处理
    },
    onDrop(event) {
      console.log(event.dataTransfer);
    }
  }
}
</script>

PHP通过Sql生成带特定索引的数组

虽不明,但觉厉。

不明白原理,从别人代码中看到的,蛮好用,不过似乎性能不好:

SELECT id, sum(rmb) AS rmb, sum(device) AS device
FROM log_table
WHERE date>'2012-10-20'
GROUP BY id

这样一段Sql,用PHP自带的pdo这样请求:

$result = $dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC|PDO::FETCH_UNIQUE|PDO::FETCH_GROUP);

可以得到一个数组,使用sql中第一个字段也就是id为索引,每个元素为一个含两个属性(rmb, device)的对象。换成json写法大概是这样:

// 以前
[{id: 1, rmb: 1, device: 1}, {id: 2, rmb: 2, device:2}]

// 现在
{'1': {rmb: 1, device: 1}, '2': {rmb: 2, device: 2}}

这样再操作会方便很多。

Robotlegs笔记

以下记录学习Robotlegs期间遇到的问题和解答。

Robotlegs是一个纯AS3的小型框架,他解决的是不同模块间的交互问题,View部分和Model部分可以保留之前的逻辑。即使不实用Robotlegs,了解他的架构设计思想,对我们的工作也会有很大帮助。

我在使用的版本:1.5.2
官网地址:http://www.robotlegs.org/
下载地址:http://downloads.robotlegs.org/robotlegs-framework-v1.5.2.zip

以下记录学习Robotlegs期间遇到的问题和解答。

继续阅读“Robotlegs笔记”