BinZhiZhu's Blog

Hello,World.


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 搜索

熬夜在VPS简单搭了个frp内网穿透web服务

发表于 2019-05-02 | | 阅读次数:
字数统计: 623 | 阅读时长 ≈ 2

搭建成功 : )

http://ww1.sinaimg.cn/large/00655MmOgy1g2mbbs6c3nj31gc13qkjl.jpg

回顾一下

小白前几天发了一个帖子,简单调研了一下大佬们平时用服务器来干啥,大多数的答案基本如下:
1.闲置、吃灰
2.搭梯子、frp 内网穿透
3.测试服务器
4.API 调用
5.等等更加高级的玩法
这里贴一下之前的帖子 https://www.v2ex.com/t/559909#reply93

为什么瞎几把搞

然后我琢磨了一下,觉得吃灰的话还不如自己搭一个内网穿透,也就是大家口中说的 frp 咯。
之前我毕业前实习的时候做开发是用花钱去买市场上的一些内网穿透的产品,之前用的是 natapp,开始用免费的。
结果可想而知,那速度慢的一批。于是买了个 10 元 /月的套餐,流量勉强还能接受吧,基本用于微信开发,大家知道的啦,sbox 沙盒那边配置一下开发起来以及测试比较方便,免得每次都得更新到线上才可以测试,或者说更新到测试服务器,这样开销有点大,所以那会就这样搞。后来业务逐渐少了,自己也买了个阿里云的小学机,虽然尿管,但是自己搭搭博客还是🆗的。这里就不扯淡了,有点丢人,这里高手如云,大家给个面子。

瞎几把搞

搭建这个 frp 的公网服务器我是选择了我闲置吃灰的 VPS,搬瓦工买的,$19.99/year。现在估计玩蛇了,上次看了一下,有点贵了,我有点怕不能续费。那么平时只是翻墙,所以打算就拿它开刀呗。

流程

  • 公网服务器安装最新版本的 release,根据 arch。
  • 配置 frps.ini
  • 测试连接
  • 内网同样安装相同版本的 frp
  • 配置 frpc.ini (注意端口统一的问题)
  • 阿里云添加一个新的域名
  • 域名解析到自己的公网 ip
  • 由于要让外网访问到内网,所以在服务器增加一个虚拟域名。( root 填自己内网的项目地址即可)
  • 内网测试连接
  • 收工

其实过程中遇到一些小问题,官方 issue 也很多人提到过,类似于:
[W] [service.go:82] login to server failed: dial tcp xxx.xxx.xxx.xxx:7000: connect: connection timed out

交流贴,纯粹跟大家分享一下,并不是炫技哈~~

CSS BEM 书写规范

发表于 2019-04-20 | | 阅读次数:
字数统计: 1.2k | 阅读时长 ≈ 4

BEM命名约定


使用 BEM 命名规范,理论上讲,每行 css 代码都只有一个选择器。

BEM代表 “块(block),元素(element),修饰符(modifier)”,我们常用这三个实体开发组件。

在选择器中,由以下三种符号来表示扩展的关系:

1
2
3
4
5
-   中划线 :仅作为连字符使用,表示某个块或者某个子元素的多单词之间的连接记号。
__ 双下划线:双下划线用来连接块和块的子元素
_ 单下划线:单下划线用来描述一个块或者块的子元素的一种状态

type-block__element_modifier

块(block)

一个块是设计或布局的一部分,它有具体且唯一地意义 ,要么是语义上的要么是视觉上的。

在大多数情况下,任何独立的页面元素(或复杂或简单)都可以被视作一个块。它的HTML容器会有一个唯一的CSS类名,也就是这个块的名字。

针对块的CSS类名会加一些前缀( ui-),这些前缀在CSS中有类似 命名空间 的作用。

一个块的正式(实际上是半正式的)定义有下面三个基本原则:

  1. CSS中只能使用类名(不能是ID)。
  2. 每一个块名应该有一个命名空间(前缀)
  3. 每一条CSS规则必须属于一个块。

例如:一个自定义列表 .list 是一个块,通常自定义列表是算在 mod 类别的,在这种情况下,一个 list 列表的block写法应该为:

1
.list

元素(element)

块中的子元素是块的子元素,并且子元素的子元素在 bem 里也被认为是块的直接子元素。一个块中元素的类名必须用父级块的名称作为前缀。

如上面的例子,li.item 是列表的一个子元素,

