Jekyll 站点资源管理实战:CSS、JS、图片与内置 Sass 编译指南
【免费下载链接】jekyll:globe_with_meridians: Jekyll is a blog-aware static site generator in Ruby项目地址: https://gitcode.com/gh_mirrors/je/jekyll
本指南以 Jekyll 官方 step-by-step 教程的 Assets 一章(docs/_docs/step-by-step/07-assets.md)为主线,讲解如何在 Jekyll 站点中组织 CSS、JS、图片等静态资源,并深入剖析 Jekyll 内置的 Sass/SCSS 编译机制——从目录规划、入口文件与 partial 的拆分,到将编译产物接入布局的完整流程。读完本文,你将掌握一套可复用的 Jekyll 资源组织方案,并理解静态文件“原样复制”、Sass 文件“编译输出”这两条关键管线背后的源码实现。
资源文件的两条处理管线
在动手之前,先建立正确的认知模型:Jekyll 对站点目录下的普通文件只做一件事——原样复制到构建输出目录(默认_site)。文档原话是 “Place them in your site folder and they’ll copy across to the built site”,这意味着 CSS、JS、图片、PDF 等任何不以下划线开头的文件,都会保持目录层级被搬运到_site中。
这一行为在源码中有明确实现:构建时 lib/jekyll/reader.rb 的read_directories方法递归遍历站点目录(read→read_directories→retrieve_static_files),将无 YAML front matter 的文件交给StaticFileReader,lib/jekyll/readers/static_file_reader.rb 为每个文件创建Jekyll::StaticFile对象;最终写入时由 lib/jekyll/static_file.rb 的write(dest)方法把源文件复制到目标路径,并依据 mtime 判断是否增量跳过。
而带有两行 triple dashes(空 front matter)的文件则进入另一条管线:它会被当作页面处理,经过转换器编译后输出。Sass/SCSS 文件正是这条管线的典型代表——这是下一节的核心。
第一步:建立规范的资源目录结构
Jekyll 官方推荐的资源组织方式非常简洁,在你的站点根目录下创建:
. ├── assets │ ├── css │ ├── images │ └── js ...即先创建assets文件夹,在其下分别建立css、images、js三个子目录;同时在站点根目录(与assets平级)再创建一个_sass目录,稍后就会用到。
几点说明:
assets中的文件会按原路径出现在构建产物中。例如assets/css/styles.scss经编译后输出为assets/css/styles.css,assets/images/logo.png则原样复制到assets/images/logo.png。官方文档 docs/_docs/assets.md 也印证了这一点:“if you have a file namedcss/styles.scssin your site's source folder, Jekyll will process it and put it in your site's destination folder undercss/styles.css”。_sass目录比较特殊:它不会被直接输出到_site,仅作为 Sass@import的查找路径(load path),只存放 partial(以_开头或仅被导入的片段文件)。这一约定在 docs/_docs/assets.md 中有专门强调:sass_dir只被 Sass 使用,其中的文件不应包含空 front matter,否则它们不会按预期被转换,该目录只应放 import 内容。
第二步:用class="current"取代内联样式
教程此前的步骤里,为了让导航中“当前页面”的链接高亮,曾在_includes/navigation.html中内联了样式代码(例如把当前链接标红)。内联样式难以维护,不是最佳实践——样式应该外置到独立的样式表文件。
打开_includes/navigation.html,删除之前添加的用于着色当前链接的内联代码,替换为引用currentclass 的写法(该 class 将在本步稍后定义):
{% raw %}
<nav> {% for item in site.data.navigation %} <a href="{{ item.link }}"{% if page.url == item.link %} class="current"{% endif %}>{{ item.name }}</a> {% endfor %} </nav>{% endraw %}
这里item.link来自上一步在_data/navigation.yml中定义的数据,通过site.data.navigation循环渲染每个导航项;当page.url与当前导航项链接一致时,就给该<a>加上class="current",作为样式钩子。这是 Jekyll 站点中做“当前页高亮”的经典模式,相关上下文可对照 docs/_docs/step-by-step/05-includes.md(include 的建立)与 docs/_docs/step-by-step/06-data-files.md(数据驱动的导航)。
第三步:用 Sass 编写样式——Jekyll 内置的 CSS 扩展能力
虽然标准 CSS 文件同样可以完成样式编写,但 Jekyll 内置了对 Sass),可以让你使用变量、嵌套、mixin、partial 拆分等 CSS 本身不具备的能力。Sass 是直接烘焙进 Jekyll 的,无需额外安装转换器即可使用。
创建 Sass 入口文件assets/css/styles.scss
在assets/css/下新建styles.scss,内容如下:
--- --- @import "main";逐行解读:
- 开头的空 front matter(两行 triple dashes)是关键开关。文档明确指出:“The empty front matter at the top tells Jekyll it needs to process the file”。没有它,Jekyll 会把该文件当作普通静态文件原样复制,而不会执行 Sass 编译。这一点与 lib/jekyll/reader.rb 的分流逻辑完全对应:有 YAML front matter 的文件走
PageReader/页面管线,没有的走StaticFileReader/静态复制管线。 @import "main"告诉 Sass 去查找名为main.scss的文件,默认在站点根目录的_sass目录中查找(即前文创建的_sass/)。Jekyll 会把_sass配置为 Sass 的 import 搜索路径。
创建 partial 文件_sass/main.scss
在_sass/下新建main.scss,定义上面navigation.html中引用的currentclass,把当前链接的颜色改为绿色:
.current { color: green; }这就是拆分的思想:styles.scss只是入口与装配清单(通过@import组织各个 partial),真正的样式规则放在_sass下的 partial 文件中。文档也指出,现阶段你的站点只有这一个主 CSS 文件,但对于更大规模的项目,这种“入口文件 + partial 库”的组织方式是保持 CSS 结构清晰的最佳实践——官方站点本身即是范例:docs 站点的 docs/css/screen.scss 只有空 front matter 加一串@import(mixins、normalize、gridism、pygments、font-awesome、fonts、docsearch、style),而具体实现全部位于 docs/_sass 下的 partial 中。
底层原理:Jekyll 如何识别与编译 Sass 文件
从源码层面看,Jekyll 对 Sass/SCSS 的支持有明确约定:
- lib/jekyll/document.rb 定义了
SASS_FILE_EXTS = %w(.sass .scss).freeze,用于识别 Sass 类文件; - lib/jekyll/convertible.rb 中的
sass_file?、asset_file?方法据此判断文件类型,并且place_in_layout?明确返回 false——Sass/SCSS 文件不会被套进布局模板,这与普通页面不同; - 编译由
jekyll-sass-converter提供的Jekyll::Converters::Sass/Jekyll::Converters::Scss转换器完成,输出扩展名由 lib/jekyll/renderer.rb 的output_ext决定——styles.scss的产物就是styles.css。
你还可以在 Liquid 模板中直接使用sassify/scssify过滤器把字符串即时转换为 CSS:lib/jekyll/filters.rb 中这两个过滤器分别调用Jekyll::Converters::Sass与Jekyll::Converters::Scss的convert方法,测试用例见 test/test_filters.rb 的 “sassify with simple string”。
可选的 Sass 配置项
你可以在_config.yml中通过sass键定制转换行为,docs/_docs/configuration/sass.md 与 docs/_docs/assets.md 给出的核心配置包括:
sass: sass_dir: _sass # Sass 导入路径,默认即 _sass(相对 source 目录解析) style: compressed # 输出样式,所有 Sass 支持的 style 均可用sass_dir默认值为_sass,它是 Sass@import的 load path。注意:路径是相对站点 source 目录解析的,而不是相对_config.yml的位置;该目录仅服务 Sass 的导入机制,其中文件不会被单独输出为页面。style会被透传给 Sass,nested、expanded、compact、compressed等 Sass 支持的输出风格都合法。官方站点实际就使用了压缩输出:见 docs/_config.yml 中的sass: style: compressed。- 另外,Sass 文件与 Jekyll 的其他页面一样,会先经过 Liquid 渲染。如果模板语法与 Liquid 冲突(如使用 Mustache 等 JS 模板引擎的
{{ }}),需要用{% raw %}与{% endraw %}包裹相关代码,docs/_docs/assets.md 对此有专门提醒。
关于@import "main"与同名文件的注意事项
文档 docs/_docs/configuration/sass.md 特别提醒两点:
- 如果你在 VSCode 等编辑器里看到关于
@import "main";的告警,可以忽略——这不影响 Jekyll 中 SCSS 的功能; - 但 Jekyll 4 不允许从同名 Sass 页面(如
css/main.scss)导入名为main的 partial(_sass/main.scss)。因此本教程使用styles.scss作为入口文件,恰好规避了这个问题——入口文件名与 partial 名刻意不同。
第四步:在布局中引用编译后的样式表
要让整站应用这些样式,需要把样式表链接到布局模板的<head>中。打开_layouts/default.html,加入<link>标签:
{% raw %}
<!doctype html> <html> <head> <meta charset="utf-8"> <title>{{ page.title }}</title> <link rel="stylesheet" href="/assets/css/styles.css"> </head> <body> {% include navigation.html %} {{ content }} </body> </html>{% endraw %}
关键点:href中引用的/assets/css/styles.css并不存在于源码目录中,它是 Jekyll 由assets/css/styles.scss编译生成的产物。文档明确说:“Thestyles.cssreferenced here is generated by Jekyll from thestyles.scssyou created earlier inassets/css/”。只要你保持assets/css/styles.scss存在且带空 front matter,每次构建时 Jekyll 就会在_site/assets/css/下产出对应的styles.css,链接自然不会 404。
href使用绝对路径(以/开头)的前提是你的站点部署在域名根路径。如果你的站点需要通过baseurl部署在子路径(例如/blog),更稳妥的做法是使用{{ "/assets/css/styles.css" | relative_url }}过滤器自动拼上 baseurl——这与 docs/_docs/assets.md 中其他文档链接的处理方式一致(其内部即使用relative_url过滤器生成路径)。
第五步:启动本地服务验证效果
运行 Jekyll 的本地开发服务器:
jekyll serve然后打开 http://localhost:4000(默认端口 4000,可通过jekyll serve --port修改),检查导航栏中当前页面对应的链接是否显示为绿色。若为绿色,说明整条管线已经打通:
_data/navigation.yml提供导航数据;_includes/navigation.html依据page.url == item.link为当前项输出class="current";_sass/main.scss定义.current { color: green; };assets/css/styles.scss通过@import "main"把规则汇编为styles.css;_layouts/default.html通过<link>引入该样式表。
jekyll serve会监听文件变化并增量重建(参见 docs/_docs/configuration/incremental-regeneration.md),所以你修改_sass/main.scss或styles.scss后刷新浏览器即可看到最新效果,无需手动重启。
小结:本步完成的站点能力
经过这一步骤,你的 Jekyll 站点具备了:
- 一套清晰的资源目录约定(
assets/css|images|js+ 根级_sass),普通资源文件自动原样复制到_site; - 基于 Sass 的样式组织能力:带空 front matter 的
.scss入口文件 +_sass下的 partial 拆分,编译产物自动生成同名.css; - 数据驱动的导航高亮:
class="current"钩子 + Sass 规则,实现当前页链接着色,样式与结构彻底分离。
下一步,教程将进入 Jekyll 最受欢迎的功能之一——博客(Blogging),届时assets与_sass的组织方式将持续发挥作用。完整教程系列位于 docs/_docs/step-by-step,从 01-setup.md 开始即可完整复现这套站点。
【免费下载链接】jekyll:globe_with_meridians: Jekyll is a blog-aware static site generator in Ruby项目地址: https://gitcode.com/gh_mirrors/je/jekyll
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考