Use JBake ("mvn generate-resources") to build your static website or blog. Use layouts, macros, and data files.
We migrated the entire www.optaplanner.org website (1399 files) to use Java and Maven instead of Ruby and Rake for building. On the surface, nothing has changed. But in the source code, it is a game changer for our team of Java developers.
Our Java team can now easily contribute to the website. Within a few hours of completing the migration, one of our developers had already submitted a submission that was unwilling to touch the previous source code with a ten-foot pole.
We have established this website.
We built this site on Java and Maven.
We have established this website.
We set up this website on JBake and Freemarker.
Why use a static website generator?
The static website generator converts templates and content files into static HTML/JS/CSS websites. For projects like ours, this has many advantages over content management systems (CMS):
Hosting is cheap. GitHub pages even host static websites for free.
The source file enters Git for backup and history recording.
The source file is in plain text format:
Changes come in the form of pull requests for proper review and CI verification.
The source code is open in our IDE, which encourages refactoring them along with the code. This will reduce stale content.
Awestruct has been serving us for many years. But due to lack of activity, it was time to upgrade.
Why is JBake?
Because we are Java programmers.
There are several good static website generators, such as Jekyll (Ruby) and Hugo (Go). We choose JBake (Java) because:
Our website is now built using Maven (mvn generate-resources).
No need to install anything. Not even JBake. Everyone uses the same version of JBake to build, such as pom.xml.
And it's fast: even if mvn clean builds 150 output pages on my machine, it only takes 20 seconds.
.The following is all Java.
It's easy to write conditional expressions. The API (String.substring(), ...) is familiar. The date format (d MMMM yyyy) and regular expression behave as expected.
Most importantly, the error message is clear.
For 8 years, I have used Awestruct (Ruby) to write this website. But I never took the time to learn Ruby, so every change requires hours of trial and error. I can't just read the error message and fix it. It's not Ruby's fault. That's because I never took a few days to really learn Ruby. With JBake, I can fix errors in a short amount of time: trial and error are no longer required.
What is JBake?
JBake is a static website generator with many options:
Use Maven or Gradle to build.
We chose Maven because all our repos are built with Maven (although the two OptaPlanner Quickstarts are also built with Gradle, because OptaPlanner also supports Gradle).
Write content in Asciidoc, Markdown or HTML.
We chose Asciidoc because it is richer and more reliable than Markdown. In addition, all our documents are written with Asciidoc.
Use Freemarker, Thymeleaf or Groovy to create templates.
We chose Freemarker because it is a powerful and proven template engine.
Tips and tricks
These are common tasks for building advanced static websites and how to implement each task in JBake-Freemarker. You can even call these JBake design patterns:
Use macros to render shared content
Almost all of our templates display the same latest version panel:
Latest release
Freemarker templates are very suitable to avoid repeating yourself (DRY):
templates/macros.ftl is created with a macro that outputs HTML:
<#macro latestReleases>
<div class="panel panel-default">
<div class="panel-heading">Latest release</div>
...
</div>
</#macro>
Then use it in the *.ftl template:
<#import "macros.ftl" as macros>
...
<div class="row">
<div class="col-md-9">
...
</div>
<div class="col-md-3">
<@macros.latestReleases/>
</div>
</div>
Use data files to add videos, events, or other volatile data
Some data changes too frequently to be maintained in the content or template files:
A data file, such as a simple *.yml file, can well store such volatile data:
Create data/videos.yml:
- youtubeId: blK7gxqu2B0
title: "Unit testing constraints"
...
- youtubeId: gIaHtATz6n8
title: "Maintenance scheduling"
...
- youtubeId: LTkoaBk-P6U
title: "Vaccination appointment scheduling"
...
Then use it in the ftl template:
<#assign videos = data.get('videos.yml').data>
<div class="panel panel-default">
<div class="panel-heading">Latest videos</div>
<div class="panel-body">
<ul>
<#list videos[0..6] as video>
<li>
<a href="https://youtu.be/${video.youtubeId}">${video.title}</a>
</li>
</#list>
</ul>
</div>
</div>
Layout inheritance
All HTML pages usually share the same HTML header (metadata), header (navigation), and footer. These fit perfectly in the base.ftl layout and are extended by all other templates:
Although most content uses normalBase.ftl, all use case pages of useCaseBase.ftl have separate templates, such as vehicle routing issues (VRP), maintenance plans, and shift scheduling.
Use the macros with <\#nested> to build layout inheritance:
Create templates/base.ftl:
<#macro layout>
<html>
<head>
...
</head>
<body>
<div>
... <#-- header -->
</div>
<#nested>
<div>
... <#-- footer -->
</div>
</body>
</html>
</#macro>
Extend it templates/useCaseBase.ftl and introduce the custom attribute related_tag:
<#import "base.ftl" as parent>
<@layout>${content.body}</@layout>
<#macro layout>
<@parent.layout>
<h1>${content.title}</h1>
<#nested>
<h2>Related videos</h2>
<#assign videos = data.get('videos.yml').data>
<#assign relatedVideos = videos?filter(video -> video.tags.contains(content.related_tag))>
<ul>
<#list relatedVideos as video>
<li><a href="https://youtu.be/${video.youtubeId}">${video.title}</a></li>
</#list>
</ul>
</@parent.layout>
</#macro>
Create a use case page for content/vehicleRoutingProblem.adoc using this template and setting the related_tag attribute:
= Vehicle Routing Problem
:jbake-type: useCaseBase
:jbake-related_tag: vehicle routing
The Vehicle Routing Problem (VRP) optimizes the routes of delivery trucks,
cargo lorries, public transportation (buses, taxi's and airplanes)
or technicians on the road, by improving the order of the visits.
This routing optimization heavily reduces driving time and fuel consumption compared to manual planning:
...
begin
Try it yourself. To build the www.optaplanner.org website, run the following command:
$ git clone https://github.com/kiegroup/optaplanner-website.git
...
$ cd optaplanner-website
$ mvn clean generate-resources
...
$ firefox target/website/index.html
Or take a look at the source code .
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。