作者归档:白宦成

关于 白宦成

独立开发者, 自由职业者, 写作者

text

HOWTO: 如何学习 Alpine.js

什么是 Alpine.js

Alpine.js 是由开发者 Caleb Porzio 开发的一款响应式前端框架。和过去人们所熟悉的 Vue.js、React、Angular 不同的是,Alpine.js 不需要你对于现有的应用进行高成本的改造,也没有 VDom 的概念,直接可以在现有的系统中加入并使用

快速学习指南

Alpine.js 在国内的使用并不多,因此,相应的学习内容大多是英文写就的,不过 Alpine.js 涉及到的概念不会像 Vue、React 之类那么多,你可以很轻松学会它。

推荐学习路线

Alpine.js 没有那么多的概念,因此,学习路线也非常简单,你只需要掌握以下一些内容就可以了

  1. Alpine.js 基础语法和使用;
  2. Alpine.js 的magic helper; (非必需)
  3. Alpines.js 的状态管理工具 Spruce(非必需)

基础语法的了解可以让你使用 Alpine.js 开发自己的应用。而后面两者可以简化你的整个开发工作流,提升自己的开发效率。

推荐学习文档

1. 查阅官方文档,学习基础语法

学习 Alpine.js ,首先离不开的是官方文档,Alpine.js 的官方文档在其项目主页

https://github.com/alpinejs/alpine

如果你的英语不够好,可以看中文版本的 Readme

https://github.com/alpinejs/alpine/blob/master/README.zh-TW.md

具体的语法层面,我建议你按照如下的逻辑来学习

第一梯队,学习:

  • x-data:教你如何组织你的 Alpine.js 代码
  • x-on:事件绑定
  • x-if:逻辑处理
  • x-for:列表渲染
  • x-bind:数据绑定
  • x-model:双向数据绑定

这六个语法让你可以基本开始使用 Alpine.js。

第二梯队,学习:

  • x-show:控制是否显示
  • x-spread:将 Alpine.js 对象属性绑定到 Object 上
  • x-text:控制元素内文字
  • x-html:控制元素内 Html
  • x-transition:控制转场渐变动画

这五个语法让你的 Alpine.js 项目拥有更多的功能

第三梯队,学习:

  • x-cloak:控制组件初始化完成
  • x-ref:绑定父组件对象
  • $el:获取元素
  • $refs:获取父组件对象中标注的 x-ref
  • $event:事件对象
  • $dispatch:触发事件
  • $nextTick:下次 DOM 更新
  • $watch:监听数据变化

上述这些语法可以让你更加深入的使用 Alpine.js,不过在很多场景下可能你都用不到,所以也无需担心。

2. 查看常用逻辑的实现方式,比对不同

Hugo 是 Alpine.js 的开发团队成员之一,除了开发以外,Hugo 还在自己的网站上给出了一个 Playground ,你可以在这里看到一些 Alpine.js 的常见用例,比如:数据绑定、 for 循环、抓取数据等。

c7gdc

你可以访问 https://alpinejs.codewithhugo.com/ 来查看 Hugo 准备的一些案例,从而快速的了解你熟悉的功能在 Alpine.js 中的应该如何实现。

3. 在线练习 Alpine.js

当你了解了一些基本的使用后,你就可以开始打开一个网页,开始自己练习使用了。

这里有两个可以在线使用的调试环境,你可以基于他们来进行练习,直接看到效果。

Alpine.js 作为一个工具,需要多练才能熟悉它的使用,配合前面看的文档和案例,现在你就可以在这两个练习环境中练习 Alpine.js 的使用。

4. 查看真实项目,了解 Alpine.js

一个工具从测试到落地到真实环境,需要的是来自真实项目的参考。而 Awesome 中就提供了不少这样的案例。

n8o10

通过了解这些项目和工具,你可以看到别人是怎么使用 Alpine.js 的,从而学习 Alpine.js 的开发。

Alpine.js 的学习资源汇总

Alpine.js 的学习资源不多,但有一些比较适合国内开发者看的,我也再列举一下,具体如下:

视频教程

  • Building AlpineJS:由 Alpine.js 开发者 Caleb Porzio 开设在 Laracasts 上的一门课程,介绍如何从 0 打造一个 Alpine.js, 这个课程会让你对于 Alpine.js 更好更快的理解。

