Skip to main content

nginx域名泛解析绑定子目录配置

· 2 min read

需求场景

如果需要实现demo演示站。当然不希望每个小项目都去配置域名解析,太麻烦。所以用到了域名泛解析。并且将域名前缀和目录名字对应,根据目录名字即可访问对应的域名,就减少了很多配置。

具体配置(php示例)

server {
listen 80;
server_name ~^(?<subdomain>.+).demo.urcloud.co$;
root /home/demos/$subdomain;
index index.html index.htm index.php;
fastcgi_intercept_errors on;
error_page 404 = /404.html;
location / {
# This is cool because no php is touched for static content.
# include the "?$args" part so non-default permalinks doesn't
# break when using query string
try_files $uri $uri/ =404;
}

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ .*\.php(\/.*)*$ {
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
include fastcgi.conf;
}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
location ~ /.ht {
deny all;
}
}

前端基础知识—block,inline,inline-block的区别

· 2 min read

前沿

一个html页面,是由多种html标签如div,p,a,img,input等构成。每个标签都是一个元素。除了flex和table,block,inline,inline-block是最为常用的显示方式。

block块状元素

块状元素最明显的特征就是会换行。多个块状元素会多行显示。块状元素可以设置宽高
(如div,header,article,section,footer,p)

inline内联元素

和块状元素相对应不会换行。多个内联元素会显示在同一行。内联元素不能设置宽高
(如a,span,i,b,strong,em)

inline-block内联块元素

是block和inline的折衷方案。其本质是inline,具有inline的不换行特点,但又具有block的可以设置宽高的特点。
(如img,input,textarea)

float和absolute,fixed

除了display属性会更改元素的显示方式,float和position也会更改元素的显示方式,而且优先级更高。float和absolute,fixed都会导致元素脱离文档流,不占有具体空间,元素都会变成类似inline-block的展现形式。

前端自动截取视频第一帧作为封面

· 3 min read

需求场景

现在的移动端播放器往往都是h5实现的,我们知道通过设置poster属性就可以设置视频封面,一种方式就是后台上传视频的时候同时上传封面,或者自动生成封面。这样后端同学的工作就相对多了,还有一种折衷的方案就是前端自动生成封面图。

基本原理

通过video的loadeddata事件,以及canvas绘制视频的第一帧,生成base64图片后赋值给video的poster属性。

核心代码

    function setPoster(video,scale) {
var scale = scale || 0.8
// 设置poster属性:(非本地视频资源会有跨域截图问题)
// video.setAttribute('crossOrigin', 'anonymous');//处理跨域
video.addEventListener('loadeddata', function (e) {
// 截取视频第一帧
var canvas = document.createElement('canvas');
canvas.width = video.videoWidth * scale;
canvas.height = video.videoHeight * scale;
canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
var src = canvas.toDataURL('image/png');
// 设置属性
video.setAttribute('poster', src);
});
};

演示地址

前端自动截取视频第一帧作为封面演示地址

异常情况

  1. ios下video标签必须加上autoplay,否则不会触发loadeddata事件。
  2. 如果在微信中测试,可以发现ios并不能生效,在safari浏览器却是可以的,原因和微信禁止了视频的默认播放有关。
  3. 还有一个缺点, 如果视频第一帧是黑屏,截图出来就会是黑的。

总结

总的来说,前端生成封面只能是一种临时解决方案。最好还是通过后端实现封面的上传和截图,最简单的可以调用七牛云等服务商的视频封面api。七牛云视频封面演示

http://cdn.urcloud.co/190318231014076505.mp4?vframe/jpg/offset/1

后端视频截图参考

ffmpeg视频截图

vue单页应用seo解决方案rendertron

· 4 min read

需求场景

现在越来越多的前端项目是基于vue,react,angular做的单页应用,可是单页应用的一大痛点就是seo不友好,虽然百度统计支持单页应用,但是seo不行呀。

可行解决方案

目前有三种解决方案。方案一预渲染,方案二服务端渲染,方案三针对seo的渲染。方案一和方案二都会原有项目进行改动,其中方案二改动方案最大。所以目前来说,改动成本最小的就是方案三了。本文采用的方式就是针对seo渲染的方案三。

rendora和rendertron

目前有rendora和rendertron两种主流开源方案,rendora是基于go语言的,支持docker部署。rendertron是由google团队基于node开发的,背靠大树。从目前的star数以及更新状况来看,rendertron要更好些。rendora已经一年多没有更新,并且安装过程中有些bug还无法解决。

rendertron原理

