Info

The ctr-loader turns up the ctr volume to eleven. I’m going to assume right off the bat you’re familiar with Webpack and the concept of loaders within its context. If not, I recommend you first read up on Webpack because trying to jury-rig webpack is a recipe for disaster. Also, I know I’m beating a dead horse, but ctr is not a run-time CSS in JS solution thus the reason for the ctr-loader.

The ctr-loadershould ” fit seamlessly into any CSS pipeline as a complete or progressive replacement. The loader packages up the entirety of ctr along with the Javascript API and delivers it to you with a bow on top. Albeit I will warn you from the outright the ctr-loader will definitely increase the complexity of your pipeline quite a bit depending on your use case.

At this stage of the game, I have yet to give the ctr-loader a real go out in the field. My current experience with the loader is limited to writing the tests to validate its mechanics. This means you’re on your own for best practices like the American frontier, so God speed. Regardless of your findings, good or bad, I encourage you to share them.

Outside of the basic setup and concepts I’ve created a plethora of tests you can scope out in the GitHub ctr-loader repository that test, experiment, and demonstrate various workflows and integrations.

webpack.config.js

Description: The ctr-loader needs to be chained with the style-loader and the css-loader but can also be chained with other loaders such as postcss-loader to autoprefix styles.

webpack.config.js

// Default webpack.config.js
module.exports = {
// ...
module: {
rules: [{
test: /\.ctr(\.js|\.yml|\.yaml)$/,
use: ['style-loader', 'css-loader', 'ctr-loader']
}]
}
// ...
};
// ExtractTextPlugin webpack.config.js
module.exports = {
// ...
module: {
rules: [{
test: /\.ctr(\.js|\.yml|\.yaml)$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'ctr-loader']
})
}]
},
plugins: [
new ExtractTextPlugin('styles.css')
]
// ...
};

Notes

Mode of Operation

The mode of operation for the ctr-loader can seem a bit abstracted, but in reality, it’s as straightforward as it gets. The loader simply executes the [filename].ctr.js, passing two arguments to the exported Function, a global ctr instance and requireWatch. Upon execution, the ctr-loader expects a return of a String which is assumed to be CSS, although, if a String is not returned the return is disregarded. For the sake of demonstration, first let’s use the ctr-loader without actually using ctr.

// index.js (webpack entry point)
require('./styles.ctr.js');
// styles.ctr.js
module.exports = function () {
// the CSS we wish to create
const myCSS = 'body {background: red;}';
return myCSS;
};

Boom! Like magic we have a background of red. In the above example, we are simply declaring in index.js that we wish to use the CSS styles located in styles.ctr.js. That’s it; it’s truly that simple. Let’s now do the same thing using ctr. Remember, the ctr-loader passes a global ctr instance to use as the first argument.

// index.js (webpack entry point)
require('./styles.ctr.js');
// styles.ctr.js
module.exports = function (ctr) {
// create the style via ctr
ctr.create({
background: 'red'
});
// get the ctr results
const myCSS = ctr.getResult();
return myCSS;
};

Boom! Like magic we have a background of red, but this time it the CSS style was made using ctr. The ctr instance that is passed to the styles.ctr.js file is a global ctr instance initialized in the ctr-loader. The reasoning behind this operation is to allow all ctr styles to be memoized so you can go Fast And Furious Five fast.

In case you’re not familiar with “how” loaders compile in general, the styles.ctr.js file is being compiled via node through webpack. What this means is if you needed to debug styles.ctr.js you can not just plop a debugger statement in a style file and catch the breakpoint in the browser. Rather you must use a node debugging tool like Visual Studio Code’s built-in debugger or an external tool. You can check out a list of node debugger tools here. However, hands down I recommend iron-node or devtool, but I fucking love iron-node, it’s one of my most trusted and used tools on my tool belt.

requireWatch

Description: The requireWatch Function is a wrapper around webpack’s addDependency method. Similar to require, requireWatch is used to require ctr styles, however, unlike require it tells webpack “hey, if this file is changed recompile my results.” Through the requireWatch Function a project can be setup similar to that of a CSS preprocessor structure.

Parameters

Arguments

// String
module.exports = function (ctr, requireWatch) {
ctr = requireWatch('./box-style.ctr.js');
ctr = requireWatch('./circle-style.ctr.js');
// get the ctr results
const myCSS = ctr.getResult();
return myCSS;
};
// [String, String]
module.exports = function (ctr, requireWatch) {
ctr = requireWatch(['./box-style.ctr.js', './circle-style.ctr.js']);
// get the ctr results
const myCSS = ctr.getResult();
return myCSS;
};

Notes

Loader Options

Description: Technically you should not need to use these options because they smell pretty bad.

Arguments

// Default webpack.config.js
module.exports = {
// ...
module: {
rules: [{
test: /\.ctr(\.js|\.yml|\.yaml)$/,
use: [{
loader: 'style-loader'
}, {
loader: 'css-loader'
}, {
loader: 'ctr-loader'
option: {
newInstance: false,
context: 'special.context.path',
warning: true
}
}]
}]
}
// ...
};