个人博客

  • Code With Hugo: Alpine.js 核心开发者的博客,会更新一些关于 Alpine.js 的技术文章
  • Alpine.js之一步一腳印:台湾同胞写的 Alpine.js 入门教程,有一个系列。完整的一共有30篇,可以一点点看看。

邮件列表

  • Alpine.js Weekly:Alpine.js Weekly 由 Alpine.js 的核心开发者 Hugo 维护,每周五发送一封邮件,介绍最新的 Alpine.js 社区的资源,十分值得订阅。

讨论区

一些常见问题

1. Alpine.js 依赖 Webpack / Alpine.js 不支持 Webpack?

答:并不是,Alpine.js 可以在 webpack 中使用,也可以不在 Webpack 中使用。即使通过 webpack 构建,Alpine.js 也会自动绑定对象,方便你使用。

2. Alpine.js 是为前端/后端设计的技术方案

答:Alpine.js 并不是为某一类人设计的技术方案。虽然在我看来,他对于后端十分友好,因为不需要 webpack 之类的前端构建工具就可以使用,但如果你是前端,且不太喜欢 React 的 JSX 或者是 Vue 的template ,那依然可以选择使用 Alpine.js。

3. Alpine.js 学习门槛如何?

Alpine.js 的学习只需要掌握一些核心的语法,就可以正式开始使用了。相比于 Vue、React, 我认为学习成本还是要低一些的。Vue 有完整的工具链,放平缓了学习曲线,但需要学习的概念依然不少,只是上手难度低而已。

我自己的使用感受

Alpine.js 在我看来,是对于后端开发者的利器。他的语法足够简单, 也不需要打包,因此对于后端开发者来说,可以十分方便的在系统中接入。同时,Alpine.js 可以很好的与传统的服务端渲染的逻辑结合,使用服务端渲染内容,使用 Alpine.js 来控制内容,从而可以很好的完成页面的构建,实现在不过多提升项目复杂度的同时,提升了页面的动态效果和逻辑编写难度,对于后端开发者来说,是一个不错的工具。

对于前端开发者来说,如果你厌恶了每次写项目都需要构建、打包,那么 Alpine.js 也是一个不错的选择。

white paper plane on white background

开了一个 HOW-TO 目录

HOW-TO 类目主要会介绍一些我自己熟悉/经常使用的技术栈,并将这些技术栈的学习路径等,整理出来,提供给需要的人。

HOW-TO 子目录放置在“技术“目录目录下,所以内容大体上是和技术有关的。如果有一些别的内容,可能也会分享出来。

比如我自己倒腾的一些硬件产品之类的。

purple and blue light digital wallpaper

屏蔽爬虫请求的四种方式

在进行应用开发的过程中,难免会遇见爬虫爬取数据的。正常情况下,爬虫的数据爬取不应影响业务系统的正常运行。但毕竟都是人写的代码,难免会出现 Bug ,在 Bug 的情况下,爬虫可能会对业务系统发起超出日常水平的请求,从而使业务系统开始出现故障。在这种情况下,就需要对爬虫进行屏蔽。

屏蔽爬虫,由内而外,可以分为四个不同的方式来屏蔽。

1. 屏蔽 UA

爬虫一般而言,都会有特殊的 User Agent ,比如 Baiduspider 就是百度的爬虫;Googlebot 就是 Google 的爬虫。

在第一阶段,你可以针对 User Agent 进行屏蔽,这部分只需要在 HTTP Server 层面加入相应的屏蔽代码即可。

以最常用的反向代理服务器 Nginx 为例,你可以在站点的配置文件中添加如下代码来屏蔽百度和 Google 的爬虫访问。

if ($http_user_agent ~* "Baiduspider|Googlebot")
{
    return 403;
}
Code language: PHP (php)

上述这段代码可以实现在 Nginx 检测到访问者的 User Agent 包含特定的字符的时候,返回 403 报错,拒绝访问服务。

2. 在主机层面屏蔽 IP

除了针对 User Agent ,有些时候是特定的来源的 IP 疯狂的访问,那也可以考虑针对 IP 进行封禁。

