Sass verwerken met 11ty

Mijn Eleventy (11ty)-project

Ik heb onlangs 11ty ontdekt en de statische sitegenerator gebruikt om een ​​zakelijke website te bouwen. Ik vind het leuk dat 11ty het mogelijk maakt om met verschillende sjablonen te werken en ze ook te mixen. Op deze site heb ik Nunjucks, Markdown en Sass gebruikt. Nu heeft 11ty geen Sass-voorverwerking ingebouwd. Dus ik moest mijn eigen weg vinden.

Scss veranderen in css

Er zijn een paar benaderingen om dit probleem op te lossen met behulp van filters of Gulp. Ik had de Gulp-manier in een ander project gebruikt, maar voor deze wilde ik iets anders doen. Dus schreef ik in plaats daarvan een Node-script!

De code

Het leuke van 11ty is dat het in JavaScript is geschreven. Dus je kunt rennen in .eleventy.js config bestand elke uitvoerbare code die je leuk vindt, zolang het JavaScript is. Dus hier is de functie die ik in mijn project gebruik om scss-bestanden voor te verwerken.

/config/sass-process.js

const sass = require('sass');
const fs = require('fs-extra');
const path = require('path');

module.exports = (scssPath, cssPath) => {
    //If cssPath directory doesn't exist...
    if(!fs.existsSync(path.dirname(cssPath))) {
        //Encapsulate rendered css from scssPath into result variable
        const result = sass.renderSync({file: scssPath});
        //Create cssPath directory recursively
        fs.mkdir(path.dirname(cssPath), {recursive: true})
        //Then write result css string to cssPath file
        .then(() => fs.writeFile(cssPath, result.css.toString()))
        .catch(error => console.error(error))
    }
    //Watch for changes to scssPath directory...
    fs.watch(path.dirname(scssPath), () => {
        console.log(`Watching ${path.dirname(scssPath)}...`);
        //Encapsulate rendered css from scssPath into watchResult variable
        const watchResult = sass.renderSync({file: scssPath});
        //Then write result css string to cssPath file
        fs.writeFile(cssPath, watchResult.css.toString())
        .catch(error => console.error(error))      
    });
}

En neem die functie dan op in .eleventy.js bestand als zodanig.

.eleventy.js

const sass = require('./config/sass-process');

module.exports = config => {
    //Watching for modificaions in style directory
    sass('./style/index.scss', './docs/style/index.css');
}

Deze code herstructureren om deze asynchroon te maken

De bovenstaande oplossing werkt prima voor mijn behoefte. Het punt is dat ik de synchrone methode gebruik om sass . weer te geven sass.renderSync() en die code blokkeert (heel weinig, maar toch). Er zijn reguliere oplossingen om css . weer te geven van sass asynchroon zoals de node-sass-bibliotheek met zijn asynchrone render() methode die ik kan veranderen in een promise zoals zo.

const sass = require('node-sass');
const cssResultFrom = file => {
    return new Promise((resolve, reject) => {
        sass.render({file: file}, (error, result) => {
            if(error) {
                reject(error);
            }
            resolve(result);
        });
    });
}
//Then to use it...
cssResultFrom(scssPath)

In plaats van mijn eigen Promise te schrijven wrapper, ik zou een module kunnen gebruiken die het voor mij doet, zoals de vrij nieuwe node-sass-promise.

//node-sass-promise method
const sass = require('node-sass-promise');
//And to use it...
sass.render({file: scssPath})

Iets minder flexibel dan het schrijven van mijn eigen wrapper, maar minder code om te schrijven! Een voorbeeld van code met node-sass-promise :

const sass = require('node-sass-promise');
const fs = require('fs-extra');
const path = require('path');

module.exports = (scssPath, cssPath) => {
    //If cssPath directory doesn't exist...
    if(!fs.existsSync(path.dirname(cssPath))) {
        //Create cssPath directory recursively
        fs.mkdir(path.dirname(cssPath), {recursive: true})
        //Render css from sass
        .then(() => sass.render({file: scssPath}))
        //Then write result css string to cssPath file
        .then(result => fs.writeFile(cssPath, result.css.toString()))
        .catch(error => console.error(error))
    }
    //Watch for changes to scssPath directory...
    fs.watch(path.dirname(scssPath), () => {
        //Render css from sass...
        sass.render({file: scssPath})
        //Then write result css string to cssPath file
        .then(result => fs.writeFile(cssPath, result.css.toString()))
        .catch(error => console.error(error))
        console.log(`Watching ${path.dirname(scssPath)}...`);      
    });
}

Mijn stapel

Software versie
OS Linux Mint 18.2 Sonya
Knooppunt 10.15.0
NPM 6.8.0
11ty 0.8.3

Het einde

Bedankt voor het lezen! :-)