1
2
3
4
5
6
.list{}
.list .item{}


.list{}
.list__item{}

修饰符(modifier)

一个“修饰符”可以理解为一个块的特定状态,标识着它持有一个特定的属性。

用一个例子来解释最好不过了。一个表示按钮的块默认有三个大小:小,中,大。为了避免创建三个不同的块,最好是在块上加修饰符。这个修饰符应该有个名字(比如:size )和值( small,normal 或者 big )。

如上面的例子中,表示一个选中的列表,和一个激活的列表项

1
2
3
4
5
6
7
8
9
10
.list{}
.list.select{}
.list .item{}
.list .item.active{}


.list{}
.list_select{}
.list__item{}
.list__item_active{}

LESS 书写规范

使用 .less 后缀的文件来存储变量、混合代码以及最终合并压缩。

子less 注解
lib-base.less 预定义的变量,例如颜色、字号、字体
lib-mixins.less 用于混合的代码,例如渐变、半透明的混合
lib-reset.less 初始化
lib-ui.less 颗粒化ui功能
xxx.less 模块样式

.less 文件的引用顺序会对最终编译的样式的作用域和优先级产生影响,请尽量按照由底层到自定义的顺序来引用。

关于风格

书写原则

1. 原则上不会出现2层以上选择器嵌套

使用BEM原则,用命名来解耦,所有类名都为一层,增加效率和复用性

2. 两层选择器嵌套出现在.mod-xxx__item_current子元素的情况,如下:

使用推荐的嵌套写法

常规写法:

1
2
3
4
5
.xxx{}
.xxx__item{}
.xxx__item_current{}
// 嵌套写法
.xxx__item_current .mod-xxx__link{}

推荐:

1
2
3
4
5
6
7
8
9
10
11
.xxx{}
.xxx__item{}
.xxx__item_hightlight{}
.xxx__product-name{}
.xxx__link{}
.xxx__ming-zi-ke-yi-hen-chang{}

// 嵌套写法
.xxx__item_current{
.xxx__link{}
}

对应的HTML结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<ul class="xxx">
<li class="xxx__item">第一项
<div class="xxx__product-name">我是名称</div>
<span class="xxx__ming-zi-ke-yi-hen-chang">看类名</span>
<a href="#" class="xxx__link">我是link</a>
<li>
<li class="xxx__item xxx__item_current">第二项 且 当前选择项
<div class="xxx__product-name">我是名称</div>
<a href="#" class="xxx__item-link">我是link</a>
<li>
<li class="xxx__item xxx__item_hightlight">第三项 且 特殊高亮
<div class="xxx__product-name">我是名称</div>
<a href="#" class="xxx__item-link">我是link</a>
<li>
</ul>

BEM 解决问题

组件之间的完全解耦,不会造成命名空间的污染,如:.mod-xxx ul li 的写法带来的潜在的嵌套风险。

性能

BEM 命名会使得 Class 类名变长,但经过 gzip 压缩后这个带宽开销可以忽略不计

xxx__item_hightlight

QA

  • 更新文档只是有利于提高自己开发效率 有版权问题 请联系本人修正。

MacOS PhpStorm 快捷键

发表于 2019-04-20 | | 阅读次数:
字数统计: 310 | 阅读时长 ≈ 1

全局搜索(command + shift + F)

显示类中的方法 (command + 7)

函数追踪 (command +鼠标点击)

单行注释/取消(command + /)

输入行号跳到某一行(command + l)

列出打开的文件(command + e)

删除当前行(command + x)

复制当前行(command + d)

跳到变量申明处(command + b)

格式化代码(command + option + l)

关闭当前窗口 (command + w)

项目刷新 (command + option + y)

多行注释(command + option + /)

查找//@todo标签(command + 6)

列出左侧文件(command + 1)

切换大小写(command + shift + u)

复制(command + c)

粘贴(command + v)

撤销(command + z)

显示行号

IDE settings->Editor->General->Appearance->Show Line Number

换肤

IDE settings->Editor->Colors & Fonts 下拉框选择即可。

设置字体大小

IDE settings->Editor->Colors & Fonts->font 设置即可。

配置文件头默认注释

IDE settings->Editor->File and Code Templates->PHP File Header。

设置注释不顶格

IDE settings->Editor->Code Style->PHP 去掉勾 Line comment at first column。

去掉右上角游览器