rendertron会启动一个node项目,对请求进行拦截,如果是搜索引擎发来的请求,就会被拦截,通过puppeteer渲染想要请求的地址,并将渲染好的html返回给搜索引擎,而普通用户的请求还是转发到对应的后端服务器上

环境技术栈

操作系统ubuntu18.04
前端vue
后端接口nestjs
服务器nginx
seo预渲染rendertron

步骤一:rendertron安装启动

git clone https://github.com/GoogleChrome/rendertron.git
cd rendertron
npm install
npm run build
npm run start

rendertron在启动过程中可能会报错,原因是puppeteer的环境没有安装完,需要参考puppeteer官方文档安装对应的包chrome-headless-doesnt-launch-on-unix
如果启动没有问题了,之后可以通过pm2加入后台进程

步骤二:配置nginx拦截搜索引擎

  location / {
if ($http_user_agent ~* "bot|bing|yandex|duckduckgo|baiduspider|googlebot|360spider|sogou spider") {
rewrite ^/(.*) /render/https://sz.urcloud.co/$1 break;
proxy_pass http://127.0.0.1:3001; #rendertron端口
}
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://127.0.0.1:3000; #后端api接口
}

步骤三:测试搜索引擎访问和普通用户访问

通过postman在请求header中添加User-Agent:baiduspider来测试蜘蛛访问和普通用户访问,如果正常的话,可以看到搜索引擎访问返回的是渲染好的html页面。

后续说明

可以看到这样改只是修改了nginx配置以及新增了一个rendertron项目,对原有项目没有任何改动,rendertron官方是有node,python等后端语言的插件的,通过nginx转发到后端,在后端项目里面判断是否搜索引擎来决定是否转发url到rendertron项目下。这样会更好,不过对原有项目做了一些小的调整,感兴趣的同学可以去研究一下。

腾讯云ubuntu使用root用户登录

· One min read

需求场景

腾讯开通的ubuntu主机,默认用户是ubuntu,并且这个ubuntu的权限还是相对比较低的,虽然提升了安全性,可是对于个人站长来说方便才是硬道理,自己也不会用root用户瞎操作。这个时候就需要用权限更大的root用户登录操作了。

步骤一:设置root密码

sudo passwd root回车设置两次密码即可

步骤二:修改ssh登录的配置

sudo vim /etc/ssh/sshd_config
找到文件的Authentication部分,将LoginGraceTime,PermitRootLogin,StrictModes前面的#号去掉。并且将PermitRootLogin的值改为yes

# Authentication:

LoginGraceTime 2m
PermitRootLogin yes
StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

步骤三:重启ssh

sudo service ssh restart
重启之后就可以用root用户登录啦

ubuntu安装mysql/mariadb,开启远程登录

· 3 min read

步骤一:安装mysql

apt install mysql-server
#apt install mariadb-server

安装完成后验证是否安装成功

netstat -tap | grep mysql

步骤二:数据库初始化

mysql_secure_installation

根据提示选择y或n

Securing the MySQL server deployment.
Connecting to MySQL using a blank password.
VALIDATE PASSWORD PLUGIN can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD plugin?
#要安装验证密码插件吗? 选择N
Please set the password for root here.
#输入要为root管理员设置的数据库密码
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.
# 删除匿名账户 选择Y
Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.
# 禁止root管理员从远程登录 选择Y
By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.
# 删除test数据库并取消对它的访问权限 选择Y
Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.
# 刷新授权表,让初始化后的设定立即生效 选择Y

操作完成后检查mysql安装状态

systemctl status mysql

步骤三:重启mysql/mariadb

systemctl restart mysql
#systemctl restart mariadb

关于远程登录:

在步骤二中我们关闭了允许root用户远程登录,推荐创建一个本地的拥有所有权限的管理员账号,再使用Navicat的ssh隧道功能实现远程登录。

创建用于远程登录的管理员账户

sudo mysql;
use mysql;
CREATE USER 'admin'@'localhost' IDENTIFIED BY 'strongpassword';
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost' WITH GRANT OPTION;
FLUSH PRIVILEGES;

nvm安装node太慢,更换淘宝镜像源

· One min read

需求场景

node的版本管理工具一般使用nvm,可nvm默认node镜像源是https://nodejs.org/dist,从默认的镜像缘源下载会很慢,所以可以通过更换镜像源加快下载。

linux、mac环境

  • 方案一:临时解决方案(每次安装替换成淘宝镜像源)
NVM_NODEJS_ORG_MIRROR=https://npm.taobao.org/mirrors/node nvm install stable
  • 方案二:linux环境下设置默认镜像源
    nvm的默认配置文件安装在~/.nvm目录下,找到nvm.sh修改NVM_NODEJS_ORG_MIRROR的默认参数即可。
  • 方案三:linux下设置永久环境变量
    ~/.bashrc文件中添加export NVM_NODEJS_ORG_MIRROR=https://npm.taobao.org/mirrors/node

