Skip to content

Using a preprocessor in single file components (without a build step)

Lena Derksen edited this page Aug 22, 2019 · 4 revisions

Vue single file components support the usage of using different processors than the default HTML for templates, JavaScript for the script, and CSS for the style. To do so, you can add the lang="<processor name>" attribute to the outer tag. For example, to use SCSS instead of CSS, use <style lang="scss">. Below follows a non-exhaustive list of boilerplates to set up pre-processing capabilities for each type.

Prerequisites

Set up http-vue-loader following the instructions on the Dynamically load .vue files without a build step page.

SCSS

To add SCSS support, you will need Sass.js. This functions as a browser-based compiler for SASS/SCSS. It is fairly heavy, and users may experience this in the load times. However, while the Sass.js instructions describe that users on Node should use node-sass instead, this won't work if you are creating a frontend without a build step.

Compatibility

Because the boilerplate uses Promise.all() as well as the Fetch API, it is not compatible with Internet Explorer. It could be set up without the Fetch API and use plain XHR requests instead, however to make it compatible the Promise.all() would have to be replaced with a jquery based setup, adding jquery as a dependency. If you need Internet Explorer support, take a look at this Stack Overflow question where most of the code below was inspired by. Please note that I do not have access to Internet Explorer at this moment and have neither tested nor checked if any of the other code prevents it to work.

Installation

  1. From the uibuilder node's configuration, click "Manage front-end libraries".
  2. Add a new library with the package name Sass.js and install it.

Sass.js is now installed and available as vendor package.

Boilerplate HTML

Add the Sass.js vendor library below the http-vue-loader library in the index.html file, like this:

<script src="../uibuilder/vendor/http-vue-loader/src/httpVueLoader.js"></script> <!-- http-vue-loader -->
<script src="../uibuilder/vendor/sass.js/dist/sass.js"></script> <!-- scss support -->

Do note that the exact order between these two is not important, but for readability http-vue-loader above makes most sense, as in the rest of the setup, the usage of Sass.js is dependent on http-vue-loader.

Boilerplate JS

Following the instructions on the http-vue-loader page, to add a language processor it is needed to add it to httpVueLoader itself. To have the Sass.js compile the SCSS files, it needs its own boilerplate as well. To have Sass.js deal with imports in the SCSS segments, they need to be defined as virtual files. The code below sets up a basis, with two virtual files defined for overriding the themes of Bootstrap components.

/* HTTP-Vue-Loader boilerplate: Setting up SCSS loader */
var virtualScssFileDefs = {
    // Format: file name (how you @import them in scss) : relative path for where it is located
    "../uibuilder/vendor/bootstrap/scss/_variables.scss": '../uibuilder/vendor/bootstrap/scss/_variables.scss',
    "../uibuilder/vendor/bootstrap/scss/_functions.scss": '../uibuilder/vendor/bootstrap/scss/_functions.scss',
};

function promisifyScssFileDefs(name, url) {
    return new Promise(function(resolve, reject) {
        fetch(url).then(function(resp) {
            return resp.text();
        }).then(function(data) {
            resolve({
                name: name,
                scss: data,
            });
        });
    });
}

httpVueLoader.langProcessor.scss = function (scssText) {
    console.log('Getting started...');
    console.log(scssText);
    return new Promise(function(resolve, reject) {
        var promises = [];
        for (name in virtualScssFileDefs) {
            promises.push(promisifyScssFileDefs(name, virtualScssFileDefs[name]));
        }
        Promise.all(promises).then(function(data) {
            // Data as array of objects, each object in format {"name": <virtual file name>, "scss": <scss text>}
            var sass = new Sass();
            data.forEach(function(item) {
                sass.writeFile(item.name, item.scss);
            });

            sass.compile(scssText, function (result) {
                if ( result.status === 0 ) {
                    resolve(result.text);
                }
                else {
                    reject(result);
                }
            });
        });
    });
};

The virtualScssFileDefs variable contains the files it has to resolve. The name is how it would be imported in SCSS. For the _variables.scss this would be called as @import ../uibuilder/vendor/bootstrap/scss/_variables.scss. This value can actually be whatever you want, but since it is executed in the browser, using the full relative path as name will prevent errors from showing in the browser console. This block of code has to be added to the outermost JavaScript code before the root instance is defined. It only needs to be added once, child components that use SCSS will be able to use it as well. Do remember that browser based compiling is in fact slow, and the component might take a while to load.

Clone this wiki locally