IDE settings->tools ->WebBrowsers 去掉选中即可。

PHPStorm + CodeSniffer

设置

IDE settings->Languages & Frameworks->PHP->CodeSniffer-> 配置即可。

选择编码规范

IDE settings->Editor->Inspections->PHP->PHP Code Sniffer validation(打钩) ->Coding Standard 选择规范(PEAR)

TODO

  • 待更新

docker-Compose 相关命令

发表于 2019-04-20 | | 阅读次数:
字数统计: 1.5k | 阅读时长 ≈ 5

下面将介绍 docker-compose 子命令的使用。也可以通过运行 docker-compose --help来查看这些信息。

  • build
  • help
  • kill
  • ps
  • restart
  • run
  • start
  • up
  • logs
  • port
  • pull
  • rm
  • scale
  • stop

build

1
2
3
4
5
用法:build [options] [SERVICE...]
选项:
--force-rm 总是移除构建过程中产生的中间项容器
--no-cache 构建镜像过程中不使用Cache
--pull 总是尝试获取更新版本的镜像

构建服务并打上project_service风格的标签(如:composetest_db)。如果你更改了服务的Dockerfile或者构建目录下的内容,需要运行docker-compose build重新构建服务。

help

1
用法:help COMMAND

显示命令的帮助信息及用法教程。

kill

1
2
3
用法:kill [options] [SERVICE...]
选项:
-s SIGNAL SIGNAL 是发送给容器的信号量,默认是 SIGKILL

通过发送SIGKILL信号来强制终止运行中的容器,也可以发送指定的信号量,例如:

1
$ docker-compose kill -s SIGINT

ps

1
2
3
用法:ps [options] [SERVICE...]
选项:
-q 仅仅显示容器ID

列出容器。

restart

1
2
3
用法:restart [options] [SERVICE...]
选项:
-t, --timeout TIMEOUT 设置关闭服务的超时时间,单位为秒,默认为10

重启服务。

run

1
2
3
4
5
6
7
8
9
10
11
用法:run [options] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]
选项:
-d 分离模式:在后台运行容器,只打印新的容器名称
--entrypoint CMD 覆盖镜像的入口点(CMD ...)
-e KEY=VAL 设置环境变量,可以使用多次
-u, --user="" 通过指定的用户名或用户id来运行
--no-deps 不启动link连接的服务
--rm 运行结束后移除容器,在分离模式下将被忽略
-p, --publish=[] 将容器暴露端口映射到主机端口
--service-ports 通过服务映射到主机的端口执行命令
-T 禁用pseudo-tty分配,默认会分配一个TTY

对服务运行的命令。例如,以下命令启动web服务并运行bash命令

1
$ docker-compose run web bash

run命令,将使用服务中已经定义的配置来创建运行一个新的容器。也就是说,如此创建的容器,将会使用相同的挂载卷、容器连接等相同的配置,但它们依旧可以存在差异。

第一个区别是,可以使用run命令覆盖服务中指定的运行命令。例如,web服务中的配置指定的运行命令为bash,那么docker-compose run web python app.py将使用python app.py来覆盖它。

第二个区别是,docker-compose run命令不会创建任何服务配置中指定的端口映射,这样可以防止多个容器映射同一端口的冲突。如果你需要使得服务的端口创建并映射到主机,需要指定--service-ports标记,如下:

1
$ docker-compose run --service-ports web python manage.py shell

或者可以手动指定端口映射,和使用docker run一样,使用--publish或-p选项:

1
$ docker-compose run --publish 8080:80 -p 2022:22 -p 127.0.0.1:2021:21 web python manage.py shell

如果启动一个带有容器连接的服务,run命令将首先检查连接到的服务是否已运行,如果是停止状态,将会启动它,直到所有的相关服务都处于正在运行状态,才会执行你创建的命令。例如:

1
$ docker-compose run db psql -h db -U docker

这将创建一个与PostgreSQL容器db交互服务。

如果你不希望启动相关联容器,可以使用--no-deps标记:

1
$ docker-compose run --no-deps web python manage.py shell

start

1
用法:start [SERVICE...]

启动服务中已经存在的容器。

up

1
2
3
4
5
6
7
8
9
用法:up [options] [SERVICE...]
选项:
-d 分离模式:在后台运行容器,只打印新的容器名称
--no-color 单色输出
--no-deps 不启动link连接的服务
--force-recreate 强制重新创建容器,即使镜像没有任何改变。与--no-recreate会冲突
--no-recreate 如果对应容器已经存在,不重新创建它。与--force-recreate会冲突
--no-build 不构建镜像,即使缺失
-t, --timeout TIMEOUT 为容器设置关闭超时时间,单位:秒 (默认为 10)

