分类 技术 下的文章

本系列基于前文《在 Fedora 上用 LaTex 和 TeXstudio 排版你的文档》和《LaTeX 基础》,本文即系列的第一部分,是关于 LaTeX 列表的。

列表类型

LaTeX 中的列表是封闭的环境,列表中的每个项目可以取一行文字到一个完整的段落。在 LaTeX 中有三种列表类型:

  • itemize 无序列表 unordered list / 项目符号列表 bullet list
  • enumerate 有序列表 ordered list
  • description 描述列表 descriptive list

创建列表

要创建一个列表,需要在每个项目前加上控制序列 \item,并在项目清单前后分别加上控制序列 \begin{<类型>}\end{<类型>}(将其中的<类型>` 替换为将要使用的列表类型),如下例:

itemize(无序列表)

\begin{itemize}
    \item Fedora
    \item Fedora Spin
    \item Fedora Silverblue
\end{itemize}

enumerate(有序列表)

\begin{enumerate}
    \item Fedora CoreOS
    \item Fedora Silverblue
    \item Fedora Spin
\end{enumerate}

description(描述列表)

\begin{description}
    \item[Fedora 6] Code name Zod
    \item[Fedora 8] Code name Werewolf
\end{description}

列表项目间距

可以通过在导言区加入 \usepackage{enumitem} 来自定义默认的间距,宏包 enumitem 启用了选项 noitemsep 和控制序列 \itemsep,可以在列表中使用它们,如下例所示:

使用选项 noitemsep

将选项 noitemsep 封闭在方括号内,并同下文所示放在控制序列 \begin 之后,该选项将移除默认的间距。

\begin{itemize}[noitemsep]
    \item Fedora
    \item Fedora Spin
    \item Fedora Silverblue
\end{itemize}

使用控制序列 \itemsep

控制序列 \itemsep 必须以一个数字作为后缀,用以表示列表项目之间应该有多少空间。

\begin{itemize} \itemsep0.75pt
    \item Fedora Silverblue
    \item Fedora CoreOS
\end{itemize}

嵌套列表

LaTeX 最多最多支持四层嵌套列表,如下例:

嵌套无序列表

\begin{itemize}[noitemsep]
    \item Fedora Versions
    \begin{itemize}
        \item Fedora 8
        \item Fedora 9
        \begin{itemize}
            \item Werewolf
            \item Sulphur
            \begin{itemize}
                \item 2007-05-31
                \item 2008-05-13
            \end{itemize}
        \end{itemize}
    \end{itemize}
    \item Fedora Spin
    \item Fedora Silverblue
\end{itemize}

嵌套有序列表

\begin{enumerate}[noitemsep]
    \item Fedora Versions
    \begin{enumerate}
        \item Fedora 8
        \item Fedora 9
        \begin{enumerate}
            \item Werewolf
            \item Sulphur
            \begin{enumerate}
                \item 2007-05-31
                \item 2008-05-13
            \end{enumerate}
        \end{enumerate}
    \end{enumerate}
    \item Fedora Spin
    \item Fedora Silverblue
\end{enumerate}

每种列表类型的列表样式名称

enumerate(有序列表)itemize(无序列表)
\alph* (小写字母)$\bullet$ (●)
\Alph* (大写字母)$\cdot$ (•)
\arabic* (阿拉伯数字)$\diamond$ (◇)
\roman* (小写罗马数字)$\ast$ (✲)
\Roman* (大写罗马数字)$\circ$ (○)
$-$ (-)

按嵌套深度划分的默认样式

嵌套深度enumerate(有序列表)itemize(无序列表)
1阿拉伯数字(●)
2小写字母(-)
3小写罗马数字(✲)
4大写字母(•)

设置列表样式

下面的例子列举了无序列表的不同样式。

% 无序列表样式
\begin{itemize}
    \item[$\ast$] Asterisk
    \item[$\diamond$] Diamond
    \item[$\circ$] Circle
    \item[$\cdot$] Period
    \item[$\bullet$] Bullet (default)
    \item[--] Dash
    \item[$-$] Another dash
\end{itemize}

有三种设置列表样式的方式,下面将按照优先级从高到低的顺序分别举例。

方式一:为各项目单独设置

将需要的样式名称封闭在方括号内,并放在控制序列 \item 之后,如下例:

% 方式一
\begin{itemize}
    \item[$\ast$] Asterisk
    \item[$\diamond$] Diamond
    \item[$\circ$] Circle
    \item[$\cdot$] period
    \item[$\bullet$] Bullet (default)
    \item[--] Dash
    \item[$-$] Another dash
\end{itemize}

方式二:为整个列表设置

将需要的样式名称以 label= 前缀并封闭在方括号内,放在控制序列 \begin 之后,如下例:

% 方式二
\begin{enumerate}[label=\Alph*.]
    \item Fedora 32
    \item Fedora 31
    \item Fedora 30
\end{enumerate}

方式三:为整个文档设置

该方式将改变整个文档的默认样式。使用 \renewcommand 来设置项目标签的值,下例分别为四个嵌套深度的项目标签设置了不同的样式。

% 方式三
\renewcommand{\labelitemi}{$\ast$}
\renewcommand{\labelitemii}{$\diamond$}
\renewcommand{\labelitemiii}{$\bullet$}
\renewcommand{\labelitemiv}{$-$}

总结

LaTeX 支持三种列表,而每种列表的风格和间距都是可以自定义的。在以后的文章中,我们将解释更多的 LaTeX 元素。

关于 LaTeX 列表的延伸阅读可以在这里找到:LaTeX List Structures


via: https://fedoramagazine.org/latex-typesetting-part-1/

作者:Earl Ramirez 选题:lujun9972 译者:rakino 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

平铺式窗口的特性吸引了很多人的追捧。也许是因为它很好看,也许是因为它能提高 Linux 快捷键 玩家的效率。又或者是因为使用不同寻常的平铺式窗口是一种新奇的挑战。

Tiling Windows in Linux | Image Source

从 i3 到 Sway,Linux 桌面拥有各种各样的平铺式窗口管理器。配置一个平铺式窗口管理器需要一个陡峭的学习曲线。

这就是为什么像 Regolith 桌面 这样的项目会存在,给你预先配置好的平铺桌面,让你可以更轻松地开始使用平铺窗口。

让我给你介绍一个类似的项目 —— Material Shell。它可以让你用上平铺式桌面,甚至比 Regolith 还简单。

Material Shell 扩展:将 GNOME 桌面转变成平铺式窗口管理器

Material Shell 是一个 GNOME 扩展,这就是它最好的地方。这意味着你不需要注销并登录其他桌面环境。你只需要启用或关闭这个扩展就可以自如的切换你的工作环境。

我会列出 Material Shell 的各种特性,但是也许视频更容易让你理解:

这个项目叫做 Material Shell 是因为它遵循 Material Design 原则。因此这个应用拥有一个美观的界面。这就是它最重要的一个特性。

直观的界面

Material Shell 添加了一个左侧面板,以便快速访问。在此面板上,你可以在底部找到系统托盘,在顶部找到搜索和工作区。

所有新打开的应用都会添加到当前工作区中。你也可以创建新的工作区并切换到该工作区,以将正在运行的应用分类。其实这就是工作区最初的意义。

在 Material Shell 中,每个工作区都可以显示为具有多个应用程序的行列,而不是包含多个应用程序的程序框。

平铺式窗口

在工作区中,你可以一直在顶部看到所有打开的应用程序。默认情况下,应用程序会像在 GNOME 桌面中那样铺满整个屏幕。你可以使用右上角的布局改变器来改变布局,将其分成两半、多列或多个应用网格。

这段视频一目了然的显示了以上所有功能:

固定布局和工作区

Material Shell 会记住你打开的工作区和窗口,这样你就不必重新组织你的布局。这是一个很好的特性,因为如果你对应用程序的位置有要求的话,它可以节省时间。

热建/快捷键

像任何平铺窗口管理器一样,你可以使用键盘快捷键在应用程序和工作区之间切换。

  • Super+W 切换到上个工作区;
  • Super+S 切换到下个工作区;
  • Super+A 切换到左边的窗口;
  • Super+D 切换到右边的窗口;
  • Super+1Super+2Super+0 切换到某个指定的工作区;
  • Super+Q 关闭当前窗口;
  • Super+[鼠标拖动] 移动窗口;
  • Super+Shift+A 将当前窗口左移;
  • Super+Shift+D 将当前窗口右移;
  • Super+Shift+W 将当前窗口移到上个工作区;
  • Super+Shift+S 将当前窗口移到下个工作区。

安装 Material Shell

警告!

对于大多数用户来说,平铺式窗口可能会导致混乱。你最好先熟悉如何使用 GNOME 扩展。如果你是 Linux 新手或者你害怕你的系统发生翻天覆地的变化,你应当避免使用这个扩展。

Material Shell 是一个 GNOME 扩展。所以,请 检查你的桌面环境,确保你运行的是 GNOME 3.34 或者更高的版本。

除此之外,我注意到在禁用 Material Shell 之后,它会导致 Firefox 的顶栏和 Ubuntu 的坞站消失。你可以在 GNOME 的“扩展”应用程序中禁用/启用 Ubuntu 的坞站扩展来使其变回原来的样子。我想这些问题也应该在系统重启后消失,虽然我没试过。

我希望你知道 如何使用 GNOME 扩展。最简单的办法就是 在浏览器中打开这个链接,安装 GNOME 扩展浏览器插件,然后启用 Material Shell 扩展即可。

如果你不喜欢这个扩展,你也可以在同样的链接中禁用它。或者在 GNOME 的“扩展”应用程序中禁用它。

用不用平铺式?

我使用多个电脑屏幕,我发现 Material Shell 不适用于多个屏幕的情况。这是开发者将来可以改进的地方。

除了这个毛病以外,Material Shell 是个让你开始使用平铺式窗口的好东西。如果你尝试了 Material Shell 并且喜欢它,请 在 GitHub 上给它一个星标或赞助它 来鼓励这个项目。

由于某些原因,平铺窗户越来越受欢迎。最近发布的 Pop OS 20.04 也增加了平铺窗口的功能。有一个类似的项目叫 PaperWM,也是这样做的。

但正如我前面提到的,平铺布局并不适合所有人,它可能会让很多人感到困惑。

你呢?你是喜欢平铺窗口还是喜欢经典的桌面布局?


via: https://itsfoss.com/material-shell/

作者:Abhishek Prakash 选题:lujun9972 译者:Chao-zhi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

我们已经了解到如何通过 GNU Screen 进行多会话管理。今天,我们将要领略另一个著名的管理会话的命令行实用工具 Tmux。类似 GNU Screen,Tmux 是一个帮助我们在单一终端窗口中创建多个会话,同一时间内同时运行多个应用程序或进程的终端复用工具。Tmux 自由、开源并且跨平台,支持 Linux、OpenBSD、FreeBSD、NetBSD 以及 Mac OS X。本文将讨论 Tmux 在 Linux 系统下的高频用法。

Linux 下安装 tmux

Tmux 可以在绝大多数的 Linux 官方仓库下获取。

在 Arch Linux 或它的变种系统下,执行下列命令来安装:

$ sudo pacman -S tmux

Debian、Ubuntu 或 Linux Mint:

$ sudo apt-get install tmux

Fedora:

$ sudo dnf install tmux

RHEL 和 CentOS:

$ sudo yum install tmux

SUSE/openSUSE:

$ sudo zypper install tmux

以上,我们已经完成 Tmux 的安装。之后我们继续看看一些 Tmux 示例。

Tmux 命令示例: 多会话管理

Tmux 默认所有命令的前置命令都是 Ctrl+b,使用前牢记这个快捷键即可。

注意Screen 的前置命令都是 Ctrl+a.

创建 Tmux 会话

在终端中运行如下命令创建 Tmux 会话并附着进入:

tmux

抑或,

tmux new

一旦进入 Tmux 会话,你将看到一个 沉在底部的绿色的边栏,如下图所示。

创建 Tmux 会话

这个绿色的边栏能很容易提示你当前是否身处 Tmux 会话当中。

退出 Tmux 会话

退出当前 Tmux 会话仅需要使用 Ctrl+bd。无需同时触发这两个快捷键,依次按下 Ctrl+bd 即可。

退出当前会话后,你将能看到如下输出:

[detached (from session 0)]

创建有名会话

如果使用多个会话,你很可能会混淆运行在多个会话中的应用程序。这种情况下,我们需要会话并赋予名称。譬如需要 web 相关服务的会话,就创建一个名称为 “webserver”(或任意一个其他名称) 的 Tmux 会话。

tmux new -s webserver

这里是新的 Tmux 有名会话:

拥有自定义名称的 Tmux 会话

如你所见上述截图,这个 Tmux 会话的名称已经被标注为 “webserver”。如此,你可以在多个会话中,轻易的区分应用程序的所在。

退出会话,轻按 Ctrl+bd

查看 Tmux 会话清单

查看 Tmux 会话清单,执行:

tmux ls

示例输出:

列出 Tmux 会话

如你所见,我们开启了两个 Tmux 会话。

创建非附着会话

有时候,你可能想要简单创建会话,但是并不想自动切入该会话。

创建一个非附着会话,并赋予名称 “ostechnix”,运行:

tmux new -s ostechnix -d

上述命令将会创建一个名为 “ostechnix” 的会话,但是并不会附着进入。

你可以通过使用 tmux ls 命令验证:

创建非附着会话

附着进入 Tmux 会话

通过如下命令,你可以附着进入最后一个被创建的会话:

tmux attach

抑或,

tmux a

如果你想附着进入任意一个指定的有名会话,譬如 “ostechnix”,运行:

tmux attach -t ostechnix

或者,简写为:

tmux a -t ostechnix

关闭 Tmux 会话

当你完成或者不再需要 Tmux 会话,你可以通过如下命令关闭:

tmux kill-session -t ostechnix

当身处该会话时,使用 Ctrl+b 以及 x。点击 y 来关闭会话。

可以通过 tmux ls 命令验证。

关闭所有 Tmux 服务下的所有会话,运行:

tmux kill-server

谨慎!这将终止所有 Tmux 会话,并不会产生任何警告,即便会话存在运行中的任务。

如果不存在活跃的 Tmux 会话,将看到如下输出:

$ tmux ls
no server running on /tmp/tmux-1000/default

切割 Tmux 窗口

切割窗口成多个小窗口,在 Tmux 中,这个叫做 “Tmux 窗格”。每个窗格中可以同时运行不同的程序,并同时与所有的窗格进行交互。每个窗格可以在不影响其他窗格的前提下可以调整大小、移动位置和控制关闭。我们可以以水平、垂直或者二者混合的方式切割屏幕。

水平切割窗格

欲水平切割窗格,使用 Ctrl+b"(半个双引号)。

水平切割 Tmux 窗格

可以使用组合键进一步切割面板。

垂直切割窗格

垂直切割面板,使用 Ctrl+b%

垂直切割 Tmux 窗格

水平、垂直混合切割窗格

我们也可以同时采用水平和垂直的方案切割窗格。看看如下截图:

切割 Tmux 窗格

首先,我通过 Ctrl+b " 水平切割,之后通过 Ctrl+b % 垂直切割下方的窗格。

如你所见,每个窗格下我运行了不同的程序。

切换窗格

通过 Ctrl+b 和方向键(上下左右)切换窗格。

发送命令给所有窗格

之前的案例中,我们在每个窗格中运行了三个不同命令。其实,也可以发送相同的命令给所有窗格。

为此,使用 Ctrl+b 然后键入如下命令,之后按下回车:

:setw synchronize-panes

现在在任意窗格中键入任何命令。你将看到相同命令影响了所有窗格。

交换窗格

使用 Ctrl+bo 交换窗格。

展示窗格号

使用 Ctrl+bq 展示窗格号。

终止窗格

要关闭窗格,直接键入 exit 并且按下回车键。或者,按下 Ctrl+bx。你会看到确认信息。按下 y 关闭窗格。

关闭窗格

放大和缩小 Tmux 窗格

我们可以将 Tmux 窗格放大到当前终端窗口的全尺寸,以获得更好的文本可视性,并查看更多的内容。当你需要更多的空间或专注于某个特定的任务时,这很有用。在完成该任务后,你可以将 Tmux 窗格缩小(取消放大)到其正常位置。更多详情请看以下链接。

自动启动 Tmux 会话

当通过 SSH 与远程系统工作时,在 Tmux 会话中运行一个长期运行的进程总是一个好的做法。因为,它可以防止你在网络连接突然中断时失去对运行进程的控制。避免这个问题的一个方法是自动启动 Tmux 会话。更多详情,请参考以下链接。

总结

这个阶段下,你已经获得了基本的 Tmux 技能来进行多会话管理,更多细节,参阅 man 页面。

$ man tmux

GNU Screen 和 Tmux 工具都能透过 SSH 很好的管理远程服务器。学习 Screen 和 Tmux 命令,像个行家一样,彻底通过这些工具管理远程服务器。


via: https://www.ostechnix.com/tmux-command-examples-to-manage-multiple-terminal-sessions/

作者:sk 选题:lujun9972 译者:chensanle 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在 Linux 中有两种运行 shell 脚本的方法。你可以使用:

bash script.sh

或者,你可以像这样执行 shell 脚本:

./script.sh

这可能很简单,但没太多解释。不要担心,我将使用示例来进行必要的解释,以便你能理解为什么在运行一个 shell 脚本时要使用给定的特定语法格式。

我将使用这一行 shell 脚本来使需要解释的事情变地尽可能简单:

abhishek@itsfoss:~/Scripts$ cat hello.sh

echo "Hello World!"

方法 1:通过将文件作为参数传递给 shell 以运行 shell 脚本

第一种方法涉及将脚本文件的名称作为参数传递给 shell 。

考虑到 bash 是默认 shell,你可以像这样运行一个脚本:

bash hello.sh

你知道这种方法的优点吗?你的脚本不需要执行权限。对于简单的任务非常方便快速。

在 Linux 中运行一个 Shell 脚本

如果你还不熟悉,我建议你 阅读我的 Linux 文件权限详细指南

记住,将其作为参数传递的需要是一个 shell 脚本。一个 shell 脚本是由命令组成的。如果你使用一个普通的文本文件,它将会抱怨错误的命令。

运行一个文本文件为脚本

在这种方法中,你要明确地具体指定你想使用 bash 作为脚本的解释器

shell 只是一个程序,并且 bash 只是 Shell 的一种实现。还有其它的 shell 程序,像 ksh 、zsh 等等。如果你安装有其它的 shell ,你也可以使用它们来代替 bash 。

例如,我已安装了 zsh ,并使用它来运行相同的脚本:

使用 Zsh 来执行 Shell 脚本

方法 2:通过具体指定 shell 脚本的路径来执行脚本

另外一种运行一个 shell 脚本的方法是通过提供它的路径。但是要这样做之前,你的文件必须是可执行的。否则,当你尝试执行脚本时,你将会得到 “权限被拒绝” 的错误。

因此,你首先需要确保你的脚本有可执行权限。你可以 使用 chmod 命令 来给予你自己脚本的这种权限,像这样:

chmod u+x script.sh

使你的脚本是可执行之后,你只需输入文件的名称及其绝对路径或相对路径。大多数情况下,你都在同一个目录中,因此你可以像这样使用它:

./script.sh

如果你与你的脚本不在同一个目录中,你可以具体指定脚本的绝对路径或相对路径:

在其它的目录中运行 Shell 脚本

在脚本前的这个 ./ 是非常重要的(当你与脚本在同一个目录中)。

为什么当你在同一个目录下,却不能使用脚本名称?这是因为你的 Linux 系统会在 PATH 环境变量中指定的几个目录中查找可执行的文件来运行。

这里是我的系统的 PATH 环境变量的值:

abhishek@itsfoss:~$ echo $PATH
/home/abhishek/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

这意味着在下面目录中具有可执行权限的任意文件都可以在系统的任何位置运行:

  • /home/abhishek/.local/bin
  • /usr/local/sbin
  • /usr/local/bin
  • /usr/sbin
  • /usr/bin
  • /sbin
  • /bin
  • /usr/games
  • /usr/local/games
  • /snap/bin

Linux 命令(像 lscat 等)的二进制文件或可执行文件都位于这些目录中的其中一个。这就是为什么你可以在你系统的任何位置通过使用命令的名称来运作这些命令的原因。看看,ls 命令就是位于 /usr/bin 目录中。

当你使用脚本而不具体指定其绝对路径或相对路径时,系统将不能在 PATH 环境变量中找到提及的脚本。

为什么大多数 shell 脚本在其头部包含 #! /bin/bash ?

记得我提过 shell 只是一个程序,并且有 shell 程序的不同实现。

当你使用 #! /bin/bash 时,你是具体指定 bash 作为解释器来运行脚本。如果你不这样做,并且以 ./script.sh 的方式运行一个脚本,它通常会在你正在运行的 shell 中运行。

有问题吗?可能会有。看看,大多数的 shell 语法是大多数种类的 shell 中通用的,但是有一些语法可能会有所不同。

例如,在 bash 和 zsh 中数组的行为是不同的。在 zsh 中,数组索引是从 1 开始的,而不是从 0 开始。

Bash Vs Zsh

使用 #! /bin/bash 来标识该脚本是 bash 脚本,并且应该使用 bash 作为脚本的解释器来运行,而不受在系统上正在使用的 shell 的影响。如果你使用 zsh 的特殊语法,你可以通过在脚本的第一行添加 #! /bin/zsh 的方式来标识其是 zsh 脚本。

#!/bin/bash 之间的空格是没有影响的。你也可以使用 #!/bin/bash

它有帮助吗?

我希望这篇文章能够增加你的 Linux 知识。如果你还有问题或建议,请留下评论。

专家用户可能依然会挑出我遗漏的东西。但这种初级题材的问题是,要找到信息的平衡点,避免细节过多或过少,并不容易。

如果你对学习 bash 脚本感兴趣,在我们专注于系统管理的网站 Linux Handbook 上,我们有一个 完整的 Bash 初学者系列 。如果你想要,你也可以 购买带有附加练习的电子书 ,以支持 Linux Handbook。


via: https://itsfoss.com/run-shell-script-linux/

作者:Abhishek Prakash 选题:lujun9972 译者:robsean 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这是 Python 之禅特别系列的一部分,重点是第十五和第十六条原则:现在与将来。

 title=

Python 一直在不断发展。Python 社区对特性请求的渴求是无止境的,对现状也总是不满意的。随着 Python 越来越流行,这门语言的变化会影响到更多的人。

确定什么时候该进行变化往往很难,但 Python 之禅 给你提供了指导。

现在有总比永远没有好 Now is better than never

总有一种诱惑,就是要等到事情完美才去做,虽然,它们永远没有完美的一天。当它们看起来已经“准备”得足够好了,那就大胆采取行动吧,去做出改变吧。无论如何,变化总是发生在某个现在:拖延的唯一作用就是把它移到未来的“现在”。

虽然将来总比现在好 Although never is often better than right now

然而,这并不意味着应该急于求成。从测试、文档、用户反馈等方面决定发布的标准。在变化就绪之前的“现在”,并不是一个好时机。

这不仅对 Python 这样的流行语言是个很好的经验,对你个人的小开源项目也是如此。


via: https://opensource.com/article/19/12/zen-python-timeliness

作者:Moshe Zadka 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

NESHouse 作为一个黑客松项目,相比于其他正式运行的项目,可能生命周期更短,也不会走入正式运营的阶段。不过,在我个人看来,这个项目的选型、设计等,还是有一些有意思的点,值得和大家分享。

1、 黑客松,要的就是快!

这几天前几篇文章发出去后,不断有一些开发者留言评论:这个项目使用的都是别人的服务,你的价值是什么?

NESHouse 作为一个黑客松项目,目的是在有限的时间内,从 0 到 1 将需求实现,在这个过程中,开发者需要去仔细评估自己所拥有的资源和要达成的目标,让资源和目标匹配,才能很好的完成自己的开发工作,达成自己本次黑客松的目标。

作为一个 Go 后端开发者,在这个项目中,我使用的是 LeanCloud 提供的云服务,而不是使用 gin 自己写一个 http 服务器,似乎不合常理,没有使用自己最熟悉的技术方案。但如果将资源和需求结合起来看,就会发现这个选择是很正常的。gin 固然熟悉,但我不熟悉的是前端,如果我将一部分时间安排在了后端的研发上,必然挤压我在前端开发的时间。

所以在 NEShouse 项目中,我选择了我比较熟悉,且开发时间周期最短的 Serverless 云服务 —— LeanClod 来完成我的后端工作量,这样我可以几乎不用在后端上花费时间和精力来完成工作。在音频服务上选择使用声网,而不是自己实现一套,原因也一致,我的预期是在 72 小时内完成这个项目的研发,而不是自己打造一套完整的实时音频系统。所以必然会选择更加好用,更加现成的解决方案,来简化我自己的工作。

此外,在这个项目中,有一个比较适合进行工作量评估的事情,便是我在项目中使用到了 LeanCloud 的 LiveQuery 的能力。LiveQuery 提供了实时数据同步的能力,使用 WebSocket 也可以实现相同的功能,不过,如何能又好又快,同时在 WebSocket 服务器上完成各种鉴权和扩展能力,是一个麻烦的事情。你可以用这个非常简单的功能,来评估假设你自己来完成所有的功能所需要耗费的时间。这样就可以理解为什么在这个项目中,我选择 LeanCloud 来完成工作。

2、浏览器兼容,你是真的坑!

在 NESHouse 的开发中,其实并没有花费太多的时间,倒是中间因为我回老家,花了不少时间在路上。实际上,在整个项目中,最为费心的,是各种浏览器之间的兼容问题。

基于浏览器的 NESHouse 和其他基于系统原生 API 的音频应用相比,一个很大的问题在于浏览器在处理音频设备上的不同。NESHouse 使用的音频接口是基于浏览器封装后一层的 API,而这个 API 处于考虑保护用户的考虑,在某些特定的场景下,会要求你先产生一些操作才能触发音频播放,所以针对不同的浏览器,你需要编写不同的适配代码,这些代码最终就会让你的代码变得又臭又长,存在大量的冗余代码。

比如说,在微信浏览器中,默认情况下你是无法听到 WebRTC 传回的音频的,需要用户在页面上进行点击,才能进行播放。

NESHouse 在实现这部分的逻辑时,采用的是判断如果用户使用的是微信浏览器,则会显示一个用户授权页面,让用户主动去点击,来完成音频播放的能力。

如果你希望以其他的方式来解决这个问题,那也可以参考 Agora 文档中的相关说明,来实现这部分能力:https://docs.agora.io/cn/Voice/autoplay_policy_web?platform=Web

3、Alpine.js,真香

作为一个后端开发者,对于前端的几大框架,也仅仅局限在可以用,可以写出我想要的功能的应用。但在具体的实现的时候,由于一些原因,我没有使用 Vue/React/Angular 之类的应用,再加上希望在黑客松中使用一些新的技术,于是我使用了 Alpine.js。

什么是 Alpine.js?Alpine.js 是一个在基础的 DOM 上实现了类似 Vue/React 的双向绑定的一个框架,使用 Alpine.js 和 Vue/React 的一个很大的不同点就在于,他可以让你在现有的 HTML 中非常轻松的实现双向绑定,而不需要重写整个代码。

举个例子来说,假设你想要在 Vue/React 中实现双向绑定,你需要将你的代码放在模板中或者转换为 JSX 来获取相应的双向绑定的能力。但在 Alpine.js 中,你需要做的仅仅是在你需要绑定的地方加入 x-model=xxx 来实现绑定,十分简单。

不仅如此,Alpine 也实现了大部分 Vue/React 之类应用实现的功能,比如 x-forx-onx-if 等常用的命令,在实际写逻辑的时候,我大量的应用了这些逻辑来完成我自己的工作,十分方便。

在 NESHouse 中,随处可见 Alpine.js 的应用:

Alpine.js 可以很轻松让一个不熟悉 Webpack 等前端构建工具的后端工程师,在自己的应用中实现双向绑定。对于后端工程师来说,这个工具你们不可错过。

总结

NESHouse 的技术栈相比于很多复杂的应用来说,十分的简单,仅仅是 Leancloud + Agora 就可以完成几乎所有功能,但我相信,这样的技术架构选型,对于一些不需要那么大计算量、没有那么高业务负载的项目而言,是有帮助的。就算你有屠龙技,又何需在杀鸡之时用它呢?