分类目录归档:工程化

自定义 Bootstrap 5 的风格,实现自定义风格页面开发

和更加自定义化的 TailwindCSS 相比,Bootstrap 显然更具备主题和模板页面开发的潜力和更易于进行模板页面的开发 —— 毕竟各种样式都已经封装好了,你可以直接使用诸如 btn 来定义一个 Button。

我有在想,提供一个基于 TailwindCSS 的 StarterKit 来快速基于 TailwindCSS 开发出一套自己的样式库,但仔细想想,其实意义不大。因为可选项太多了,想要自定义化其实没那么容易。

白宦成

而在开发 Bootstrap 的时候,大家往往会遇到的一个问题的是 —— Bootstrap 开发出来的页面千篇一律,一千个人有一千个哈姆雷特,但一千个 Bootstrap 页面却长的一模一样。而这背后的原因,主要是因为大部分人使用的是标准版的 Bootstrap —— 也就是官方所定义的样式。大家都使用一样的样式,自然就使得开发出来的页面显得雷同。

不过,其实 Bootstrap 的风格自定义并不困难。

前情提要

其实大家不去做自定义风格开发的原因倒是可以理解 —— 锅都要给 Node Sass,在 Bootstrap 5 以前,Bootstrap 使用 Node Sass 来进行样式的构建,但 Node Sass 是一个基于 C++ 编写的拓展,这使得 Node Sass 的安装十分麻烦,加上特有的网络环境,使得 Node Sass 的安装十次有九次都是无法成功安装的,大家自然也不愿意使用 Node Sass 构建的项目(包括我自己,都会刻意选择使用 Less 构建的项目)。

不过,从 Bootstrap 5 开始,Bootstrap 项目开始使用 Dart Sass 进行样式风格的开发。这使得 Bootstrap 的构建不会像过去那么痛苦,因此也可以更好的进行风格的自定义。对于如今还在使用 Bootstrap 进行项目构建的同学来说,无疑是个好消息。

自定义 Bootstrap 5 的风格

关于如何在你的项目中引入 Boostrap 的 Sass 来满足自定义的需求,可以参考官方所给出的 Customize Sass 的说明,官方提供了包括 WebpackParcel 等的接入说明,如果你连基本的配置都懒得做,官方还提供了一个空白项目,方便你 Fork 后再修改。

以我自己使用的 Next.js 为例,配置起来也比较简单:

1. 安装相关依赖

在 Next.js 项目根目录安装所需依赖

yarn add bootstrap
yarn add -d sass sass-loader

2. 创建 Scss 文件

styles 目录下创建一个新的 globals.scss 文件,并在其中加入如下代码

// custom variables
@import "../node_modules/bootstrap/scss/bootstrap";
// custom css code 

其中 custom variables 的部分是让你用来加入自定义的变量的,比如自定义 Primary 的颜色、自定义 Padding 等一系列操作,都需要在 Bootstrap 的引入前定义,这样才能确保你的引入变量会生效。

而后面的 custome css code 则是可以用来定义一些你自己编写的,没有被覆盖在 Bootstrap 内部的类。

3. 在项目中引入创建好的 scss 文件

在项目的 pages/_app.js 引入我们刚刚创建好的 scss 文件,从而确保应用在启动的时候可以自动构建 Bootstrap ,并引入至项目中。

import '../styles/globals.css'
import '../styles/globals.scss' // 这一行是新增的
function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default MyApp

4. 在项目中使用 Bootstrap 类进行开发

当你完成上述的配置,就可以在自己的项目中引入相应的类来进行开发了。

一些小技巧

使用 Themestr.app 进行风格的快速设定

Themestr 是一个帮助你快速生成一套Bootstrap5自定义风格的工具网站。

在 Themestr 中,提供了 UI Builder、Themer 和 Customizer 三个不同的工具,其中:

UI Builder 提供了一个简单的 4 步选择器,让你定义了基本的颜色、字体、ICON 和 按钮风格,从而形成一套独特的 Bootstrap UI。

Themer 则提供了更加全面的样式的设定和预览功能,你可以在右侧的选择界面简单的配置样式,并在左侧自动刷新的页面中查看你的配置所实现出来的效果,方便你快速找到看到你的配置所能展现出的效果,简单且直观。

