Jump to navigation

Re-building this website - iameven.com

- Even Alander

Yet again rebuilding a site that already worked. But optimization, you know.

As I said in my previous post about building this website I really didn't like depending on both node and ruby to build my site. As awesome as jekyll is I just never got into ruby. I also didn't like doing the build locally before submitting. Duplication of content and more work for me, all my builds were in git commits, and sometimes I forgot to do it.

I began using react.js on a work project and really like that way to structure code. For some reason I thought I could do really cool things with this site by changing to that. I converted my markdown files to react components and started realizing that this was the wrong tool for the job. Yes, I could do awesome transitions but writing posts suddenly got really hard. I did get to experiment some with server side rendering with the same code, so not all was wasted.

Then I wrote my own post parser and static file generator. I had a working prototype in a couple of hours, but the code was really messy. I suddenly started thinking about metalsmith and its plugin based structure. It suddenly seemed a lot more safe to lean on some sort of established system rather than re-invent everything.

How it works

I have all the posts collected in src/posts, an index.html, iameven.css and iameven.js file in src/ and some template files in a templates/ folder. I run index.js locally or from Dokku which collects the files and build the site before starting an express.js server.

The index.js file loads metalsmith and all the plugins I use, excerpt is a modified version of metalsmith-excerpts and date is a custom one I wrote to handle date manipulation.

// index.js
var Metalsmith = require('metalsmith');
var markdown = require('metalsmith-markdown-remarkable');
var highlight = require('metalsmith-code-highlight');
var collections = require('metalsmith-collections');
var permalinks = require('metalsmith-permalinks');
var templates = require('metalsmith-templates');
var beautify = require('metalsmith-beautify');
var feed = require('metalsmith-feed');
var sass = require('metalsmith-sass');
var autoprefixer = require('metalsmith-autoprefixer');
var ignore = require('metalsmith-ignore');

var excerpt = require('./plugins/excerpt.js');
var date = require('./plugins/date.js');

var url = 'https://iameven.com/';

Metalsmith(__dirname)
    // set data used by feed
    .metadata({
        site: {
            title: 'iameven.com',
            author: 'Even Alander',
            description: 'Ramblings of an average geek',
            url: url,
        },
    })
    // convert markdown to html
    .use(
        markdown({
            langPrefix: 'lang-',
            html: true,
        })
    )
    .use(excerpt()) // collect descriptions
    .use(highlight({languages: []}))
    // this adds path to post metadata for collections
    .use(permalinks(':title'))
    // create the collections before running through templates
    .use(
        collections({
            posts: {
                pattern: '*/*.html',
                sortBy: 'date',
                reverse: true,
            },
        })
    )
    // create feed before header and footer is added
    .use(
        feed({
            collection: 'posts',
            destination: 'feed.rss',
        })
    )
    // change date to custom display format
    .use(date())
    // parse files and create the index
    .use(
        templates({
            engine: 'handlebars',
            cache: false,
            partials: {
                header: 'partials/header',
                footer: 'partials/footer',
                posts: 'partials/posts',
            },
            helpers: {
                ifCond: function(v1, v2, options) {
                    if (v1 === v2) {
                        return options.fn(this);
                    }
                    return options.inverse(this);
                },
            },
        })
    )
    .use(
        sass({
            outputStyle: 'compressed',
            includePaths: ['styles'],
        })
    )
    .use(autoprefixer())
    // make sure output is somewhat pretty
    .use(
        beautify({
            html: {
                indent_inner_html: true,
            },
        })
    )
    .use(ignore(['styles/']))
    .build(function(err) {
        if (err) console.log(err);
        server();
    });
// serve
function server() {
    var express = require('express'),
        compression = require('compression'),
        port = process.env.PORT || 3000,
        app = express();
    app.use(compression());
    app.use(express.static('build'));
    // catch unresolved paths and serve a 404.html file
    app.use(function(req, res) {
        res.status(404).sendFile(__dirname + '/build/404.html');
    });
    app.listen(port, function(err) {
        if (err) return err;
        console.log('listening to port ' + port);
    });
}

The express server is pretty much the same thing I used before.

Problems

Or rather quirks, I would say. Struggles maybe?

Changes

Conclusion

The site is now really light weight, easy to manage and pretty optimized. I think I'll manage to live with this for a while.

Post stats 2014 Post install
Logo