gohugo-amp

Styling & HTML-Minification

AMP does not allow you to include CSS styles with the regular link rel='stylesheet'-tag we need to embed the CSS in the header section. For this reason we have prepared a simple yet powerful workflow how you can easily and automatically manage your stylesheets with ease.

Where lives the stylesheet?

In your documents <head>-Section is a tag called <style amp-custom> this is the only place AMP accepts custom CSS. Therefore have made a partial called partials/stylesheet.html where your CSS has to be rendered in. Remember, just the RAW CSS, without the wrapping <style>-Tag.

Our goal is that you can work with gohugo-amp as flexible as possible, thats why we have prepared the following NPM-Workflow for you so do not have to be worried about the process.

Create a package.json-File in your root folder

If you do not already have a package.json, you can do this by typing npm init in your console and follow the wizard. The output will look something like this:

{
  "name": "gohugo-amp.gohugohq.com",
  "version": "1.0.0",
  "description": "documentation repository for gohugo-amp theme.",
  "main": "index.js",
  "scripts": {},
  "author": "Raphael Wildhaber",
  "license": "UNLICENSED",
  "dependencies": {},
  "devDependencies": {},
  "repository": {
    "type": "git",
    "url": "git+https://github.com/wildhaber/gohugo-amp.gohugohq.com.git"
  },
  "keywords": [
    "gohugo",
    "amp",
    "theme",
    "starterkit",
    "hugo",
    "static-site-generator"
  ],
  "bugs": {
    "url": "https://github.com/wildhaber/gohugo-amp.gohugohq.com/issues"
  },
  "homepage": "https://gohugo-amp.gohugohq.com"
}

Add necessary dependencies

Next we will have to add some dev-dependencies for the styling workflow. In this case we use Sass as a pre-compiler.

To install the necessary packages you can simply copy paste the following installation command:

$ npm install html-minifier autoprefixer cssnano node-sass nodemon postcss --save-dev

Next, add the styling-build-file

For this you will need to add a file called styling.js and save it in a folder called /.bin/ in your root folder. Copy the following code into the the styling.js file:

var sass = require('node-sass');
var postcss = require('postcss');
var fs = require('fs');

const inputFile = './layouts/src/styles.scss';
const outputFile = './layouts/partials/stylesheet.html';

sass.render({
    file: inputFile,
    outputStyle: 'compressed'
}, function(error, result) {
    if (error) {
        console.log(error.status);
        console.log(error.column);
        console.log(error.message);
        console.log(error.line);
    }
    else {
        let cssOutput = result.css.toString();
        postcss([ require('autoprefixer'), require('cssnano') ])
            .process(cssOutput)
            .then((result) => {
                fs.writeFile(outputFile, result.css, function(err) {
                    if(err) {
                        return console.log(err);
                    }
                    console.log('\u2611 file '+outputFile+' updated with current styling from '+ inputFile);
                });
            });
    }
});

If necessary, adjust the inputFile constant with wherever your main Sass entry-point is.


Minify your HTML

AMP requires to have a minified HTML code, thats why you need to setup an HTML-Minifier as well. We have done this using html-minifier package.

Create a file called .html-minifier-config.json and save it in the root of your project just beside the package.json. Add the following content to the file and save it.

{
  "caseSensitive": false,
  "collapseBooleanAttributes": true,
  "collapseInlineTagWhitespace": false,
  "collapseWhitespace": true,
  "conservativeCollapse": false,
  "customAttrCollapse": ".*",
  "decodeEntities": true,
  "html5": true,
  "ignoreCustomFragments": [
    "<#[\\s\\S]*?#>",
    "<%[\\s\\S]*?%>",
    "<\\?[\\s\\S]*?\\?>"
  ],
  "includeAutoGeneratedTags": false,
  "keepClosingSlash": false,
  "maxLineLength": 0,
  "minifyCSS": false,
  "minifyJS": false,
  "preserveLineBreaks": true,
  "preventAttributesEscaping": false,
  "processConditionalComments": true,
  "processScripts": [
    "text/html"
  ],
  "removeAttributeQuotes": true,
  "removeComments": true,
  "removeEmptyAttributes": true,
  "removeEmptyElements": false,
  "removeOptionalTags": true,
  "removeRedundantAttributes": true,
  "removeScriptTypeAttributes": true,
  "removeStyleLinkTypeAttributes": true,
  "removeTagWhitespace": false,
  "sortAttributes": false,
  "sortClassName": false,
  "trimCustomFragments": true,
  "useShortDoctype": true
}

Add custom scripts

Now you can add the following NPM-Scripts in the scripts property of your package.json

"scripts" : {
    "hugo:server": "hugo server --buildDrafts --buildFuture",
    "test": "echo \"Error: no test specified\" && exit 1",
    "build:prod": "npm run theme:build && hugo && npm run optimize:html",
    "optimize:html": "./node_modules/.bin/html-minifier --input-dir ./public/ --output-dir ./public/ --file-ext html -c ./.html-minifier-config.json",
    "theme:build": "node ./.bin/styling",
    "theme:watch": "./node_modules/.bin/nodemon -e scss -w ./ -x npm run theme:build"
}

The outcome

These scripts can be executed typing npm run [scriptname] and you have a simple production ready environment for development and deployments.

npm run hugo:server

This script simply runs hugo server including buildDrafts and buildFuture flags.

npm run build:prod

This script will build your theme styling let hugo run and minify / optimize the outcoming HTML structure. So the /public-path is ready to deploy.

npm run optimize:html

This script minifies and optimize the outcoming HTML after Hugo has rendered.

npm run theme:build

This script will grab your styling from a Sass file, minifies and autoprefixes it and safe it in the partials/stylesheet.html-Partial-File which is included in the head-section.

npm run theme:watch

This is a very handy script listening to any changes on a Sass-File and render the theme-styles.

Conclusion

This is a way you only have to run npm run theme:watch in your terminal beside the regular hugo server and your development is ready.