Customizer 则提供了全面的 Bootstrap 的变量,方便你快速找到你要修改的变量,并帮助你生成对应的 Sass 配置文件,方便你在此修改变量,并在本地进行开发。

对于不同的场景,Themestr 提供了不同的工具来帮助你快速开发,是一个非常不错的 Bootstrap 主题开发的辅助工具。

如何找到需要修改的变量

Bootstrap 在文档中针对每一个 Component 都提供了相应的 Sass Variables 的说明,你只需要在文档中找到你要修改的组件, 并在你自己的 global.scss 中修改对应的变量,就可以实现自定义。

如何找到特定类的源码

在进行 Bootstrap 开发的时候,如果有些类你找不到样式的时候,一个很好的方式是开启开发环境,并在开发环境中可以看到对应的 scss ,并在对应的 scss 当中,点击链接跳转到对应的 scss 定义,即可看到对应的样式的源码。

在跳转后,有些时候你发现似乎并不是直接定义的样式,比如下图,则说明这样的类是通过 map 来批量生成的,你就需要修改对应的 map 来完成自定义。

如何自定义主题颜色、字体大小、间距等批量生成的类

在 Bootstrap 中存在一些批量生成的类,比如 theme-colorfont-sizefont-weight 还有 paddingmargin 等等。

这些类是 Bootstrap 使用 @each 来生成的,而生成的依据,则是 Bootstrap 的各种 map 来完成的。因此,你想要进行定义,则需要修改对应的 Map。你可以使用 map-merge 来向 map 中添加新的选项

// Create your own map
$custom-colors: (
  "custom-color": #900
);

// Merge the maps
$theme-colors: map-merge($theme-colors, $custom-colors);

而如果你想要移除一个选项,则可以使用 map-remove 方法来完成

// Required
@import "../node_modules/bootstrap/scss/functions";
@import "../node_modules/bootstrap/scss/variables";
@import "../node_modules/bootstrap/scss/maps";
@import "../node_modules/bootstrap/scss/mixins";
@import "../node_modules/bootstrap/scss/root";

$theme-colors: map-remove($theme-colors, "info", "light", "dark");

// Optional
@import "../node_modules/bootstrap/scss/reboot";
@import "../node_modules/bootstrap/scss/type";
// etc

那些影响你前端开发体验的问题(1)

最近在研究和体验一些 GitHub 上的前端项目,遇到了一些让人体验不佳的点, 这里梳理一些我遇到的,一方面是留存,记录那些让我体验不好的事情。另一方面警示自己在开发前端项目的时候应该注意一下开发体验,确保不会让别人在开发的时候也遇到这些问题。

1. 项目应该有文档

这是不少 GitHub 上面项目的普遍问题。现有的文档要么是以 Framework 生成的 Readme 为主,要么直接没有文档。

但没有文档对于后来者的开发其实非常不友好,比如几个常见问题:

  1. 如何启动一个 Server & 如何设置后台 API 的 Prefix?
  2. 项目的组织结构是什么样的?
  3. 涉及到的第三方服务应该如何配置?

上面这些文档是帮助后来者快速使用你的项目所必需的(换句话说,如果你要做开源项目,想要打造开源社区,这也是必要的)。

2. 项目控制算法复杂度

我在开一些前端项目的时候,明显会感到浏览器的响应变慢了,我以为是我的 Mac Mini 2012 性能不行。但我打开自己的博客,依然如丝般顺滑,我就明白了。问题不在于我的电脑性能跟不上,而是这个前端页面加入了大量的有用或无用的代码,使得 CPU 需要大量的计算。

lanhu 的性能检测

虽然进入 SPA 的时代以后,我们开始将算力的使用从服务端往客户端转移,但也建议各位工程师控制自己项目的复杂度,不要一开网页,风扇就呼呼的转。浏览体验不好,还凸显自己的技术不行。

3. 使用 debuuger 调试,而不只是 console.log

在编译型语言当中,使用 Debugger 来进行调试是一项基本技能,因为需要在运行时去看不同的变量的值,以此来完成调试。

爆炸的 Console

但在前端领域,因为 console.log 的过于好用,大家开始习惯于使用 console.log 来打印变量,但对于大型项目来说,大量的 console.log 也会让你的项目输出许多无意义的内容,让整个项目的调试和开发受到阻碍。

总结

