Skip to content

Passing Themes to Sass Through Node

esr360 edited this page Feb 9, 2020 · 9 revisions

If your project uses themes, you can expose them to Sass using Synergy-Sass-Importer. Some setup to your local environment is required to ensure Node exposes your themes to Sass (as well as to ensure hot-reloading works properly).

You can alternatively import your themes directly into your Sass files (learn more)

Webpack Config

Under-the-hood, Synergy-Sass-Importer looks for a Synergy object attached to Node.js's global object. You can set this up in your webpack config file.

ES6
import webpack from 'webpack';
import SassJSONImporter from '@onenexus/synergy-sass-importer';
import THEME from 'PATH/TO/THEME';

global.Synergy = { THEME }

// Webpack function
export default function(env) {
  ...
}
CommonJS
var webpack = require('webpack');
var SynergySassImporter = require('@onenexus/synergy-sass-importer');

global.Synergy = {
  THEME: require('PATH/TO/THEME')
}

module.exports = {
  ...
}

Now inside your Sass, $theme will be defined.

Hot-Reloading

Using Webpack and Webpack Dev Server, if you utilise hot-reloading you will want your app's styles to recompile whenever you save your theme or module's configuration. This means that you must update the global.Synergy object before your app re-compiles. Webpack Hooks are a good solution for this (particularly the compile hook).

In addition to this, your theme and config files must be deleted from Node's require.cache. Synergy-Sass-Importer handles the deletion of your config file, but you must handle the deletion of the theme file yourself (which is trivially easy to do as seen in the following example).

A full example of a server.js file to handle all of this might look like:

require('@babel/register')();

const webpack = require('webpack');
const webpackDevServer = require('webpack-dev-server');
const webpackConfig = require('./webpack.config.babel').default();
const compiler = webpack(webpackConfig);

compiler.plugin('compile', () => {
  global.Synergy = { 
    THEME: requireUncached('./src/themes/myTheme').default
  }
});

new webpackDevServer(compiler, {
  publicPath: webpackConfig.output.publicPath,
  hot: true,
  contentBase: './dist',
  historyApiFallback: true
}).listen(3000, 'localhost', function(error, result) {
  if (error) {
    return console.log(error);
  }

  console.log('Listening at http://localhost:3000/');
});

function requireUncached(module){
  delete require.cache[require.resolve(module)];
  return require(module);
}