考虑到这部分,最常见的是使用主机自带的防火墙机制,来屏蔽来自特定来源的 IP。以 Linux 为例,可以通过 iptables 来完成相应的功能。

在 Linux 下,输入如下命令,来添加 iptables 屏蔽

iptables -I INPUT -s 8.0.0.1 -j DROP
Code language: CSS (css)

上述命令,就可以在 iptables 中添加针对 8.0.0.1 的请求,所有来自 8.0.0.1 的请求都会被抛弃。

3. 在安全组层面屏蔽 IP

在如今的业务模式下,大家大多使用的是云服务器。如果你使用的是云服务器,则可以在用户的请求到达主机之前,直接在云服务商的内部网关层面直接丢弃。

你只需要在现有的安全组规则中新增一条屏蔽特定来源 IP 的规则,就可以实现在安全组层面上屏蔽特定的 IP。

ktz0r

4. 在 CDN 层面屏蔽 IP

现在我们的业务大多会使用 CDN 来完成数据的分发。在这种情况下,服务器获取到请求不是来自我们要屏蔽的 IP,因此,我们可以直接在 CDN 层面屏蔽掉爬虫的 IP。

现在的云服务商的 CDN 大多提供了 IP 白名单/黑名单的功能,你只需要将需要屏蔽的 IP 放在黑名单中,就可以实现在 CDN 层面屏蔽 IP。

qm1qk

总结

屏蔽爬虫的方式有多种多样,不过最为常见的主要就是这四种。当你找到了爬虫的特征,便可以很轻松的屏蔽它。

four women holding drinks while laughing together during daytime

两代人的交锋

我和我妈的关系一直都不太好。

她年少时便好强,一直到现在,始终好强,万事喜欢比一比。

我也好强,18岁前唯唯诺诺,18岁后独立便喜欢万事靠自己。

我们两个人一样好强,父亲去世后, 没有了中间的缓冲,我们争论的的时候,也会更加的激烈。由于身份的限制,我并不能说出一些很过分的话,我们的地位天然不对等,所以,基本上每次争论,我都会无奈的放弃。但放弃,并不意味着我会顺从她的选择。

在上一次争论中,她提出:既然你认为自己很能, 那你以后每个月给我打 5000 块钱。

今天,她很轻描淡写的说,你以后每个月给我打 4000 块钱,就当你交房贷了。我说,

我可以理解,钱是她仅有的控制我的方法。当年,她也试图用这样的方式来控制父亲。但,我和父亲不同的地方是我更加的自由,也比父亲更加的冷血。

我已经做好了每个月给她打 5000 的准备,她希望用这 5000 来控制我,我同样希望使用这 5000 来堵她的嘴。

对抗,自此正式开始。

programming language

一个小技巧,提升你用 TailwindCss 写代码的效率

TailwindCSS 是我目前比较喜欢使用的 CSS 框架,组件优先的设计思路可以让我更好的完成产品原型的建设。

而 TailWindCSS 的一个问题就是对于文档十分的依赖,你需要对比着文档来写样式,才能够写出自己想要的样式,比较麻烦。不过,最近写代码的时候,我发现了一个好办法,可以很好的写出我们想要的样式。

这个办法就是,使用浏览器自带的 DevTools 中的「元素类」这个功能,来调试样式。

598n6

操作的路径也非常简单,打开浏览器的开发者工具,选择元素一栏,在其中找到你要调试的元素,并在右侧的属性列表中勾选开启元素类(.cls),你就可以在下方的样式元素类输入框中,输入关键词,来获取到当前页面支持的样式,从而可以查看不同的类会对组件产生的效果。

z8h13

通过这样的技巧,你可以很轻松的完成样式的选择。在完成调试后,只要把你需要的样式写入到组件内,就可以将你调试好的样式固化到你的代码中,从而完成你的工作。

总结

借助浏览器自带的元素类功能,你可以很轻松的完成基于 TaildwindCss 的样式编写。

summary

2021 年 1 月月度总结

TLDR

这篇是 2021 年的第一篇月度总结,但写的很潦草,可能是因为整个一月份我都过的非常随意,每天醒了就上网,困了就睡觉。感觉这个状态有点问题。

下个月需要让自己忙起来。

定性分析

学习成长