windows环境

找到windows-nvm的安装目录,如果安装时没有修改默认地址则为C:\Users\Administrator\AppData\Roaming\nvm,在settings.txt中增加软件源

node_mirror: https://npm.taobao.org/mirrors/node/
npm_mirror: https://npm.taobao.org/mirrors/npm/

前端css布局详解

· 4 min read

前言

css布局实际上是前端的入门教程,所谓的前端切图仔主要工作也就是在写 html,css布局。虽然css布局是前端的入门教程,可实际工作中可以发现,并没有几个人掌握了css布局的基本技巧,往往都是margin,padding一把梭搞定,写得慢不说还给之后维护的人看的懵逼。

主旨

本文旨在帮助前端基础不好的同学或一些需要写界面的后台朋友熟悉常规的css布局,能够又快又好的完成前端切图工作。另一方面,本文也可以作为css布局的速查笔记。

常规布局方式

实际上常用的css布局总结来说可以分为3类。两端对齐,等分,居中。基本上一个页面都可以拆分成这3种布局的组合方式。

两端对齐

  • 方式一:float(兼容性最好)
.clearfix:before,
.clearfix:after {
display: table;
content: '';
}
.clearfix:after {
clear: both;
}
.fl{
float:left;
}
.fr{
float:right;
}
 <div class="clearfix">
<div class="fl"></div>
<div class="fr"></div>
</div>
  • 方式二:flex(最简单)
.flex-justify {
display: flex;
align-items: center;
justify-content: space-between;
}
 <div class="flex-justify">
<div class="l"></div>
<div class="r"></div>
</div>

等分布局(兼容最好,可以多行)

  • 方式一:float
.clearfix:before,
.clearfix:after {
display: table;
content: '';
}
.clearfix:after {
clear: both;
}
.list-wrapper {
margin-left: -20px;(负的间距值)
}
.list-box{
float: left;
box-sizing:border-box;
width: 33.3333%; (100% / 等分个数)
margin-bottom: 20px;
padding-left: 20px;(间距值)
}
  <div class="list-wrapper clearfix">
<div class="list-box">
<div class="list"></div>
</div>
<div class="list-box">
<div class="list"></div>
</div>
<div class="list-box">
<div class="list"></div>
</div>
</div>
  • 方式二:flex(最简单,仅单行)
.flex-justify {
display: flex;
align-items: center;
}
.list{
width:33.3333%;(间距可以通过宽度控制)
}
<div class="flex-justify">
<div class="list"></div>
<div class="list"></div>
<div class="list"></div>
</div>

居中布局(涉及块状元素,内联元素,固定宽高,不定宽高)

  • 水平居中

text-align(内联元素)

 .text-center{
text-align: center;
}
.item{
display: inline-block;
}
  <div class="text-center">
<div class="item"></div>
</div>

margin(块状元素)

.item{
width:200px;
margin:0 auto;
}
<div class="item"></div>

position

.parent{
position: relative;
}
.child{
position: absolute;
left: 50%;
width: 200px;
margin-left: -100px; //(负宽度的一半)
}
 <div class="parent">
<div class="child"></div>
</div>

flex

.flex-h-center {
display: flex;
justify-content: center;
}
 <div class="flex-h-center">
<div class="child"></div>
</div>
  • 垂直居中
    1.vertical-align
 .parent{
height:200px;
background-color: green;
}
.parent:after{
display:inline-block;
width:0;
height:100%;
vertical-align:middle;
content:'';
}
.parent .child{
display:inline-block;
width: 200px;
vertical-align:middle;
}
 <div class="parent">
<div class="child"></div>
</div>

2.transform

.parent{
position: relative;
height: 200px;
}

.parent .child {
position: absolute;
left: 50%;
transform: translate(-50%, 0);
}
 <div class="parent">
<div class="child"></div>
</div>

3.position

.parent{
position: relative;
}
.child{
position: absolute;
top: 50%;
height: 200px;
margin-top: -100px;
}
<div class="parent">
<div class="child"></div>
</div>

4.flex

.flex-v-center {
display: flex;
align-items: center;
}
 <div class="flex-v-center">
<div class="child"></div>
</div>
  • 水平垂直居中
    1.position(固定宽高)
.parent{
position:relative;
}
.child{
position:absolute;
left:50%;
top:50%;
width:200px;
height:200px;
margin-left:-100px;
margin-top:-100px;
}
 <div class="parent">
<div class="child"></div>
</div>

2.flex(不定宽高)