最近看项目,总结了三条自己觉得影响体验的点,后续随着看的项目的深入,会逐渐总结出更多影响体验的点,引以为鉴。

green and black digital device

使用 systemd 后台值守运行 Bark

什么是 Bark?

Bark 是由 Fin 开源的一个向 iOS 设备推送通知的服务,Bark 支持自行部署服务端,从而实现消息的推送通过自己的服务器进行,避免与官方的服务共享,提升推送时效。

服务端源码:Finb/bark-server: Backend of Bark (github.com)

客户端源码:Finb/Bark: Bark is an iOS App which allows you to push customed notifications to your iPhone (github.com)

Bark 如何部署?

Bark 的部署非常简单,直接下载官方的 release 文件即可。

下载完成后,你可以执行如下命令来进行测试

bark-server -addr 0.0.0.0:8080 -data ./bark-data

执行成功后,你会看到如下的界面,此时你可以访问 127.0.0.1/ping 来验证你的 Bark 的部署

使用 Systemd 进行值守

验证成功后,接下来就可以设定值守运行了

1. 将 bark server 移动到一个固定目录

首先,你需要将 bark server 移动到一个固定的目录,方便后续执行。

mv bark-server /usr/local/sbin/bark-server

2. 创建 Bark Service

创建 /etc/systemd/system/bark.service 文件,并添加如下内容

[Unit]
Description=Bark Server
[Service]
ExecStart=/usr/local/sbin/bark-server -addr 0.0.0.0:8080 -data /usr/local/bark-data
[Install]
WantedBy=multi-user.target

创建完成后,你可以执行 systemctl status bark 来查看 bark server 的状态。

然后,你就可以使用 systemctl 来控制bark 了

  • 启动服务 systemctl start bark
  • 停止服务 systemctl stop bark
  • 查看服务状态 systemctl status bark
black and white penguin toy

@action/checkout 如何抓取所有的历史记录

GitHub 的 Action Template 中默认带了一个 checkout 插件,这个插件可以实现将你的项目 Clone 到 CI 的运行环境中,从而执行各项操作。

为了提升速度,Github 在实际上实现的时候,默认会限制 depth=1,这就导致在 clone 的时候,仅 clone 一个 commit ,如果你需要依赖 git 进行操作,则需要更多的 commit 。

在具体的实现过程中,你需要做的仅仅是在配置 github action 中的 fetch-depth 选项,设置为你需要的 commit 数量。如果你需要的是所有的 commit, 则将该选项设置为 0。具体配置如下

- uses: actions/checkout@v2
        with:
          fetch-depth: 0

这样你就可以在 CI 中访问到所有的数据。

不过,这样你并不能直接执行诸如 git merge-base 这样的命令,因为你虽然将所有的数据抓取到了本地,但并没有建立相应的分支,则需要你先建立相应的分支,才能进行处理。

这个时候你可以在 action 当中新增一行,用来切换分支。

- run: git checkout x

这里的 x 是你需要操作的分支,不过你需要注意,切换过来以后,还需要重新切换回去,不然你的代码就版本不对了。

black and white penguin toy

如何使用 GitHub Action 自动部署 MKDocs

MKDocs 是一个基于 Python 写成的文档生成工具,在实际的使用过程中,我们可以借助 GitHub Action 来实现自动部署到 GitHub Pages 。

操作流程

首先,你需要先在本地生成一个 MKDocs 项目

生成后, 你可以在项目的根目录创建 GitHub Action 所需目录。

mkdir -p .github/workflows/

并创建一个配置文件 publish_docs.yml

name: Publish docs via GitHub Pages
on:
  push:
    branches:
      - main
jobs:
  build:
    name: Deploy docs
    runs-on: ubuntu-latest
    steps:
      - name: Checkout main
        uses: actions/checkout@v2
      - name: Deploy docs
        uses: mhausenblas/mkdocs-deploy-gh-pages@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          CONFIG_FILE: mkdocs.yml
          EXTRA_PACKAGES: build-base

创建完成后,将配置文件添加到版本控制中,并提交到 GitHub 上,就可以在你提交代码的时候,自动推送到 GitHub Pages 中。

需要注意的是,我使用的是 MKDocs 的 Material Design 主题,如果你使用的是其他主题(非自带的主题),则需要修改 EXTRA_PACKAGES 的配置。

代码解读

这个配置文件中主要是 on 和 steps 比较有学习的价值。

