position sticky 失效问题

写了个图墙组件,其中用到了 sticky 做滚动固定。测试发现部分使用情况下会失效。搜了下,看到下面情况会导致 sticky 失效:
1、具有 sticky 属性的元素,其父级高度必须大于sticky元素的高度。
2、sticky 元素的底部,不能和父级底部重叠。
3、sticky 元素的父级不能含有 overflow:hidden 和 overflow:auto 属性。
4、必须具有 top,或 bottom 属性。
对应排查后,发现父元素上使用了 overflow:hidden,去除后问题修复了。

设置 debian 服务器虚拟内存

服务器虚拟内存只有 512M,安装 X 服务的时候提示虚拟内存太小了,搜了把,找到如下设置调整虚拟内存大小的方法:
cd /var
touch swap.img # 创建虚拟内存文件
chmod 600 swap.img # 设置权限
dd if=/dev/zero of=/var/swap.img bs=1024k count=1000
mkswap /var/swap.img # 设置文件为虚拟内存
swapon /var/swap.img # 启用虚拟内存
free # 释放内存
echo "/var/swap.img none swap sw 0 0" >> /etc/fstab # 设置启动自动加载

通过 rel=noopener 属性进行性能优化

当你通过打开新标签的方式跳转页面时,最好给 a 标签加上 rel="noopener" 属性,特别是在调往其他域的页面的时候。
代码如下:
<a href="http://example.com" target="_blank" rel="noopener">
Example site
</a>
从安全上看:
如果没有添加这个属性,那么新页面可以通过 window.opener 变量访问原来的页面,虽然受限于跨域安全机制,新页面不能读取老页面信息,但是新页面可以通过 window.opener.location = newURL 来修改老页面连接,让其跳转到其他页面。
从性能上看:
另外一个重要的问题是,如果仅仅通过 target="_blank" 标签从新标签打开页面。新老页面将运行在同一个进程上,如果新老页面上有运行大量计算任务的脚本时,新老页面的性能都会受到影响。
还有要注意的点,在老的浏览器中,rel=noreferrer 除了禁用 window.opener 外,还一并禁用了 HTTP 头部 的 Referer 属性,会对页面打点等功能造成影响,可以通过

var otherWindow = window.open();
otherWindow.opener = null;
otherWindow.location = url;

的方式进行规避。但是这样的话又会引入新的问题。这个方法在 safari 下会因为弹出机制被拦截。
参考文章:
https://developers.google.com/web/tools/lighthouse/audits/noopener?hl=zh-cn
https://jakearchibald.com/2016/performance-benefits-of-rel-noopener/
https://mathiasbynens.github.io/rel-noopener/#hax
http://lists.w3.org/Archives/Public/public-whatwg-archive/2015Jan/0002.html
http://www.jdon.com/idea/target-blank.html
https://my.oschina.net/dawd/blog/816023

webpack 3 脚手架 tapable 依赖错误问题修复

负责公司 vue 项目脚手架维护,有段时间没改过脚手架,最近对脚手架进行依赖升级,防止依赖腐化导致后面升级维护困难。
结果发现项目直接跑不起来了。排查后发现遇到了 webpack 升级 4 后升级了依赖的 tapable 组件的版本,并且和老版本不兼容,而 webpack 3 中依赖 tapable 没有指定版本号,导致依赖 webpack 3 的很多项目都跪了的问题。强制指定 tapable 版本号到 0.2.5 后问题修复。

前端用户行为打点方案

