Squoosh 是 Google 推出的一个图片压缩工具。之前整理macOS 初始化设置 的时候就说过,基本上算是必不可少的一个压缩工具了。
如果要大批量压缩图片,之前也介绍过 jpegoptim 和 optipng。
如果要实现更加高阶的图片操作,比如 resize, blur, crop, despeckle, dither, drow on, flip, join, re-sample 等等,也可以了解一下 [[ImageMagick]]。
但使用 Squoosh 的过程中有一点不方便的就是 Google 只提供了在线版,之前也在 issue 中提过,官方回复是本来这个工具就是命令行的一个在线化,没有必要再搞一个离线的版本。
但最近发现 GitHub 上有人做出了一个离线版本的 Squoosh。
离线版本的 Squoosh 基于 Electron,并使用了 GoogleChromeLabs 之前开源的在线版。
这是 [[20220417-21 天计划]] 的第二本书,看过 [[何帆]] 翻译的很多本作品,这一本《大法官说了算:美国司法观察笔记》是何帆多年的司法观察记录。作者以[[苏特大法官]] 的辞职开始说起,先后介绍了大法官是如何产生的,最高法院内部是怎么运行的,网络时代的法庭,法院对言论自由的态度,对死刑的态度,等等角度对大法官展开了详细的描述,最后一章对现在美国的最高法院的每一位大法官做了单独的介绍。
个人感觉这是一本非常适合想要了解大法官,以及最高法院的读者,在书中可以对整个最高法院的历史,以及大法官为何一言九鼎有一个非常直观的认识。
如果读完钦佩于大法官的人格魅力,那么可以继续看[[九人-美国最高法院风云]],如果读完更关心最高法院是如何界定言论自由的,那么继续阅读 [[言论的边界 美国宪法第一修正案简史]] ,如果读完更醉心于案件的错综复杂以及大法官们抽丝剥茧梳理给出判决,那么可以再读[[美国宪政历程 影响美国的 25 个司法大案]]
当然如果不想读这些大部头作品,那么也有牛津通识读本中的 [[美国最高法院通识读本]],[[批评官员的尺度]] 等等作品可以继续。
或许看过美剧、韩剧律政剧的人,对那个蒙着眼睛、一手持剑,一手天平的正义女神不再陌生,我也曾在这些剧集中一次次被法官「正义」的判决所感染。然而稍微了解一下美国的司法史就可以看到在不同的历史时期司法的天平都不是绝对的公平。
美国的历史上存在《惩治煽动性言论法》,曾一度赋予了总统以无上的言论审查权;最高法院也会允许雇主不受任何限制的和劳工签订超长工作时间的合同,大法官们认为雇主有权利和劳工签订不受时间限制的合同;更甚至[[坦尼大法官]]在 1857 年的 [[斯科特案]] 判决中判定黑人不是美国公民,直接导致了南北战争。[[202011041258-最高法院历史上的污点]] 不是一两句话就可以说清楚的,但是正是因为司法只是三权分立中的一个分支,更甚至是一个在最初没有一点地位的分支,司法天平的倾斜甚至倾倒,可以用行政的立法的权力予以纠正。
林肯当上总统之后,用宪法第十四修正案推翻了最高法院关于黑人不是美国公民的判决,将倾斜的天平拨了回来。
而司法的存在也正是为了约束行政权力的过大,以及立法分支的肆意立法。大法官们手握[[司法审查权]],可以对立法分支涉嫌违宪的法律进行审查。正是这三个分支的相互制约才使得美国在过去 200 多年的历史中,一直在修修补补中度日,除了南北战争这一次严重的战争之外一直可以不断地进化。
这两天在 Twitter 刚好看到一则推文,提出一个问题,如果这三个分支都不再很好的执行自己的职责,司法分支不再对超越宪法的立法进行审查,而行政权力以更强硬的手段行政,那么该怎么办?最终给出的答案是美国的持枪自由。但是我们都知道非要走到那一步必然会导致更严重的问题,这也不是这一本书所讨论的问题了。
在最高法院的描述中,一直少不了「自由派」和「保守派」两派大法官的描述。但是,我们要知道,在这里「保守」绝不是一个贬义词,保守派大法官只是始终对宪法保持警惕之心,深怕任意解释宪法会破坏法治框架。而自由派大法官,并非不尊重宪法,只是他们认为一部「活的宪法」才能与时俱进,适应不断变幻的现实,体现制宪先贤的本意。他们会秉持「至善论」(Perfectionism)的观点,不断创制一些新权利,进而将该权利解释为宪法的应有之义。
保守的含义其实颇为多元,可能是对无孔不入的「大政府」的畏惧,可能是对上帝的虔诚信仰,可能是对种族、文化、性的审慎态度,很难以进步或落后加以评判。
美国是一个缺乏改革传统的国家,就像上面提到的那样,越是重大的变革,越是以润物细无声的渐进方式完成。最高法院当然能够推动社会变革,但是「大法官说了算」并不意味着判决是推动变革的主要途径。[[布朗案]]之后依然有百万的黑人儿童无法获得读书的机会。最高法院的判决并非只是权力的宣示,更是一种理想的表达,当权力和理念合二为一时,才能慢慢影响人们的观念,直至形成一种更为先进的文化。这些观念被大多数人接受的时候,就会演变成制度和法律。
无论最高法院如何判决,绝大多数人都会接受判决结果。这种信任建立在过去上百位大法官孜孜努力的基础之上。
在使用 LinuxServer 的 Docker 镜像的时候经常会需要设置 umask 值,这个值的具体作用一直不太清楚,正好整理一下。
在 Linux 或 Unix 操作系统中,所有的新文件都有默认权限的。umask
命令行允许用户设置文件的 creation mask, 这决定了新创建的文件或目录的权限。
预设的文件夹权限是:
0755 drwxr-xr-x
预设的文件权限是:
0644 -rw-r--r--
在 Linux 下创建目录或文件时有一个默认值,这个权限减去 umask 的权限就是新建的目录或文件的实际权限了。
这个配置会被 mkdir
, touch
, tee
等等一些命令使用。
在深入了解 umask 之前,首先再来解释一下 Linux 的权限模型。在 Linux 中,每一个文件都三个类别用户组:
每一个类别都有三个权限:
这使用用户可以决定哪些用户允许读、写、执行这个文件。
使用 ls -l dirname
来查看:
drwxr-xr-x 12 einverne users 4.0K Apr 8 20:51 dirname
|[-][-][-] [------] [---]
| | | | | |
| | | | | +-----------> Group
| | | | +-------------------> Owner
| | | +----------------------------> Others Permissions
| | +-------------------------------> Group Permissions
| +----------------------------------> Owner Permissions
+------------------------------------> File Type
第一个字幕表示文件的类型:
d
表示目录-
文件l
symbolic link之后的九位,每三位一组:
权限有两种表示方法:
字母 rwx
分别表示读(read),写(write),执行(execute),而 -
表示没有权限。
权限还可以使用数字来表示,r 可以使用 4 来表示, w 是 2,x 是 1。
比如 rwxr-xr-x
使用数字表示则是 755.
再回到 umask,在 Linux 系统中,默认的创建文件权限是 666,默认给 user, group, others 读和写的权限。目录的权限是 777。
umask
可以用来查看或改变新文件或目录的权限。umask
只会影响当前 shell 环境。在大部分的 Linux 发行版中,默认的系统级别的 umask value 一般在 pam_umask.so
或者 /etc/profile
中。
直接执行 umask
来查看输出,在我本机输出是 002
。
umask
值包含了新创建的文件或目录不拥有的权限。
上面提到过,默认的新文件的权限是 666
,如果 umask 值是 002
则,新创建的文件权限就是 666-002
结果是 664
。
用户也可以使用 umask -S
来查看 symbolic notation:
❯ umask -S
u=rwx,g=rwx,o=rx
在 /etc/profile
中可以设置 umask 值。比如不想要其他用户有任何权限,umask 就要设置为 027.
umask 027
在过去几年的时间里面,一直再寻求各种服务的 Self-hosted ,但唯独邮件服务器自建起来的步骤比较麻烦,但也不是不可能,甚至邮件服务器的 Self-hosted 方案更加全面。
下面这些邮件服务器架设方案是过去几年里面尝试和使用的。
其他一些方案:
我个人在首先尝试 Mailu ,学习基本的邮件服务器的协议必要的 DNS 配置之后,从 Mailu 切换长期使用 Mailcow。Mailcow 支持多用户,多域名配置,相对 Mailu 要重一些。所以如果是简单的轻度使用推荐 Mailu,Python 编写,Docker 镜像依赖简单,后台简洁。如果是重度使用,那么推荐 Mailcow,虽然镜像搭建稍微复杂,后台管理也稍微复杂一些,但是更强大。
Mailcow 是一个可以使用 Docker 容器化部署的邮件服务器。
GitHub: https://github.com/mailcow/mailcow-dockerized
Mailcow 相较于 Mailu 整体比较完整,功能相对比较丰富。
Mailcow 整体的搭建过程比较简单,如果之前搭建过 Mailu,实际上,参考官网的教程,并没有太多需要再强调的,甚至如果在同一台机器上,从 Mailu 上迁移过来,只需要修改 [[DKIM]] 记录即可。
提前的 DNS 设置可以参考官网。主要需要配置一些 A 记录,CNAME,[[DKIM]], [[SPF]],[[DMARC]] 等等。
配置 DNS
# Name Type Value
mail IN A 1.2.3.4
autodiscover IN CNAME mail.example.org. (your ${MAILCOW_HOSTNAME})
autoconfig IN CNAME mail.example.org. (your ${MAILCOW_HOSTNAME})
@ IN MX 10 mail.example.org. (your ${MAILCOW_HOSTNAME})
# Name Type Value
@ IN TXT v=spf1 mx a -all
安装:
git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
然后执行:
./generate_config.sh
交互命令中输入自己的 MAILCOW_HOSTNAME
,比如 mail.example.com
。
然后启动:
docker-compose pull
docker-compose up -d
然后使用配置好的域名 mail.example.com
登录,用户名 admin
密码 moohoo
。
编辑 mailcow.conf
然后配置 HTTP_BIND=
编辑 data/conf/nginx/redirect.conf
:
server {
root /web;
listen 80 default_server;
listen [::]:80 default_server;
include /etc/nginx/conf.d/server_name.active;
if ( $request_uri ~* "%0A|%0D" ) { return 403; }
location ^~ /.well-known/acme-challenge/ {
allow all;
default_type "text/plain";
}
location / {
return 301 https://$host$uri$is_args$args;
}
}
重启:
docker-compose up -d
docker-compose restart nginx-mailcow
进入后台之后,在 Configuration->Domains -> 添加域名。
添加域名之后需要修改域名的对应 DNS 记录。在界面会有显示。
添加完域名之后可以点击页面中的 Mailboxes 来添加域名邮箱来收发邮件。
Mailcow 使用 [[SOGo]] 作为默认的 Webmail 客户端。
几个常用的端口:
Service | Encryption | Port |
---|---|---|
IMAP | STARTTLS | 143 |
IMAPS | SSL | 993 |
POP3 | STARTTLS | 110 |
POP3S | SSL | 995 |
SMTP | STARTTLS | 587 |
SMTPS | SSL | 465 |
这是 [[20220417-21 天计划]] 中的第一本书,记录一下读书笔记。
这本书的作者是最高法院[[斯蒂芬-布雷耶大法官]],英文的标题是 Making our Democracy Work: A Judge’s View 可以看到这是布雷耶大法官多年的观察记录。
本书主要分为三个部分:
自上一次美国提名大法官开始,已经陆陆续续看过不少的关于最高法院,美国宪政历程,大法官的相关传记也看了不少,但是这一本由大法官主笔的著作依然让我看到了一些不一样的内容。
虽然那些经典的案例在其他著作中也曾经被一遍一遍的分析,但都是旁观者的视角,[[斯蒂芬-布雷耶大法官]]用全书的三分之一的篇幅列举了一个又一个经典案例来回答了一个问题,最高法院的信任是从何而来的。
可以看到的是最高法院从美国建国以来一步步走来并不顺利,也曾有过多次臭名昭著的判决,但是最高法院拥有[[司法审查权]],只要好好的利用这一个至上的权力,不过分迎合主流,为社会的少数群体发声,维护他们的权利,最高法院就可以一步一步慢慢地获得民众的信任。
而且可以看到的是,民众的权利也只有在最高法院,在宪法的保护下,才不会一步步被庞大的国家机器所侵犯,遇到不公和政府的权力扩张,可以随时通过最高法院去维护。
公民自由的要旨就在于,任何个人受到侵害,都有申请法律保护的权利
第二个与众不同的便是,在其他的著作中我们只能通过最后的判决以及判词来揣摩大法官的思考与想法,而这一部著作的第二部分,作者让我们窥探到了其判案的逻辑,以及内心的思考。
书中的第二部分更像是一个如何做法官的说明书,[[斯蒂芬-布雷耶大法官]]讲述大法官应该怎么做才能赢得并延续公众对大法官的信任。
布雷耶大法官总结了一套实用主义法律解释方法。
司法权的存在一方面是为少数族群争取应得的权利,另一方面是防止政府,国会权力的无限扩张,而这两者本身就不矛盾,政府权力的扩张一定会侵害到个体权利。
最高法院通过解释和裁判,尽职履责,促进宪法有效实施,从而赢得并延续公众对它的信任。
过分迎合主流政治势力的判决,会削弱甚至剥夺宪法对人民的保护,尤其是对非主流个人、群体的保护力度。[[德雷德·斯科特案]]
布雷耶认为,最高法院能实现制宪者心中切实可行的民主,推动宪法在实践中有效地运行。
[[比例原则]] 来平衡宪法价值观与实际利益诉求之间的冲突。
对三权分立感兴趣,想要了解最高法院,以及大法官的人。
公民自由的要旨就在于,任何个人受到侵害,都有申请法律保护的权利。
公众的信任,并非自动脱胎于成文宪法的存在。它必须经过构建、打造,而且一旦形成,就必须永久维持。
我们的社会,自由是一项基本标准”,未经审判的拘押“即使有例外,也必须给予严格限制”。“值此最具挑战与最不确定的时刻,我国对正当程序的承诺正经受遭受最严峻的考验;也正是在这个时候,我们也必须在自己的家园,守护那些我们在海外为之浴血奋战的原则”
制宪先贤们试图创造的民主政体,能够维护自由,有效运行,并垂范久远。他们也意识到,确有必要由一个机构来守护宪法创制的法律边界。
《积极自由》中指出,如果公众不积极参与美国的政治生活,宪法对创制民主政体的影响将微乎其微。同样,如果公众仅仅因为不喜欢对宪法的某种解释,就恣意置之不理,宪法对实现切实可行的宪政民主之影响,也将乏善可陈。
当本杰明·富兰克林被问及制宪会议创立了什么样的政府时,他给出了那句著名的回答:“一个共和国,夫人,如果你们能好好维系它的话。”由此带来的挑战是,如何令我们继承的民主宪法,始终处于切实可行的状态。
司法独立是一个国家的基本理念。但是,当苏共一名党委书记打电话给法官,告诉他某个案子该如何裁判时,司法独立将荡然无存——因为某些潜在的惩罚是不言自明的,这个法官可能再没有像样的住房,子女也可能不会再得到很好的教育。
早之前就对 Mastodon 有所耳闻,当时 Google+ 关闭的时候就想着自建一个 Mastodon 实例,但是一直因为没有服务器,也没抽出时间就耽搁了,期间一直在寻找一个比较合适的栖息地,但国内的豆瓣越来越封闭,动不动就删贴,Twitter 是进来使用比较多的社交媒体,但也并没有怎么深入的用,只是在上面关注了一些行业里面的大佬。最近正好 So you Start 服务器中的资源很有剩余,就尝试安装一下 Mastodon。
[[Mastodon]] 是一个开源的、分布式社交网络,他创立的目的就是用来代替 Twitter。和 Twitter 一样,用户可以 Follow 他人,也可以相互关注,用户可以发布消息、图片、视频等等。但是和 Twitter 不同的是,Mastodon 没有一个中心化的存储和内容审查。Mastodon 使用 [[ActivityPub]] 协议进行通信,任何实现了该协议的站点都可以同 Mastodon 实例进行通信。
Mastodon 由无数社区维护的服务器运行,用户在某一台服务器上注册的账号可以和其他网络节点进行通信,也可以跨节点交换数据。
先来看看成果:
欢迎来玩。
docker
和 docker-compose
本文使用 Docker + Nginx 的方式配置,使用 Docker 起服务,然后在宿主机上使用 Nginx 反向代理(因为 So you Start 这台机器之前就已经安装了 Nginx,否则的话会使用 Nginx-Proxy 或者 [[Nginx Proxy Manager]] 来直接管理 Docker 容器)。
因为 Docker Compose 的配置比较直观,我就直接放一个链接。
首先创建网络:
docker network create external_networks
docker network create internal_network
这里直接选用 [[PostgreSQL]] 作为数据库存储。
选择 Redis 作为缓存和队列。
Elasticsearch 是可选的组件,主要用来对内容做全文检索。
之后就是 tootsuite/mastodon
本体。
第一次安装需要先执行一个初始化的动作,将这部分内容另存为一个 docker-compose.init.yml
文件:
version: "3"
services:
web:
image: tootsuite/mastodon:v3.4.4
restart: always
environment:
- "RAILS_ENV=production"
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; tail -f /etc/hosts"
networks:
- mastodon_networks
networks:
mastodon_networks:
external: true
然后指定该文件
docker-compose -f docker-compose.init.yml run --rm web bundle exec rake mastodon: setup
在初始化的过程中会要求提供域名,数据库用户名密码,以及 SMTP 等等配置。按照提前准备的内容依次输入即可。然后就可以获得一份初始配置。记得从终端拷贝下来,并保存为 .env.production
。
然后再使用 docker-compose up -d
启动所有的容器。
在 Mastodon 的 GitHub 仓库中官方提供了 Nginx 配置文件模板 。
可以拉一下代码,然后直接拷贝使用。
git clone https://github.com/mastodon/mastodon.git
cd mastodon
sudo cp dist/nginx.conf /etc/nginx/sites-available/mastodon
sudo ln -s /etc/nginx/sites-available/mastodon /etc/nginx/sites-enabled/mastodon
然后修改配置文件中的 example.com
为自己的域名,然后记得将网站的 root 修改为自己服务器上的路径。
sudo /etc/init.d/nginx reload
等待 Nginx 加载文件之后,就可以访问域名,进入实例。
查看 Mastodon 实例的性能和日志,可以访问:https://domain.com/sidekiq [[Sidekiq]] 是一个 Ruby 的后台异步任务系统。
查看数据库的信息和查询效率,可以访问:https://domain.com/pghero
本文因为已经使用了 Nginx,所以直接使用 Nginx 做反向代理,如果你是一个台没有占用 80,443 端口的服务器,那么还可以直接使用 Nginx-Proxy,或者 Nginx Proxy Manager 来直接接管 Docker 容器。
修改 docker-compose.yml
文件中的版本,然后重启实例。
docker-compose run --rm web rails db:migrate
docker-compose run --rm web rails assets: precompile
修改 .env.production
中增加:
SINGLE_USER_MODE=true
然后重启服务。
使用 Certbot
sudo snap install core && sudo snap refresh core
sudo snap install --classic certbot
sudo certbot --nginx
00 0 * * 1 root docker exec mastodon_web_1 tootctl settings registrations approved >> /home/mastodon/log/mastodon/all.log 2>&1
00 0 * * 2 root docker exec mastodon_web_1 tootctl settings registrations close >> /home/mastodon/log/mastodon/all.log 2>&1
ES_ENABLED=true
ES_HOST=es
ES_PORT=9200
然后停止服务重新启动。然后在 https://domain.com/admin 中就能看到全文搜索已经启用了。
然后执行:
docker-compose run --rm web bin/tootctl search deploy
就可以建立索引。
网上大致看了一下,然后 docker-compose logs -f
看了一下日志,发现 ERROR:
web_1 | [9c1db729-7032-4c87-a85c-c38dc47380cf] Errno::EACCES (Permission denied @ dir_s_mkdir - /opt/mastodon/public/system/media_attachments):
可以看到权限不足,因为 Docker 部署,挂载到了本地的 ~/mastodon/public
目录下,所以:
sudo chown -R 991:991 ~/mastodon/public
同样也是上传文件的报错。但是这个错误发生在 sidekiq
中
docker-compose logs -f sidekiq
查看错误,发现:
sidekiq_1 | 2022-05-12T03:59:56.171Z pid=6 tid=2fmy WARN: Errno::ENOENT: No such file or directory @ rb_sysopen - /opt/mastodon/public/system/media_attachments/files/108/286/964/537/181/703/original/559172f05be085c3.jpeg
一查配置发现,Sidekiq 挂载的时候没有暴露其中最后一行。
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
- ~/mastodon/public/system:/mastodon/public/system
添加最后一行,重启即可。这个只能怪我太粗心了。
今天在 GitHub 上看到一个 repo,在其根目录中包含了一个 .husky
的文件夹,好奇之下就去搜索了以,于是发现了 husky 这个项目,这是一个使用 JavaScript 实现的用来管理 Git hooks 的工具。
GitHub: https://github.com/typicode/husky
首先要先了解一下 Git hooks,对于 git 已经是现代开发中必不可少的一个工具了,大家应该都比较熟悉,但是可能很多人在项目中并没有使用过 Git 的 hooks。
Git 的 hooks 允许用户在特定的时机执行用户自定义的脚本。
比如非常常见的,在提交之后自动对代码内容进行一些常规检查,如果失败则不允许提交等等。常用的 hook 有 pre-commit
, commit-msg
,pre-push
等。
Git hooks 是基于事件的,Scott Chacon 在 Pro Git 书中将 hooks 分成几个类型:
hook 列表:
hook 名称 | 触发命令 | 描述 | 参数个数描述 |
---|---|---|---|
applypatch-msg |
git am |
编辑 commit 时提交的 message,通常用于验证或纠正提交的信息以符合项目标准 | 包含预备提交信息的文件名 |
pre-applypath |
git am |
变更 commit 之前,如果以非 0 退出,会导致 uncommit 状态,用于 commit 之前的检查 | |
pre-applypath |
git am |
commit 完成提交之后,主要用于通知 | |
pre-commit |
git commit |
获取 commit message 之前,非 0 退出会取消本次 commit,检查 commit 自身,而不是 commit message | |
prepare-commit-msg |
git commit |
接收默认 commit message 之后,启动 commit message 编辑器之前。 | |
commit-msg |
git commit |
message 提交之后修改 message 的内容或退回不合格的 commit | |
post-commit |
git commit |
commit 完成之后调用,主要用于通知 | |
pre-rebase |
git rebase |
执行 rebase 时,可用于中断不想要的 rebase | |
post-checkout |
git checkout 和 git clone |
更新工作树后调用 checkout 时,或执行 git clone 后,主要用于验证环境、显示变更、配置环境 | |
post-merge |
git merge or git pull |
合并之后调用 | |
pre-push |
git push |
推送远程之前 | |
pre-receive |
远程 repo 进行 git-receive-pack |
远程 repo 更新刚被 push 的 ref 之前调用,非 0 会中断本次 | |
update |
远程 repo 进行 git-receive-pack |
远程 repo 每一次 ref 被 push 的时候调用 | |
post-receive |
远程 repo 进行 git-receive-pack |
远程 repo 所有的 ref 更新之后 | |
post-update |
git-receive-pack |
所有 ref 被 push 后执行一次 | |
pre-auto-gc |
git gc --auto |
用于在自动清理 repo 之前做一些检查 | |
post-rewrite |
git commit --amend 或 git rebase |
git 命令重写 rewrite 已经被 commit 的数据时调用 |
在 .git
这个隐藏的文件目录下,有一个 hooks/
文件夹,下面通常会有一些 sample 文件。如果要使其生效,去掉后缀 sample 即可
目录下的每一个文件都是可执行的文件,脚本通过文件名调用,内容的第一行必须有 Shebang #!
,引用正确的脚本解析器,比如 bash, perl, python, nodejs 等。Git hooks 使用的脚本语言是没有限制的。
比如在 pre-commit
中执行代码检查:
#!/bin/sh
npm run lint
# 获取上面脚本的退出码
exitCode="$?"
exit $exitCode
通过上面的简单了解也可能看到本地的 git hook
是保存在本地的 .git
文件夹中的,本地的 git hook
是不会被提交到版本控制中的。这就存在了一个问题,便是如何在项目中管理 Git hooks,这个时候就需要 Husky 登场了。
目前已经有非常多的项目在使用 husky
了,包括:
Husky 的原理就是在项目的根目录中使用一个配置文件,然后在安装 Husky 的时候把配置文件和 Git hook 关联起来,在团队之间共享。
安装:
npm install husky --save-dev
在项目中安装:
npx husky install
使用 Husky 之前确保安装了 npm
。
npm install husky -D
Husky 支持如下几种格式配置:
以 .huskyrc
为例:
{
"hooks": {
"pre-commit": "git restore -W -S dist examples/dist && eslint ."
}
}
这一个例子就是每次执行 git commit
之前把 dist
和 examples/dist
中的修改撤掉,不提交到仓库中,然后执行 EsLint。
Husky 做了两件事情:
~/.husky
目录husky install
时设置 ~/.husky
目录为 git hooks
目录。使用 husky add
:
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
npm uninstall husky
// 删除.husky文件夹,并且重置core.hooksPath
rm -rf .husky && git config --unset core.hooksPath
Husky 不支持服务端 hooks。
包括 pre-receive
、update
、post-receive
。
如果想跳过所有的 hooks,可以使用:
HUSKY_SKIP_HOOKS=1 git rebase ...
在 git 2.9 中引入了 core.hooksPath
配置,可以手动配置 git hooks
所在的目录。这也就使得我们可以在另外的目录中创建 Git hooks,然后手动设置 Hooks 目录来实现 hooks 脚本的同步。
tail 命令是一个日常查看日志非常常用的命令,用来在终端显示文件的最后部分内容。
tail 不加任何参数的情况下,默认显示文件最后 10 行内容。
tail /path/to/file.log
通常业务系统中以文件形式记录日志时会一直追加到文件末尾,可以使用 -f
来显示新追加的内容:
tail -f /path/to/file.log
tail -100 mail.log
tail -n 100 mail.log
tail -n +20 mail.log
tail -c 10 mail.log
Gatsby 是一个基于 [[React]] 的、免费开源的、用于搭建静态站点的框架。Gatsby 虽然是一个静态站点框架,但其数据却可以从任何地方获取之后渲染。 Gatsby 是基于 React 和 [[GraphQL]]。 结合了 webpack, babel, react-router 等前端领域中最先进的工具。 对开发人员来说开发体验非常好。
Gatsby 采用数据层和 UI 层分离的现代前端开发模式。静态 HTML 访问快,对 SEO 非常友好。
数据来源多样化: Headless CMS, markdown, API 等多种方式获取数据。
之前学习的时候建的券商推荐网站 就是使用 Gatsby 搭建。
/src/pages
目录下的组件会被生成同名页面/src/templates
目录下放渲染数据的模板组件,如渲染 Markdown 文章,在其它博客系统中一般叫 layout。/src/components
公共可复用的组件/static
静态资源, webpack 会跳过gatsby-config.js
配置
gatsby-node.js
可以调用 Gatsby node APIs
gatsby-browser.js
调用 Gatsby 浏览器 API作为 Gatsby 在本地管理资源的一种方式,作为一个数据库查询语言,它有非常完备的查询语句。
在 src/pages
下的页面可以直接 export
GraphQL 查询,在其它页面需要用 StaticQuery 组件或者 useStaticQuery hook。
在开发时默认的查询地址: http://localhost:8000
Gatsby 命令行:
npm install -g gatsby-cli
新建项目:
gatsby new gatsby-start
gatsby 默认会使用 gatsby-starter-default 来新建项目,你可以在后面加上其他 starter 的 GitHub 地址,来使用这个 starter 初始化项目。比如说:
gatsby new gatsby-start https://github.com/gatsbyjs/gatsby-starter-hello-world
启动项目:
cd gatsby-start
gatsby develop
# 或者
yarn develop
打开 localhost:8080 查看生成页面,可以打开 http://localhost:8000/__graphiql GraphiQL 调试界面。
几个常用的命令:
在 src/pages/
` 目录下,新建一个 JS 文件即可。在 src/pages/ 目录下的页面,Gatsby 会自动添加路由,生成页面。
新建 about.js
import React from 'react'
export default () => (
<div>
<h1>About</h1>
<p>location: </p>
</div>
)
访问 http://localhost:8000/about 即可查看。
在 Gatsby 中有三种类型的插件: 分别为数据源插件 ( source ), 数据转换插件 ( transformer ), 功能插件 ( plugin )
插件的命名是有规范的,数据源插件名称中必须包含 source,数据转换插件必须包含 transformer,功能插件名称必须包含 plugin。
所有插件的地址:https://www.gatsbyjs.org/plugins/
plugins 是一个数组,每一项都是一个插件,他支持字符串和对象两种类型,如果需要配置插件参数就是用对象,resolve 指明要配置什么插件,options 就是配置选项,name 表示资源类别,这个是自定义的这里写 json,path 是数据源文件路径。
modules.exports = {
plugins: [
{
resolve: "gatsby-source-filesystem",
options: {
name: "json",
path: `${__dirname}/data.json`
}
},
"gatsby-transformer-json"
]
}
gatsby-source-filesystem 他是用于将本地文件信息添加至数据层当中
第二个是 gatsby-plugin-sharp:他是用于提供本地图像的处理功能(调整图像尺寸, 压缩图像体积 等等) 第三个是 gatsby-transformer-sharp 是将 gatsby-plugin-sharp 插件处理后的图像信息添加到数据层。
最后我们要用到 gatsby-image,这是一个 React 组件, 优化图像显示, 他是基于 gatsby-transformer-sharp 插件转化后的数据。
安装:
npm install gatsby-plugin-image gatsby-plugin-sharp gatsby-source-filesystem
通过 YAML 加载数据
https://www.gatsbyjs.com/docs/how-to/sourcing-data/sourcing-from-json-or-yaml/
StaticImage
component is for static image sources, like a hard-coded file path or remote URL. In other words, the source for your image is always going to be the same every time the component renders.GatsbyImage
component is for dynamic image sources, like if the image source gets passed in as a prop.https://www.gatsbyjs.com/docs/tutorial/part-7/#whats-the-difference-between-gatsbyimage-and-staticimage
https://www.gingerdoc.com/tutorials/how-to-handle-images-with-graphql-and-the-gatsby-image-api
https://www.labnol.org/code/gatsby-images-200607
[[2018-03-24-netlify-to-host-static-website]]