对服务,构建镜像、(重新)创建容器、启动容器。

该命令还将启动任何相关的且没有被启动的服务。

docker-compose up命令将显示所有容器的输出,命令结束时,所有容器都将关闭。运行docker-compose up -d将在后台启动运行容器。

如果服务中已经存在运行中的容器了,并且在容器创建后更改服务配置或者镜像,docker-compose up命令将会停止当前容器(保存挂载卷)并重新构建启动容器。当然,也可以通过--no-recreate选项来避免重新构建。

使用--force-recreate标记,可以强制停止并重构所有容器。

logs

1
2
3
用法:logs [options] [SERVICE...]
选项:
--no-color 单色输出

显示服务输出的日志内容。

port

1
2
3
4
用法:port [options] SERVICE PRIVATE_PORT
选项:
--protocol=proto tcp 或 udp [默认为 tcp]
--index=index 对应实例服务的第几个容器[默认为 1]

打印服务中端口绑定对应的主机端口。

pull

1
2
3
用法:pull [options] [SERVICE...]
选项:
--ignore-pull-failures 尽可能拉取服务,忽略拉取失败

拉取服务镜像。

rm

1
2
3
4
用法:rm [options] [SERVICE...]
选项:
-f, --force 强制删除,不询问确认信息
-v 移除容器挂载的卷

删除停止的服务容器。

scale

1
用法:scale [SERVICE=NUM...]

设置一个服务需要运行的容器数量。
参数形式为service=num。例如:

1
$ docker-compose scale web=2 worker=3

stop

1
2
3
用法:stop [options] [SERVICE...]
选项:
-t, --timeout TIMEOUT 设置关闭容器的超时时间

停止容器而不移除,可以通docker-compose start重新启动。

QA

上面的doc并非本人撰写,但是我忘记在哪里看到并且下载到本地了,如有版权问题,请联系我补充更正,谢谢。

糟糕 玩cypress上瘾了

发表于 2019-03-01 | | 阅读次数:
字数统计: 428 | 阅读时长 ≈ 1

玩 e2e cypress 上瘾了,你们前端项目一般如何测试?

前言

换了 Mac pro 不知不觉更喜欢深夜敲代码了,真的香!!!不知不觉已经快凌晨 4 点了,我带着困意还是打算发个帖子和大家共享一下我这几天琢磨的一些事情。本人其实是后端,但由于公司的发展与需求,开始着手维护前端项目,也一直在看 react (大佬可以带带我嘻)为了确保业务 flow 能够 stabling,最近公司前端项目在测试环节上选用了 e2e 的 cypress,琢磨了一阵子,体验还是很好的,开箱即用。

体验

  • 开箱即用

  • 官方 doc 很多,利于开发与维护

  • gui 界面( env:google 浏览器),可边测边调整

  • 自定义 commands

  • 自定义 fixture,可 mock 数据

  • 支持 ci 运行测试,可上传到 bashBoard

  • 关注测试覆盖率( Chrome 的 coverage )

  • 截图功能,用例失败的场景节点会被截图保存,利于复现

  • 录屏功能,每个测试用例都会记录下来( MP4 )

  • 等等。。。

实例

饿了么首页为例:验证搜索一个商品,断言如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
it('输入搜索词,结果正确展示', () => {
cy.visit('https://h5.ele.me/')
// 点击跳转搜索页面
cy.get('.search').click()

cy.wait(200)
cy.get('input').type('麻辣烫')

cy.get('button').click()

// 目标页面地址包含 search 点击列表第一项
cy.wait(500)
cy.url().should('include', 'search')
cy.get('.shop').first().click()

// 跳转至商家详情页,找到购物车元素
cy.wait(500)
cy.get('.cartview')
})

[原文链接] https://zhuanlan.zhihu.com/p/32666685

1…345…8
BinZhi Zhu

BinZhi Zhu

纵使你脚下有一千名挑战者,那就把我算作第一千零一名。

36 日志
4 分类
28 标签
RSS
0%
© 2020 BinZhi Zhu
Copyright © 2018
|
Powered by Hexo | Theme by Next
载入天数...载入时分秒...