.flex-center{
display: flex;
align-items: center;
}
<div class="flex-center">
<div class="child"></div>
</div>

3.transform(不定宽高)

.parent{
position:relative;
}
.child{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

sketch导出的svg上传iconfont显示空白?

· One min read

需求场景

越来越多的设计师开始使用 sketch 做设计,而不是 ai,奇怪的是 sketch 导出的 svg 居然不能上传 iconfont,这让前端工程师何以堪?iconfont 怎么说也是一大利器啊。

首先排除

有些设计师发的 svg 并不是矢量图,里面是一个 base64 的 img,所以这种是肯定上传不了 iconfont 的。

根本原因

sketch 导出的 svg 上传空白主要是因为 sketch 不支持描边路径

解决方案

在 ai 中打开 sketch 导出的 svg,菜单中选择对象-扩展,勾选描边填充,保存之后就可以上传 iconfont 啦

基于frp快速搭建内网穿透工具

· 5 min read

需求场景

在家办公时,往往需要同事看到本地服务器的效果。当然可以选择上传服务器的方式解决,当没有服务器,或者希望对方能直接访问本机时(传到服务器太麻烦,可能需配置环境),就需要内网穿透工具啦。还有一种情况就是微信公众号开发需要填写可访问的回调域名,这也可以通过内网穿透工具实现本地测试。网上有很多内网穿透工具,不过不是需要收费,就是需要注册限流等,免费的持续好用的真心没几个。如果自己有一台备案过的服务器,当然是自己搭建最好不过。

可选方式

现在比较常用的是基于ngork和frp两种方式,看了看star数和更新维护状态,后来决定使用frp。

简单介绍

frp基于go语言开发,包括服务端和客户端,服务端配置文件frps.ini,客户端配置文件frpc.ini。服务器端和客户端版本都必须是同一版本,作者并没有做兼容处理,否则可能无法生效。

开始搭建(服务端)

已经有大神做了一键安装脚本,参考https://github.com/MvsCode/frps-onekey
建议选择阿里云方式

wget https://code.aliyun.com/MvsCode/frps-onekey/raw/master/install-frps.sh -O ./install-frps.sh
chmod 700 ./install-frps.sh
./install-frps.sh install

该脚本自动安装go和frp,按照提示来安装即可.配置文件地址/usr/local/frps/frps.ini
因为需要多http客户端,所以需要做泛域名解析*.proxy.urcloud.co,之后就可以通过test1.proxy.urcloud.co,test2.proxy.urcloud.co等域名访问,frps.ini配置修改subdomain_host参数

subdomain_host = proxy.urcloud.co

常用命令/etc/init.d/frps {start|stop|restart|status|config|version}

开始搭建(客户端)

比较遗憾的是并没有多少文章介绍客户端的下载,都只提到了使用方式。(可是github下载真心慢啊),没有梯子的同学可以用http://gitd.cc/ 网站提供的github代下载服务,只要把frp github release页面对应版本的地址复制进去,如https://github.com/fatedier/frp/releases/download/v0.33.0/frp_0.33.0_windows_amd64.zip,生成链接后下载即可。注意需要选择和服务端安装的版本一致。frpc.ini配置参考如下

[common]
server_addr = xxx.xxx.xxx.xxx #服务端ip地址
server_port = 5443
token = xxxxx #frps.ini中的token
admin_addr = 127.0.0.1
admin_port = 6443 #客户端dashboard端口
admin_user = admin #客户端dashboard用户名
admin_pwd = admin #客户端dashboard密码
[web1]
type = http
local_port = 8080 #客户端服务器端口
subdomain = test1 #(服务端域名,泛域名解析)

type = http local_port = 8080 #客户端服务器端口 subdomain = test1 #(服务端域名,泛域名解析)

[web2]
type = http
local_port = 8081 #客户端服务器端口
subdomain = test2 #(服务端域名,泛域名解析)

type = http local_port = 8081 #客户端服务器端口 subdomain = test2 #(服务端域名,泛域名解析)

启动客户端./frpc -c frpc.ini之后,就可以通过test1.proxy.urcloud.co:8000(frps.ini 设置的vhost_port)访问本地的8080端口啦

ssh远程登录

[ssh]
type = tcp
local_port = 22
remote_port = 7000

如果需要远程登录家里的电脑或者树莓派,就需要配置ssh啦
frpc.ini文件配置好并设置好frpc客户端开机启动,就可以通过ssh root@ip -p 7000命令随时实现ssh远程登录啦

树莓派设置开机启动frpc客户端

参考systemctl设置开机启动,管理service

后续探索

本文暂未涉及https的使用。后续使用到会再更新。