背景
网站访问量大了以后,运营希望收集部分用户行为记录,用来分析预测用户偏好,进行针对性的优化。
方案
1、先要确定要收集哪些行为
根据我们公司的情况,这里确定了要收集用户鼠标点击,手指移动起始位置,和表单获取焦点的行为。除此之外,还有用户键盘输入等行为可以记录,可以选择性的增加。
2、确定上报的方式
上报是通过将行为数据提交到一个后端接口进行记录。为了避免实时的提交数据,造成无必要的性能损耗,可以将行为数据存储到一个列表中,每隔一段时间,从列表中获取一定数量的数据进行提交。
用户行为数据可能会比较多,选择间隔时间提交固定数量的行为数据后,可能会有部分数据在用户离开页面之前,无法有效的提交到后端。这时候,需要在用户离开页面之前,将剩下未提交的数据全部都一起提交了。但是有个问题,用户离开页面的时候,如果再触发 ajax 去提交数据,ajax 很大概率会被中断,导致数据提交失败。所以这里采用的方案是,在 window 的 unload 事件里把剩下的行为数据存储到 localStorage 之中。然后再访问下一个页面,或者下次访问同域的页面的时候,在用户第一次触发点击行为的时候合并 localStorage 里的数据一次性提交到后端。
不过存放到 localStorage 的方式也无法保障能提交所有的数据。在用户关闭浏览器 tab,或者浏览器 crash 的时候,window 的 unload 是不会触发的。并且不是所有浏览器都支持 window unload 事件。支持请见 http://w3help.org/zh-cn/causes/SD9026
为了通用性,提交数据可以使用跨域支持的 new Image() 方式
3、确定数据存储格式
前面提到要将数据存储到列表中,所以需要确定下数据存储格式。
点击和移动需要记录点击事件的 screenX, screenY, pageX, pageY 还有时间和事件名。
基本是这样的,逻辑确定好后,实现也比较简单了,实际写下来 200 行左右的代码。

IOS 模拟器命令行使用方法

背景
在公司写完页面之后要先自己测试页面的兼容性,作为非测试的同学,手头没有那么多的测试机可以用,所以很多情况下需要使用模拟器进行测试。
默认情况下使用 IOS 模拟器比较麻烦,在使用模拟器之前
1、首先需要安装 Xcode 编辑器,模拟器是作为 xcode 的一个子组件出现的。
2、装好后,打开 Xcode,在首选项里选择安装模拟器。
安装好模拟器后,通过下面的命令进行启动调试
1、查看设备列表 simctl list devices 命令
2、启动模拟器, open -a Simulator –args -CurrentDeviceUDID $设备ID
3、安装程序包 simctl install booted $程序安装包绝对路径
4、启动程序 simctl launch booted $程序包名
5、打开需要调试的页面, simctl openurl booted $唤起短链
6、电脑上打开 safari 浏览器,点击开发目中的模拟器,选择模拟器中的运行的页面
7、关闭模拟器,killall Simulator 命令
下面是模拟器中一些常用的快捷:
1、回到桌面:⌘+⇧+H
2、模拟器缩放:⌘+1、⌘+2、⌘+3、⌘+4、⌘+5,对应缩放100%、75%、50%、33%、25% 大小
3、锁屏&解锁屏:⌘+L
另外一个注意的要点是,模拟器中的代理与 mac 系统的代理是同步的。
代码溜的同学,可以对这些命令做一个封装,比如用前端常用的 nodejs 来处理。
写起来也比较简单,主要使用 commander 和 prompt 包,实现命令行和交互功能。

Could not create lock at /var/run/yum.pid: [Errno 28] 问题修复

环境:
Linux VM_185_189_centos 3.10.0-514.21.1.el7.x86_64 #1 SMP Thu May 25 17:04:51 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
执行 yum update -y ,发生报错
Could not create lock at /var/run/yum.pid: [Errno 28]
执行 ps aux | grep yum 查看是否有进程冲突,发现没有。
查 google 发现是 centos 的 bug ,需要重启修复问题。
reference:
https://www.davidvandertuijn.nl/could-not-create-lock-at-varrunyumpid-errno-28-no-space-left-on-device
https://bugs.centos.org/view.php?id=14278

debian 9 安装 docker 教程

