We’ve been working with Vuepress version-1.0.0-alpha.47 as it has more inbuilt features.
The greatest pros of VuePress include:
- Speed;
- A number of inbuilt features like navigation, sidebar, search, BackToTop, multilingual support, emoji, and so on;
- Simple to use (no need for special programming skills);
- Flexibility (it is easy to modify or add new features).
Cons:
- A small number of libraries/plugins for VuePress;
- Does not support many Vue.JS libraries;
- Template conflict (if you try to change the official theme, you have to refuse from updates).
The main point of VuePress is to convert README.md files to HTML.
VuePress fits best for documentation sites (for libraries, APIs, etc.) and blog sites. This framework converts markdown (.md) files into HTML format, so it’s pretty simple to maintain such an application. For example, in order to add newsfeed in an ordinary framework, you’d need an admin panel where a developer would put down news for the blog. Meanwhile, in VuePress, it’s enough to create a README.md document with a simple syntax which is further converted into a full-featured web page and this can be done by anyone.
As a sample case, let’s discuss the OCDS Analytics project we’ve created. This project is not fully based on VuePress - it is a combination of VuePress and Vue.JS. The reason for this is that it doesn’t simply hold API and library documentation, but also functions as a full-fledged web portal with registration and user profile where users can customize information about themselves and manage their API keys. To enable this, we’ve created Components (src/.vuepress/components) in the project root. These components are by no means different from the components written in Vue.JS.
Updating VuePress components and the theme
There were several issues we’ve faced while working on the project.
First of all, since the components are written in Vue.JS, we’ve tried to connect Vue plugins. In the dev environment, these plugins work but when trying to build, an error in rendering from README to HTML (Promise) occurred. This issue was not related to plugins but mostly emerged with libraries working directly with DOM (modal windows, Alerts, Pop-ups, etc.).
Secondly, there was a need to rewrite a lot in the standard VuePress theme. For example, on some pages, sidebar update was required. By default, the sidebar has two modes: automatic mode (when sidebar content is generated dynamically) and manual mode (when sidebar content is set via Config.js and is the same for all website pages). In our case, we used sidebar as secondary navigation and had to customize it for several pages, while leaving automatic mode for the rest of them. In order to customize sidebar content on some pages, we wrote the function in the ‘Methods’ block (page SidebarLinks.vue):
blogSidebar () {
if (this.$route.path === '/blog/' && this.items[0]) {
if (!this.blogItems.length && this.items[0].children.length) {
this.$site.pages.forEach((item) =>{
if (item.frontmatter.categories === 'blog') {
this.blogItems.push({
basePath: '/blog/',
title: item.frontmatter.title,
type: "auto",
path: "/blog/#" + item.frontmatter.title.replace(/ /g, '-'),
children: []
})
}
});
}
this.items[0].children = this.blogItems
}
}
One more problem was related to the need to implement plain HTML pages (without Vue.JS). As VuePress can work only with README documents, the framework ignored HTML pages. We could have found a workaround by writing a simple Vue.JS component using a template. But this option wasn’t suitable. The issue was solved with gitlab-ci. During the buildup, gitlab copied these HTML pages and pasted them to the ‘dist’ folder where VuePress kept the whole build. Therefore, full paths to these pages had to be used (e.g. correct path https://ocdsanalytics.com/ua/prozorro/ai/docs/examples/unit.html, wrong path /ua/prozorro/ai/docs/examples/unit.html). When a route starts with ‘/’, VuePress searches for it in Routes and if the route is not listed there, VuePress returns 404 error. That’s why external links should be pasted through ‘location.origin’. Note that in this case SPA is lost and browser restarts the application.
As for working in different environments, such as local, staging, and production, we had to create 3 documents in the ‘vuepress’ folder root: config.domain.js, config.domain.staging.js, and config.domain.production.js with the following data:
// config.domain.js:
module.exports = {
location: 'http://127.0.0.1:8000',
}
// config.domain.staging.js:
module.exports = {
location: 'http://staging.odcsanalytics.office',
}
// config.domain.production.js:
module.exports = {
location: 'https://ocdsanalytics.com',
}
In the main configuration file ‘config.js’ we’ve imported ‘config.domain.js’
let domain = require('./config.domain');
We’ve used these ‘gitlab-ci.yml’ settings for different environments:
DEV:
stage: build
script:
- cp .vuepress/config.domain.staging.js .vuepress/config.domain.js
...
only:
- master
- merge_requests
- dev
...
PROD:
stage: build
when: manual
script:
- cp .vuepress/config.domain.production.js .vuepress/config.domain.js
...
Adding Google Tag Manager and Recaptcha
Also, you might need to insert the script from Google Tag Manager and Recaptcha.
In order to add GTM and Recaptcha to VuePress project, we need to add 2 different scripts - one to the ‘<head>’ tag, and another one to the ‘<body>’ tag.
As for the first one (<head>), we need to add the script in the main configuration file (config.js):
module.exports = {
head: [
['script', {}, `
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-1234567');
`],
],
It’s a bit more complicated with the second script (<body>) since there is no main ‘index.html’ file like on Vue.JS project. We needed to find a suitable file to insert this script. ‘Layout.vue’ file which is the main one in the ‘theme’ folder, was the best fit for this.
beforeMount() {
let recaptchaScript = document.createElement('noscript')
recaptchaScript.innerHTML = '<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-1234567"
height="0" width="0" style="display:none;visibility:hidden"></iframe>'
document.body.appendChild(recaptchaScript)
},
This way any “custom” code can be added to the document.
To sum up, VuePress is very convenient to use when content of a web portal or blog needs to be managed by a non-tech or a person without coding skills. We’ve used it in our project as it is pretty simple and easy to understand being super fast at the same time.