Posted on

普吉岛旅游小记

理想是每年能去一次长途旅行的,这样活到70岁也不过去了40来个地方。40个地方,和那么多国家,那么多美丽的地方比,有些微不足道。只能加倍努力赚更多的钱啦。

去年和前年,借着公司的 outing,去了柬埔寨和日本。去年和今年,公司业绩不好,原本的长途旅行换成了郊游,去年去了舟山。而今年还没决定去哪里,公司补贴已经从 3500 元砍到了 1000 元。这么少的补贴下,那些不愿意自己出打钱的同事都选择了杭州周边的郊游。最多的是选择去千岛湖希尔顿酒店躺尸。

我对公司的Outing已经不报什么希望了,所以自力更生筹划了自己的长途旅游。

本来以为出去玩还是挺麻烦的,自己这样的流程走下来,发现真的是非常方便。

1、淘宝办理签证,加急,318 元一个人,另外送一张有效期 7 天的泰国手机卡。正好可以用来在境外打电话上网。
2、深圳航空官网预定机票。临时决定的出游,没有提前预定便宜的机票,预定的时候机票已经没有多少折扣了。为了便宜几块钱,选择了转机票,到广州转机。另外两张票一起定竟然比分开分别定要贵。还好我机智看出来其中的差别,选择了分开预定,省下了 200 块钱。
3、携程预订酒店,出去玩 8 天,定了 7 晚的酒店。第一天到酒店是凌晨 2 点多,12点就要退房了,就几个小时,也要三百多块钱,感觉非常不值,但是这么晚也没地方去,只能先定了。最终那天由于飞机晚点等原因,到酒店时候将近 4 点钟,那个时间点,要是每个床睡一觉,笔者这样的老年人也是受不了。
4、马蜂窝预定游玩项目。预定了个皮皮岛浮潜一日游。
5、预定机场接机。普吉岛机场到酒店还是有些距离的,人生地不熟,到站后再找出租车的话比较麻烦,而且是半夜的飞机,查了看机场已经没有合法营运的出租车了,一些黑车价格非常高。提前预定一个接机可以省很多事情。在马蜂窝预定皮皮岛项目的时候送了个加价购的权益,加 18 元送接机服务。顺手加购了一个。接机的是一辆小轿车,不限人数和行李,只要塞得下都可以。

准备的就这些啦。行李什么的就比较简单了

1、穿。泳装、夏装、帽子、雨伞,防嗮手臂护套,防晒围巾,拖鞋。
2、清洁。沐浴露、洗发露、防晒霜、老婆的各种化妆品、防蚊液。
3、吃。坐车坐飞机酒店吃的零食等。
4、手机充电器充电宝。

普吉岛玩的总体上是非常悠闲的。就是沙滩,逛街,夜市,游泳,浮潜。没有像去柬埔寨那要可以看到很多壮观靓丽的景色,没有像日本一样琳琅满目的商品。体验是比较平平,和国内的三亚也差不多。

一天的行程基本是睡到差不多自然醒,下楼吃酒店最后一班早餐。然后出门小镇里逛下一只逛到沙滩。蹚一会儿海水,再回镇上逛一会儿,吃午饭。接着再逛一会儿。等到脚差不多有点累了,就回酒店躺一会儿,然后下楼酒店泳池游泳。游泳完出门吃完饭。吃完逛夜市。差不多就是这样,非常悠闲。

下次去旅游的话,肯定不会再选择这种海边度假的方式了。虽然非常轻松,但笔者这样喜欢新鲜的事物的人来说,这样的游玩显得比较单调。

Posted on

vert.x 简单介绍

Vert.x is a tool-kit for building reactive applications on the JVM
Vert.x 是用于在JVM上构建响应式应用程序的工具包

今天看公司配置服务中心代码的时候,看到项目底层是用 vert.x 实现的。
笔者对 java 不太熟,随便搜索了解下。

1、先看下官方介绍

1.1、Scale 事件驱动,非阻塞模型,支持高并发。
1.2、多语种支持。支持 Java, JavaScript, Groovy, Ruby, Ceylon, Scala 和 Kotlin 等不同语言。
1.3、灵活。大小项目都适用。很多公司用来做实时游戏开发。不限制框架或容器,可以灵活创建应用。

2、再看下使用方法

代码看起来和 nodejs 非常像,类似于一个运行在 jvm 上的 nodejs

HttpServer server = vertx.createHttpServer();

server.requestHandler(request -> {

// This handler gets called for each request that arrives on the server
HttpServerResponse response = request.response();
response.putHeader("content-type", "text/plain");

// Write to the response and end it
response.end("Hello World!");
});

server.listen(8080);

Vert.x 底层使用 netty,但比 netty 要简单,支持 cluster。

光是看看这些介绍,还是不了解实际的使用场景是什么。

参考:
https://vertx.io/
https://leokongwq.github.io/2017/11/22/vertx-http-server-analyze.html
https://www.zhihu.com/question/22021343
https://www.cnblogs.com/rongfengliang/p/3531110.html
https://github.com/codefollower/My-Blog/issues/10
https://www.jianshu.com/p/2ab64267ae2c

Posted on

position sticky 失效问题

写了个图墙组件,其中用到了 sticky 做滚动固定。测试发现部分使用情况下会失效。搜了下,看到下面情况会导致 sticky 失效:

1、具有 sticky 属性的元素,其父级高度必须大于sticky元素的高度。
2、sticky 元素的底部,不能和父级底部重叠。
3、sticky 元素的父级不能含有 overflow:hidden 和 overflow:auto 属性。
4、必须具有 top,或 bottom 属性。

对应排查后,发现父元素上使用了 overflow:hidden,去除后问题修复了。

Posted on

设置 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 # 设置启动自动加载

Posted on

通过 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

Posted on

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

负责公司 vue 项目脚手架维护,有段时间没改过脚手架,最近对脚手架进行依赖升级,防止依赖腐化导致后面升级维护困难。

结果发现项目直接跑不起来了。排查后发现遇到了 webpack 升级 4 后升级了依赖的 tapable 组件的版本,并且和老版本不兼容,而 webpack 3 中依赖 tapable 没有指定版本号,导致依赖 webpack 3 的很多项目都跪了的问题。强制指定 tapable 版本号到 0.2.5 后问题修复。

Posted on

前端用户行为打点方案

背景

网站访问量大了以后,运营希望收集部分用户行为记录,用来分析预测用户偏好,进行针对性的优化。

方案

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 行左右的代码。

Posted on

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 包,实现命令行和交互功能。

Posted on

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

Posted on

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/