Why a Webpack Loader
Webpack helps make frontend development more streamlined and recently, I wanted to transform YAML into CSS as part of the build process using the Preons library.
By the end of this article:
- you will create a Webpack loader that converts a YAML configuration file into CSS
- you will manually test the loader against a basic HTML page
- you will know how to create your own Webpack loader in future
Background
Preons (and disclaimer, a project of mine) is a functional CSS utility library. You configure the utility classes in YAML.
Webpack is a popular module bundler, and one helpful thing it does is transform Sass into CSS with a few useful community loaders.
Pre-requisites
To follow this tutorial, you need:
- Node 12+. Install Node's command-line tool.
- Yarn. Install Yarn's a command-line tool.
- Have a basic knowledge of javascript
Step 1: Creating a new project
You will create a basic empty project and initialise npm to begin installing local node packages.
Execute the following command to create a new project folder:
mkdir custom-webpack-loader && cd custom-webpack-loader
Initialise Node's package manager:
yarn init
You will be asked a series of questions:
yarn init v1.22.4
question name (custom-webpack-loader):
question version (1.0.0):
question description:
question entry point (index.js):
question repository url:
question author:
question license (MIT):
question private:
success Saved package.json
By the end, you will have a basic package.json
without any dependencies. But you'll add them in a few step.
Step 2 - Configuring Webpack
In this step, you will create a webpack configuration file and tweak it to load a YAML file. It will allow you to test the loader as if you were using it in a project.
Install Webpack and Webpack's CLI to give you access to the Webpack builder:
yarn add webpack webpack-cli
Next, you'll create the webpack.config.js
:
touch webpack.config.js
In webpack.config.js
, add:
const path = require("path");
module.exports = {
//...
mode: "development",
entry: path.resolve(__dirname, "fixtures") + "/preons.js",
module: {
rules: [
{
test: /\.ya?ml$/,
use: [
"style-loader",
"css-loader",
{
loader: path.resolve(__dirname, "lib") + "/loader.js"
},
"yaml-loader",
],
},
],
},
};
- The
mode
property tells Webpack to make optimisations based on environments. In production, however, you would change themode
toproduction
. However, for this use case, the default will bedevelopment
. - Notice how the
.module.rules[0].test
catches.yaml
and.yml
files based on regex rules. - The
entry
file points to a fixtures directory as that directory has files for you to test. - There are four loaders, 3 of which are existing npm packages. Webpack will apply rules from bottom to top, so first, the
yaml-loader
will take YAML and convert it into JSON. Your loader will transform Javascript into CSS; afterwards, thecss-loader
will apply its transformation and finally, thestyle-loader
takes css and puts it into style blocks that are inserted into your page through Webpack's script.
Install other dependency loaders using yarn:
yarn add style-loader css-loader yaml-loader
Now you have a basic Webpack config for testing the loader you're going to build.
Step 3 - Importing YAML from our input js file
When initially learning about Webpack, one of the strange conventions is not to deal with non-javascript files through the configuration. Instead, you import them as if they are javascript modules themselves. You'll do the same here.
First. Create the fixtures
directory:
mkdir fixtures
Next, you need a Preons config file. To save you from learning the syntax and configuring one yourself, install the Preons utility globally.
npm install preons -g
Generate the Preons YAML config:
preons config > fixtures/preons.yaml
You will see a YAML file containing CSS class rules such as theme-colors
, scales and percentages. The file contents should start like this:
preons:
baseline: 1.6rem
rules:
theme-colors:
black: "#000000"
white: "#ffffff"
transparent: transparent
hotpinkxl: "#f188bc"
Create fixtures/preons.js
.
touch fixtures/preons.js
Add a require expression to it, so you import the YAML through it.
require("./preons.yaml");
Now you have configured the webpack loader to take the fixtures/preons.js
file and run any YAML imports through the lib/loader.js
, and it will spit that back out inside a dist
folder. But before that, you'll need the loader.
Step 4 - Creating the loader
Now you can build the loader.js
. The minimum is one exported default function that returns a module.exports = <>
string.
First, create the loader.js
file:
mkdir -p lib && touch lib/loader.js
Add the basic method to test the loader is working:
module.exports = function (source) {
console.log(source)
return `module.exports = {}`;
};
At this point, you can run webpack, and you will see the YAML source load in:
npx webpack
The output will be a lot of JSON, because of the console.log(source)
. You'll also find a dist
folder in your project with a main.js
file.
With the source containing JSON, transforming using the Preons library is only a few more steps. Install Preons locally into the project to access its lib functions to do the transformation of the preons.yaml
into CSS:
yarn add preons
Change the lib/loader.js
to parse the YAML JSON into CSS.
const preons = require("preons/src/lib/stylesheet");
module.exports = function (source) {
let set = JSON.parse(source);
let css = preons({ set });
return `module.exports = ${css}`;
};
let set = JSON.parse(source)
converts JSON into a javascript object required by the Preonsstylesheet
function.let css = preons({ set });
is a Preons function that transforms the YAML into CSS.return
module.exports = ${css};
returns the css as a module to be used by the rest of the Webpack pipeline ruleset.
Now test your webpack pipeline by running:
npx webpack
If you look inside dist/main.js
, you will find the entirety of Preons CSS generated. To check the generation works, do a grep for the css Property bg-black
:
cat dist/main.js | grep "bg-black"
Step 5 - Testing the webpack loader with HTML
Now you are generating CSS from the Preons YAML configuration file. You will want to test you can develop with it.
Create a raw HTML index.html
file in the root of the project:
touch index.html
Then add a simple starter HTML5 file:
<!DOCTYPE html>
<html class="bg-black">
<head>
<link href="https://unpkg.com/browse/preons@0.4.5/dist/reset.css" rel="stylesheet" />
<script src="dist/main.js" ></script>
</head>
<body class="bg-red">
<h1>Hi</h1>
</body>
</html>
- The
index.html
references Preons reset package as well as yourdist/main.js
file. - The markup has Preons utility classes such as
bg-black
andbg-red
. Open theindex.html
, and it will look similar to this:
Finally, you want to test that we can make changes to our YAML and it produces CSS instantly.
Start the Webpack dev server to watch for changes using:
npx webpack --watch
Go into the preons.yaml
and look for the theme-color -> black
. Change it from black: "#000000"
to black: "yellow"
. The file should have this:
#....
rules:
theme-colors:
black: "yellow"
Refresh the page, and the bg-black
rule is now yellow
.
Ok. You will want to keep bg-black
as it was, but it's just to prove that the generation runs through Webpack. You can now add more colours, change colours or remove them. Of course, you can add any utilities you want using the configuration file. The documentation on how to use the configuration file is still under development, but I'll remember to add it here once it's done.
Conclusion
You built a Webpack loader to ingest YAML and create CSS to be used as part of a development and production build. You used pre-existing modules (e.g. yaml-loader) to keep your module loader concise.
If you want to continue using Preons, look out for the Preons webpack loader package, so you won't have to maintain it yourself.
Do you have any ideas for your own for a webpack loader?
Also, I hope you enjoyed this article. I'd love feedback on how to improve as a writer and as a developer, so feel free to leave a comment or DM me on Twitter.