本月没有太多显性的成长,不过本月去了一次上海,和即刻的产品经理 kyth 聊了一些,收获颇丰。

恋爱家庭

一切正常,没有变化。

职业发展

对于顾问的理解更加深刻,也更加自由。

理财投资

财务情况在不断恶化,在思考解决之道。这个月出现了收支不平衡。本月收入 9K,但支出还是不低,达到了16K。

主要问题是本月出去旅游了几天,旅游还是有一些开销的,再加上给一些常用的 软件续费,所以开支不小。

休闲放松

这个月出去旅游了,前往杭州 & 横店,和很久没见过面的妙正灰一起吃饭聊天。

杭州还不错,去了很多次,没有惊喜,但也没有失望。不过说起来,杭州的路好像比我16年实习的时候体验的更好,五年过去了,路也越修越好了。

社交人际

本月去上海,认识了 kyth、zac,有收获。

自我实现

本月在自我实现方面,没有太多新的进展。有点乐不思蜀了。

定量分析

本月内容输出总结

本月公众号几乎达到了日更。之所以说是几乎,是中间有几天没有写。但总的来说,本月博客写的量还是不错的,写了32篇文章。

点击归档去查看我的文章

本月收支总结

wtk2z

本月读书总结

本月读书 5 本,具体信息如下:

  • 《小岛区块链》
  • 《这就是软件工程师》
  • 《Unix 传奇:历史与回忆》
  • 《男人这东西》
  • 人类群星闪耀时(当改变命运的时刻降临,犹豫就会败北!易中天、冯唐推荐译本)(果麦经典)

本月学习总结

本月学习了 0 门课程,无进展

本月娱乐总结

本月看电影 7 部,影评如下:

年度回顾

  • Linux 中国的改造计划:0/2
  • 海外收入计划进度:0/$1000
  • 减肥计划:210/170
  • 优质文章产出:1/50
  • 1W stars 项目:0/10000
  • 年入 5000 的项目:0/5000
  • 收入结余:0/25K

building photography

Serverless 不是银弹

这张图相信大家在互联网上或多或少都看过,说的很显示,如果你想要好且快的东西,那就是一分钱一分货。如果你想要快且便宜的东西,那必然会变得丑一些。

图源:Facebook劍心日劇廣告娛樂情報

作为互联网从业者,一个打工人,相信我的读者们都能够想明白这个点。

不过,大家似乎在看待别人的产品,特别是一些大厂的产品时,并不能够认清这个事实

产品方出于产品推广和运营的需要,必然会在产品推广和实际介绍的时候,宣称自己可以做任何东西。但作为真正使用的用户,你必须明确的知道,任何产品都具有自己的问题,没有一个产品可以满足你的所有诉求

我们以互联网产业中最为常见的问题来说,现在大型厂商一般都会推出自己的传统主机计算业务和 Serverless 云服务。

主机计算服务可以提供独立的主机给你使用,但相应带来的问题是你需要自己构建一整套基础环境,并进行基础的环境运维。

Serverless 服务则可以为你提供更高的弹性和更简单的环境配置,但相应的,也会带来更高的价格。 Serverless 服务在实际使用过程中,同等业务量的售价是会更高的。

你们一定要清楚不同的技术的优势和劣势。如果一个技术只有优势没有劣势,那他只能是个骗子了。

当你搞清楚技术的优势和劣势以后,反而你会对于技术的使用更加的得心应手。你不会在一个可能很大的项目中使用很低廉的技术方案。也不会在一个长期小而美的技术中,应用一整套互联网架构。

每一个产品都有自己的优势和劣势,你理解了优势和劣势,再根据实际情况选择方案,才能够不给自己挖坑,不给自己的长期运转留问题。

6ee6df690137fd06bc6166adb63caca1

微信生态中的 openId、unionID和业务系统中的ID

在进行微信生态相关的开发的时候,经常会遇到一个术语:openID。openID 在微信生态下几乎无处不在:

  • 你想要识别用户身份?需要 openID
  • 你需要给用户推送消息?需要 openID

除了 openID 以外,在开发时,还会有另外一个术语:unionID,当你思考多个微信生态下的应用互相协作之时,就会遇到 unionID。

此外,我们自己开发的业务系统中,还会有一个自己业务系统中的 ID,那如何理解这三个 ID 呢?