环境
Debian Stretch 9
uname -a => Linux VM-1-242-debian 4.9.0-3-amd64 #1 SMP Debian 4.9.30-2 (2017-06-12) x86_64 GNU/Linux
1、卸载老版本:sudo apt-get remove docker docker-engine docker.io
2、更新仓库: sudo apt-get update
3、安装可以使 apt 运行在 https 协议上的依赖:sudo apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common
4、添加 docker 官方 GPG key:curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | sudo apt-key add -。简单介绍下,这里的 GPG key 是公钥,用来解密加密的 docker 安装包。这是在网上安全传播发布的软件的一种方式。
5、验证 GPG key 正确安装:sudo apt-key fingerprint 0EBFCD88,看输出中 Key fingerprint 是否为 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
6、添加 docker 仓库 sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") $(lsb_release -cs) stable",如果想安装 edge 或者 测试版,可以在 stable 后面加 edge 和 test
7、再次执行 sudo apt-get update 更新新添加仓库里的信息。
8、sudo apt-get install docker-ce 安装 docker,如果第六步中添加了 edge 版本,那这个命令安装的是最新版本,而不是稳定版本。在生产环境里建议安装最新的稳定版本。可以通过 sudo apt-get install docker-ce=版本号 进行安装。版本号可以通过 apt-cache madison docker-ce 命令获取。
9、验证安装成功 sudo docker run hello-world。
10、卸载 sudo apt-get purge docker-ce && sudo rm -rf /var/lib/docker
reference:
https://docs.docker.com/install/linux/docker-ce/debian/

小米手机 adb 调试无法识别问题解决

今天开发的一个页面在公司 App 安卓版本中测试发现有些问题。页面使用一种叫 xcore 的技术实现,在公司 App 中使用公司定制的内核渲染。定制的内核基于腾讯的 x5 浏览器内核。本来公司有自己开发的一套真机页面测试软件,但是疏于维护,已经废弃停止使用了。App 团队的同学推荐使用腾讯的 TBS_Studio 来测试。调试工具有了,还缺少一台安卓机子,从测试团队借来一只超级大的小米手机,不记得什么型号了。
1、需要在手机上调试,先要开启调试模式吧,手机上找系统版本号,点击 6 下开启开发者模式。
2、开启开发者模式后还需要开启 USB 调试模式:“设置”-“其他高级设置”-“开发者选项”-“USB调试”
一般情况下这样子就可以了,至少前几年是这样子,好几年没开发 H5 页面,没想到发生了这么多变化。
设置完上面两步之后,发现 TBS_Studio 还是无法识别这个小米手机。继续往上查找解决方案。
3、发现新的小米系统里,开启USB调试模式后还要开启调试端口:保持手机连接在电脑上,然后在拨号界面输入 ##717717## ,输入完成之后会看到 “Diag USB port enable” 的弹出提示,表示端口已经成功开启。
4、在电脑命令窗口中 adb kill-server,然后 adb start-server,重启 adb 服务,最后 adb devices,就可以看到设备啦
TBS_Studio 底层的连接肯定也是使用 adb 啊,adb devices 里看到了设备,TBS_Studio 自然是成功的连上了

服务器 ssh 自动断开问题

有好几种解决方案
1、最不好的一种,设置终端超时自动输入字符。对 iTerm 而言 Profile 的 Session tab 里面可以设置。缺点很明显,超时时会自动输入字符影响使用。
2、客户端 ssh 配置定时保持连接,方法是修改 ~/.ssh/config 文件,加入
Host *
ServerAliveInterval=60
这样每 60 秒给服务器发送一个 no-op 包用来保持连接。
3、对单次连接可以使用 ssh -o ServerAliveInterval=30 user@host 命令来传递 ServerAliveInterval 参数
4、服务端 ssh 配置,方法是修改 /etc/ssh/sshd_config 文件,取消
TCPKeepAlive yes
ClientAliveInterval 30
ClientAliveCountMax 3
5、行代码的注释开启定时发包保持连接的功能。记得重启 ssh 服务激活配置。
6、当然还有更高级的技术。可以试试 mosh,除了保持连接外,还可以实现自动连接。需要分别在服务器和客户端安装软件。
2018-03-08 15:31:14
既然讲到了 mosh,讲下怎么安装吧。三行命令,以 debian 服务器,mac 客户机为例:
1、服务端安装 apt-get install mosh
2、配置语言 vim ~/.bashrc 添加 export LC_ALL="en_US.UTF-8",source ~/.bashrc
3、客户端 brew install mosh
下面就可以使用了
mosh user@host