on:
  push:
    branches:
      - main

这段代码限制了,只有在 main 分支上,出现了 commit 的时候,才会触发这个 action 的执行,如果是其他的分支,则不会触发 action 的构建。

    steps:
      - name: Checkout main
        uses: actions/checkout@v2
      - name: Deploy docs
        uses: mhausenblas/mkdocs-deploy-gh-pages@master
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          CONFIG_FILE: mkdocs.yml
          EXTRA_PACKAGES: build-base

这里的两个 step, 第一个是 clone 出所有的代码, 第二个 step 就是我使用一个已经做好的 action mhausenblas/mkdocs-deploy-gh-pages@master,这个 action 的作用就是将 mkdocs 的文档生成并部署到 GitHub Pages 中。

这个 action 自带了 material design 的主题,执行后,会构建并推送到 GitHub Pages。如果你使用的也是这个主题就可以直接按照我的样式进行配置。如果你使用的不是这个主题,则需要将你的主题配置在 EXTRA_PACKAGES,从而让 action 在执行的时候安装相应的 package。

总结

GitHub Action 的 Marketplace 中有大量的现成 Action 可以供你使用,借助现成的 Action ,你可以非常简单的完成自己的 CI/CD 流程,非常方便。

black and white penguin toy

被 GitHub Action 坑了半天…

我这几天在忙着搞 LCTT 的 Travis-CI 迁移到 Github Action 。整体的 CI 的流程都已经迁移完成了,但是一个特定的检查脚本死活无法正常运行。

在这个过程中我尝试了多种办法,比如修改代码、调整里面的参数、打印其中的参数,似乎都是工作运行正常的。

将项目代码 clone 到本地后,发现代码在本地运转也是正常的。

我一直不知道问题出在哪里,百思不得其解。直到我在跑了几百次 Action 构建后,我发现,Github 默认的 checkout 插件是有问题的。

和标准的 git clone 不同, Github 默认的 Checkout 插件在实际 clone 项目是使用的不是 git clone 命令,而是采用先在本地 init 一个目录,并添加相应的 remote ,并 fetch 代码下来。

github action
GitHub Action 的 Clone

这样的好处是在处理的时候,只会 fetch 到特定的分支到本地,而不会将默认的其他分支一同 clone
到本地。但坏处就是你在执行的时候,只能针对特定的分支进行操作。

而检查脚本则是基于 git 本身的命令进行执行的,因此是需要比如 master 这样的分支的,这就导致在使用了默认的 checkout 插件的时候,检查脚本无法使用。

Travis-CI 的表现
Travis CI 的 Clone

与之对比的,是 Travis CI 在执行 Clone 的时候,采用的是全量 Clone ,再单独 Fetch 某个特定分支。从这个角度上来看,我可以理解 Github Action 为什么会 Clone 的更快一些。不过,这种 Clone 的方式确实给一些 CI 在 Check 时留下隐患。

总结

如果你在 Github 中使用默认的 Checkout 插件获取项目以后,执行 Git 操作出现了问题,很有可能是插件自己的问题,而不是你的问题。你可以选择自己构建 clone 命令,避免这个问题。

如何免费为你的组织项目配置 Vercel

前言

Vercel 是我自己非常喜欢的平台,我自己的一些项目都会选择使用 Vercel 来部署。比如 LogolyEasyWPBook 等等。

主要是其在中国大陆的访问速度是比 Netlify 和 Github Pages 更快。但不得不说的是,Vercel 提供了 Production 环境和 Development 环境,对于项目开发时是非常有用的,当你提交一个 commit 或者是一个 PR 时, Vercel 会自动帮你部署,并将相应的 URL comment 到你的 commit 或 PR 下,你只需要点击相应链接,就可以预览效果,十分方便。

但 Vercel 的 Teams 功能是付费的,对于一些 Organization 来说,你需要付费用 Vercel 成本是比较高的。特别是如果你是一个 OpenSource Project,你大概率入不敷出。在这种情况下,如何才能在 Organization Project 中免费使用 Vercel 呢?我考虑了一个绕过去的方法。

我们之所以无法使用在项目中无法免费使用 Vercel 是 Vercel 的产品策略问题。

而我们被禁用的无法使用官方自建的 Github Apps 来部署,但不意味着我们不可以自己实现这样的逻辑,来实现在组织内项目进行push。

