Background
On our doc site, we have a few pages with instructions on installing Bytebase, like this one: Deploy Bytebase in Docker within 5 seconds. On these pages, we teach users how to install the latest version of Bytebase by showing command snippets.
But at Bytebase, we release a new version biweekly, which means we need to update the latest version here (currently 3.1.0) every two weeks.
This is painful and error-prone to change every version string during the upgrade. Ideally, we only need to change the latest version in one place, and let other files read and use it just like a global variable. Let's improve this procedure and say goodbye to the cumbersome manual operations!
1st Attempt - A version component
After some investigation, I sadly found out that there is no out-of-box global variable support in Nuxt Content currently: nuxt/content#997 (comment).
Our website is built with Nuxt Content v1, so I then looked through its documentation, and the title Vue components just caught my eye. When we use components, we expect them to solve the problem of functional reuse, which coincides with the purpose of a version variable. We can write a component with the latest version number as its content, and use this component everywhere we need.
So following Nuxt Content's instruction, we create a global component named Version.vue,
and place it under /components/global
:
In this way, we have registered it as a global component. Then we can use it in markdown files like below:
A standalone version file
Usually, our Developer Marketing team updates the version number on every new release, thus it's beneficial to reduce the required coding work. So it would definitely be better if the version number is in a standalone file like what we did in the Bytebase repo.
To achieve this, we create a file named VERSION
and put it under the root directory. This file only contains one line of the exact latest version number:
Then we should make some changes to the version component to let it read the version info from this plain file. Before that, we need to install raw-loader
as a devDependency
so that we can parse plain text files as raw strings.
And rewrite our Version.vue
into this:
Now, whenever we publish a new version of Bytebase, we just need to simply change the version number in the VERSION
file.
Limitations
However, the solution of using a version component has some limitations:
- In Nuxt Content, we cannot use a component directly in code blocks surrounded by backticks
```
. To do this, we have to wrap code snippets inside<pre>
tags. This is an ugly pattern and will cause rendered code blocks to lose the original styles and functionalities like copy buttons.
- Components cannot be used everywhere. For example, if we want to use the component in a link address, it won't work:
We actually used a tricky workaround to achieve it here, which will redirect visitors to the latest release page (For now, it's 3.1.0).
Refined solution - Inject version number before content parse
We used the version component for a couple of weeks. Until one day, I wandered into Nuxt Content docs' advanced part and saw an example of the hook content:file:beforeParse
:
In this example, the author uses this hook to convert all occurrences of the word react
into vue
. It inspired me that we could use a similar technique and convert all occurrences of the placeholder $$bb_version$$
into the latest version value (3.1.0
).
Let's enhance this.
Remove the former version component part, and add a few lines in the file nuxt.config.js
. Before parsing, we will look for markdown files under directory /docs
, and use a regex to replace placeholders with the latest version number read from the file VERSION
.
In markdown files, insert the placeholder $$bb_version$$
into where we are putting the version number.
Now there's no need for <pre>
tags or extra loader packages, and the placeholder works in every corner including link addresses. Perfect! ✌️
Result
This is how we update our docs now. Just a single line change to update the version string and all version references scattered over the doc will get updated. Concise and effective.