业务系统中的 ID

一般来说,我们会在自己的业务系统中存储一份用户信息,在存储用户信息的时候,用户信息会在数据库中有一个名为 ID 的主键,后续我们在进行各项开发的时候,都会使用这个 ID 来指代对应的用户。从而在开发过程中,随时可以获取到用户的一些信息。

我们会在这个 ID 对应的数据库记录中存储一些用户的数据,比如用户名、用户的头像、用户的昵称、用户的备注等等。

openID 微信应用中的用户唯一 ID

openID 是微信应用中的唯一 ID, 这里的微信应用指的是微信生态下的应用,不仅仅是小程序,也表示公众号、小商店等应用。

每一个用户在访问了某一个小程序后,就会获得自己在这个小程序中的唯一 ID。这个唯一 ID 和两个因素有关:是哪个小程序?是哪个用户?

也正是因为这两个因素,导致同一个用户在不同的小程序中的 openID 不同,所以说,openID 是微信应用中的用户唯一 ID,也仅在这个场景中有用。你在小程序拿到一个用户的 openID,意味着它只能在这个小程序中用于定位某个用户,你把这个 openID 拿到另外一个小程序/公众号中去使用,就无法定位到当前的用户。

unionID 微信应用群中的用户唯一 ID

微信生态下除了小程序,还有订阅号、服务号。你肯定希望自己的订阅号、服务号、小程序可以共用一套用户系统,这样用户在进入这三处地方,就可以获得一致的体验,比如订阅号的用户在进入小程序后,可以看到自己在订阅号中做过的事情。

这个时候,你就需要借助微信应用群中的用户唯一 ID —— unionID。

这里需要注意关键词「微信应用群」。你的公众号和你的小程序并不是天然成为一个微信应用群的。想要达成一个微信应用群,你需要在微信开放平台将你的公众号和小程序之间进行关联。在完成关联以后,微信就会在符合要求的情况下,给予每次请求赋予一个 unionID 的属性。

微信开放平台

具体的要求如下:

  1. 调用接口 wx.getUserInfo,从解密数据中获取 UnionID。注意本接口需要用户授权,请开发者妥善处理用户拒绝授权后的情况。
  2. 如果开发者帐号下存在同主体的公众号,并且该用户已经关注了该公众号。开发者可以直接通过 wx.login + code2Session 获取到该用户 UnionID,无须用户再次授权。
  3. 如果开发者帐号下存在同主体的公众号或移动应用,并且该用户已经授权登录过该公众号或移动应用。开发者也可以直接通过 wx.login + code2Session 获取到该用户 UnionID ,无须用户再次授权。
  4. 用户在小程序(暂不支持小游戏)中支付完成后,开发者可以直接通过getPaidUnionId接口获取该用户的 UnionID,无需用户授权。注意:本接口仅在用户支付完成后的5分钟内有效,请开发者妥善处理。
  5. 小程序端调用云函数时,如果开发者帐号下存在同主体的公众号,并且该用户已经关注了该公众号,可在云函数中通过 cloud.getWXContext 获取 UnionID。
  6. 小程序端调用云函数时,如果开发者帐号下存在同主体的公众号或移动应用,并且该用户已经授权登录过该公众号或移动应用,也可在云函数中通过 cloud.getWXContext 获取 UnionID。

如何使用 openID、unionID 和 ID

如果你希望你的业务可以实现,在 A 中的操作,可以在 B 中看到,那么你就需要借助于 unionID,将不同的用户关联起来,在数据库设计方面,你可以在用户表中设定几个属性: application_a_openid 、application_b_openid 和 unionid。

zezut

在执行查询的时候,判断是否存在对应 unionId 的用户,并进行关联。

smyjd

总结

微信开发生态中有不少的 ID,看似纷乱,但如果你可以把他们以某一个特定的场景来思考,就会更好理解。

6ee6df690137fd06bc6166adb63caca1

wxa.js 开启极致压缩

在之前的小程序性能优化系列中,我给出了如何分析文件大小和压缩图片的方式。但在一个项目中,如果我们已经完成了相关的文件压缩以后,还有没有办法进一步压缩呢?

答案是有的,你除了可以压缩图片以外,还可以选择压缩项目中的代码。