而想要达成这样的效果,需要你具备两个条件

  1. 你的代码每一次提交都会自动触发 CI
  2. 你的 CI 中可以自动上传代码到 Vercel

而前者,可以通过 Github 提供的 Action 来完成。后者则可以通过编写代码来完成。不过好在,我在 Github 的 Marketplace 中找到了别人已经写好的 Action ,因此又可以少写一些代码(开心?)。

接下来,看看具体要如何操作。

步骤

安装依赖

在进行后续的操作之前, 你需要先安装配置过程中的依赖。

执行如下命令安装 Vercel CLI

npm i -g vercel

创建一个项目

为了正常部署,你需要创建一个项目,并将其 push 到 Github。当然,如果你已经创建好了项目,就直接把项目 Clone 到本地就好。

使用 Vercel 部署这个项目

这一步是为了在 Vercel 上创建一个项目,因为 Vercel 不支持通过网页端创建项目,只支持在 CLI 或通过 Git 接入自动创建。

在你的项目根目录,执行命令 vercel 来触发 Vercel 的部署,它会自动上传你的项目到 Vercel 。如果你之前登录过,会看到类似这样的界面,根据其提示进行配置就好。如果你之前没有登录过,你登录后会出现类似的界面。根据提示进行配置。

获取配置

想要部署一个项目到 Vercel ,你需要知道三样东西

  1. Access Token: 用于 CLI 的登录和 API 的调用,没有 Access Token ,Vercel 就没有办法获取到你的用户身份,进行鉴权校验。
  2. Org ID:Org ID 是指你在 Vercel 上的用户 ID。由于 Vercel 中一个人其实可以管理和配置多个 Team ,因此需要借助 Org ID 来指定要管理哪个账号下的项目。
  3. Project ID:很好理解,如果你要管理 Project ,就需要一个 Project ID。

其中,Access Token 你需要从 Vercel 后台的 Tokens 页面获取。

而 Org ID 则可以从你的项目中的 .vercel/project.json 中获取。你会获得类似下面这样的内容,其中的 OrgID 就是你在 Vercel 上的 ID ,而 Project ID 就是对应的项目 ID。

{"orgId":"r359XAnYONVAmiXtdxZ22A2E","projectId":"Qma3GdwoiAfJSsbsSydBgaCDh8LJj6wTWvvqpUwrN6J2F3"}

准备好了这三项以后,就可以进入到下一个环节,配置 Action Secret 了。

配置 Github Action Secret

Github Action 提供了 Secret 的机制,用来让你保存哪些安全密钥,避免直接写在 Action File 中,出现泄漏的可能。

打开你的项目的 Settings – Secrets 页面

在这里你可以新增 Secret ,你需要新增三个 Secret ,分别是

  • ORG_ID: 填写你从 .vercel/project.json 中获取到的 orgId;
  • PROJECT_ID:填写你从 .vercel/project.json 中获取到的 projectId;
  • VERCEL_TOKEN:填写你从 Vercel 后台生成的 Token。

这样,就配置好了 Secret ,接下来就可以在你的项目中加入 a、Action 配置文件,完成项目的配置。

添加 Action 配置文件

根据 Github 的规范,你需要将你的 Action 配置文件放置在项目根目录的 .github/workflows/xxx.yml 文件中,其中 xxx 是你的 Action 名,比如叫 vercel.yml

这里我使用的是 ngduc 写的 vercel-deploy-action

按照路径创建好 vercel.yml 文件,然后在其中加入如下代码

name: deploy website
on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: ngduc/vercel-deploy-action@master
        with:
          vercel-cli: vercel
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.ORG_ID}}
          vercel-project-id: ${{ secrets.PROJECT_ID}}
          github-token: ${{ secrets.GITHUB_TOKEN }}

粘贴进去以后,将 vercel.yml 添加到 git 控制中,并提交到 Github 上,就可以实现触发 Vercel 了。

总结

虽然 Vercel 本身不能免费提供 Organization 的支持,但是我们可以通过一些小的技巧,绕过其官方的配置。对于一些只是将 Vercel 配置为开发者预览的场景下来说,还是足够的。

但如果你希望将 Vercel 配置为生产环境,那么 Teams Plan 可以提供的更多的权限控制,会是你需要的,买一个,也不贵,是吧?