> 文章列表 > 使用Bazel构建前端Sass

使用Bazel构建前端Sass

使用Bazel构建前端Sass

6e29c361f2c3ebb6640d32b3328307d4.jpeg

注:本文假设对Bazel有一定的了解。本文基于Bazel 4.2.2 版本

在web前端领域,前端样式,web浏览器只认CSS样式语言。而CSS样式语言又过于低级。于是有人发明了更高级的语言:Sass[1],用于生成CSS代码。

这样的方案,称为:“CSS预处理器”。除了使用Sass实现,还可以使用LESS实现等。

本文介绍是如何使用Bazel将Sass文件编译成CSS文件。

为什么使用Bazel

编译Sass的方法已经很多了,为什么我们还要使用Bazel呢?虽然本质上,Bazel编译Sass源代码时,使用的是sass原生的编译工具[2] 。

使用Bazel的原因如下:

  1. 1. 它支持增量构建:以避免将来的不必要的构建速度成本

  2. 2. 对单仓库友好:因为它支持多语言,所以,我们可以放心地把前后端代码、基础设施代码放在同一个仓库中;

  3. 3. 统一构建工具:使整个工程的构建逻辑达到高度一致,以避免将来构建逻辑不一致的成本。

样例工程结构

[workspace]/WORKSPACEhello_world/BUILDmain.scssshared/BUILD_fonts.scss_colors.scss

WORKSPACE说明

在WORKSPACE中引入Rule:

git_repository(  name = "io_bazel_rules_sass",  commit = "354793d0603dbe26232f4a5fb25e67e0e9e4c909", # 我这里指定最新的是commit  remote = "https://github.com/bazelbuild/rules_sass.git",  
)# Setup Bazel NodeJS rules.
# See: https://bazelbuild.github.io/rules_nodejs/install.html.# Setup repositories which are needed for the Sass rules.
load("@io_bazel_rules_sass//:defs.bzl", "sass_repositories")
sass_repositories()

我们采用git_repository的方式引入rules_sass

当你执行构建时,会遇到错误:

ERROR: Failed to load Starlark extension '@build_bazel_rules_nodejs//:index.bzl'.
Cycle in the workspace file detected. This indicates that a repository is used prior to being defined.
The following chain of repository dependencies lead to the missing definition.- @build_bazel_rules_nodejs
This could either mean you have to add the '@build_bazel_rules_nodejs' repository with a statement like `http_archive` in your WORKSPACE file (note that transitive dependencies are not added automatically), or move an existing definition earlier in your WORKSPACE file.
ERROR: cycles detected during target parsing

这是因为rules_sass依赖于rules_nodejs。解决办法是在rules_sass之前声明rules_nodejs

http_archive(  name = "build_bazel_rules_nodejs",  sha256 = "c077680a307eb88f3e62b0b662c2e9c6315319385bc8c637a861ffdbed8ca247",  urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/5.1.0/rules_nodejs-5.1.0.tar.gz"],  
)  load("@build_bazel_rules_nodejs//:repositories.bzl", "build_bazel_rules_nodejs_dependencies")  build_bazel_rules_nodejs_dependencies()  load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains")  
load("@rules_nodejs//nodejs:yarn_repositories.bzl", "yarn_repositories")  nodejs_register_toolchains(  name = "nodejs",  node_version = "16.13.2",  
)  yarn_repositories(  name = "yarn",  yarn_version = "1.22.17",  
)
以下是rules_sass的声明

注:将rules_nodejs显示声明在WORKSPACE中,是一个避免与其它Rules发生冲突的好习惯。

注:执行构建的过程需要连接外网,请留意你的网络。

BUILD说明

样例工程中,shared/BUILD定义的是sass库:

package(default_visibility = ["//visibility:public"])load("@io_bazel_rules_sass//:defs.bzl", "sass_library")sass_library(name = "colors",srcs = ["_colors.scss"],
)sass_library(name = "fonts",srcs = ["_fonts.scss"],
)

hello_world/BUILD声明的是最终的sass文件的构建逻辑,注意它使用的是sass_binary

package(default_visibility = ["//visibility:public"])load("@io_bazel_rules_sass//:defs.bzl", "sass_binary")sass_binary(name = "hello_world",src = "main.scss",deps = ["//shared:colors","//shared:fonts",],
)

sass_binary用于输出一个css文件。它还有很多参数,比如:

  • • output_dir: css输出文件的文件夹

  • • output_name:css输出的文件名称

更多参数,请前往Github仓库。

main.scss说明

在main.scss文件中,我们需要注意的是:在@import时,import的是sass_library的名称,而不是带有下划线的真实文件名:

@import "shared/fonts"; // 这里需要注意
@import "shared/colors";html {body {font-family: $default-font-stack;h1 {font-family: $modern-font-stack;color: $example-red;}}
}

执行构建

$ bazel build //hello_world
INFO: Found 1 target...
Target //hello_world:hello_world up-to-date:bazel-bin/hello_world/hello_world.cssbazel-bin/hello_world/hello_world.css.map
INFO: Elapsed time: 1.911s, Critical Path: 0.01s

成本

采用Bazel构建Sass不是没有成本的。比如旧工程的迁移成本、前端开发人员的学习成本等。你需要根据你的项目的实际情况做权衡。

引用链接

[1] Sass: https://sass-lang.com/
[2] 编译工具: https://github.com/bazelbuild/rules_sass/blob/main/sass/sass_wrapper.js

往期文章推荐:

比构建速度,Bazel是Gradle的10倍,不服不行!!!