而这些部分,你可以借助一些工具来完成代码的压缩,其中包括:

  • uglifyjs: 压缩项目 JS 代码
  • html-minifier: 压缩项目 WXML 代码

在一个普通的小程序项目中,你需要自行编辑相关的依赖。而如果你使用的是 wxa.js,则可以使用官方提供的插件,十分简单的在你的项目中加入相关特性。

如何使用?

wxa.js官方提供了两个插件 @wxa/plugin-uglifyjs@wxa/plugin-minify-wxml, 只需要安装相关的插件,并在配置文件中引入,既可以在构建时加入代码压缩。

同时,为了方便,我们可以仅在进行生产环境构建的时候,从而实现开发的时候可以方便调试。

配置方法

首先,执行命令安装插件

npm i -D @wxa/plugin-minify-wxml
npm i -D @wxa/plugin-uglifyjs
Code language: CSS (css)

其次,在 wxa.config.js 中添加配置项目

const UglifyjsPlugin = require('@wxa/plugin-uglifyjs');
const MinifyWxmlPlugin = require('@wxa/plugin-minify-wxml');
const prod = process.env.NODE_ENV === 'production';
// 其他配置代码
if (prod) {
    module.exports.plugins.push(new UglifyjsPlugin());
    module.exports.plugins.push(new MinifyWxmlPlugin());
}
Code language: JavaScript (javascript)

这样,就可以限制在仅在编译生产环境代码时,对代码执行压缩。缩小项目体积。

6ee6df690137fd06bc6166adb63caca1

wxa.js 如何使用 replace 插件实现版本号的方便更新

小程序在开发过程中,如果可以在应用的某个地方加入版本号的显示,可以在后续 debug 的过程中,快速的定位代码的版本。但在过去的开发过程中,我大多是手动修改版本号,这在实际的使用过程中,经常会出现忘记修改版本号,或者代码中的版本号和实际在 git 中记录的版本号不同,给自己在后续排除错误的时候增加困难。

不过,如果你在使用 wxa.js 的话,可以借助于 wxa.js 的 replace 插件来简化这个过程,降低工作量。

实现思路

npm 项目在其 package.json 中是有一个 version 字段的,我们可以借助 npm 自带的 version 功能,来实现版本的自增,并自动打上 git 的 tag,简化开发工作。

具体实现

想要实现自动管理控制,你需要在你的 wxa 项目中安装其 replace 插件

npm i -S @wxa/plugin-replace
Code language: CSS (css)

安装完成插件后,在wxa.config.js中引入 package.json,并添加一个replace 规则对象。

const ReplacePlugin = require('@wxa/plugin-replace');
const package = require("./package.json")
module.exports = {
    plugins: [
        // 一个规则对象,key 为目标字符串,value 为替换内容
        new ReplacePlugin({
          list: {
            'VERSION': package.version
          }
        })
    ]
}
Code language: JavaScript (javascript)

添加完成配置后,你就可以在你的小程序中的任何需要展示项目版本号的位置,新增一个 VERSION 字符串。后续在小程序开发过程中,这个版本号就会被替换为 package.json 中的版本号。

在后续开发时,当你完成了一个版本的开发时,就可以使用 npm version 命令来发布新的版本。

npm version 命令常用的版本变更命令包括:

  • npm version patch : 变更 patch 版本号,比如 1.0.0 变为 1.0.1
  • npm version minor : 变更 minor 版本号,比如 1.0.0 变为 1.1.0
  • npm version major : 变更 major 版本号,比如 1.0.0 变为 2.0.0
  • 更多的命令可以访问 https://docs.npmjs.com/cli/v6/commands/npm-version 查看

执行了版本变更命令后,npm 会自动更新 package.json 中的版本号相关字段,并自动执行 commit & 执行 git tag 命令。

如果你需要自定义 git message ,可以在执行命令时,加入 -m 参数,npm 会自动把版本号传递给 %s 字符串从而实现自定义的版本变更,比如 npm version patch -m "Upgrade to %s for reasons"

总结

wxa.js 提供的 replace 插件,可以帮助我们在开发过程中,通过简单的文本替换来实现一些简化工作流的功能, 如果你在使用 wxa.js 开发,不妨试试这个小技巧。