Using a preprocessor in single file components (without a build step) - TotallyInformation/node-red-contrib-uibuilder GitHub Wiki
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.
Set up http-vue-loader
following the instructions on the Dynamically load .vue files without a build step page.
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.
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.
- From the uibuilder node's configuration, click "Manage front-end libraries".
- Add a new library with the package name
Sass.js
and install it.
Sass.js is now installed and available as vendor package.
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.
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.