This week, I read this article explaining how CSS-in-JS slow down the rendering of some react apps and how static CSS is faster.
CSS-in-JS is very popular because, among others, you can style dynamically using javascript variables.

In this tutorial, I will show you how to recreate this perk in any of your web project thanks to Webpack (and I assume you know how to use it).
We want webpack to bundle our source files into a static dist/ folder .

source code

1. Setup our app.

The boring part.
Create a folder for this tutorial, open your terminal and init a project.

npm init -y

First things first, if it’s not already done, install node.js and Webpack:

npm install webpack webpack-cli --save-dev

Let’s create a script in our package.json that tells webpack to use our config file.

  "scripts": {
    "build": "webpack --config webpack.config.js"
  }

At the root of your folder, create a globals.js file,  where our shared variables will be stored.

module.exports = {
  myTitle: 'Hello dev.to !',
  myColor: '#42ff87',
};

The webpack config file looks like this (webpack.config.js), create it at the root of your folder.

module.exports = {
  entry: __dirname + '/app/index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'index_bundle.js'
  },
};

Our source code will be located in a app folder, create it :

mkdir app && cd app

You’ll need an index.html and index.js files at this point. Create those files in the app folder :

touch index.html index.js

Perfect !  You’re all set. 🚀
Your folder should look like this:

|-- node_modules/
|-- package.json
|-- webpack.config.js
|-- globals.js
|-- app/
	|-- index.html
	|-- index.js

2. Render our HTML files with the html-webpack-plugin

This app/index.html is empty, let’s add some markup in it and add a custom variable !

<html lang="en">
<head>
  <title>Webpack shared variables!</title>
</head>
<body>
  <h1><%= myTitle %></h1>
</body>
</html>

As you can see we are trying  to print a variable in our HTML… which is impossible ! To make it work we’ll use the html-webpack-plugin that give us the possibility to use ejs syntax and Inject data into it.

The plugin will generate a valid html file, in the meantime, you should rename your app/index.html into app/index.ejs.

npm install --save-dev html-webpack-plugin

Let’s go back to our configuration file, html-webpack-plugin has an interesting templateParameters option that allows us to pass an object as parameter. Enable the plugin as follows in webpack.config.js:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const globals = require('./globals.js')

module.exports = {
	// ... previous config, entry, output...
  plugins: [
    new HtmlWebpackPlugin({
      template: 'app/index.ejs',
      templateParameters: globals,
    })
  ]
};

Run npm run build and Tadaaaaa « <%= myTitle %> » became « Hello dev.to » ! The work is done by webpack during the compilation when he runs the html-webpack-plugin.

See ? This was pretty simple with the right tool !
HTML ✅

2.  Use our variables in javascript

Phew, so many lines to print a variable ! 😱 with webpack, things often get complicated … well, this one is very simple: in javascript just import your file ! In your app/index.js:

import globals from '../globals.js'

document.write(
'<pre>' +
  JSON.stringify(globals, null, 2) +
'</pre>'
);

This will print our globals object on the page, let’s move on to the CSS !

3. Use shared variables in our CSS

Here is our final boss 👾

Okay guys you got me… I lied ! We can’t use our globals directly in the CSS, we must use a pre-processor. In this example, we will use SASS.

On the webpack side, a plugin will not be enough, we must use a loader, to convert SASS into CSS. In this case we need the sass-loader, install it following the doc:

npm install sass-loader node-sass css-loader style-loader --save-dev

Back to coding ! Now that we have SASS, create your stylesheet file : app/style.scss :

h1 {
  color: $myColor;
}

Our SASS is setup, now how can we inject data into it ?  The sass-loader has a prependData option ! But it takes a string as parameter, which means that your data should look like this: "$myColor: red; myTitle: '...'";.

We have to automate that: convert a javascript object into a string. I didn’t found a package on npm that satisfies me so I wrote my own converter. Download the file and add it to your project (in my example utils/jsToScss.js).

Your final webpack.config.js:

const globals = require("./globals.js");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const jsToScss = require("./utils/jsToScss.js");

module.exports = {
  entry: __dirname + "/app/index.js",
  output: {
    path: __dirname + "/dist",
    filename: "index_bundle.js"
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "app/index.ejs",
      templateParameters: globals
    })
  ],
  module: {
    rules: [
      {
        test: /.s[ac]ss$/i,
        use: [
          // Creates `style` nodes from JS strings
          "style-loader",
          // Translates CSS into CommonJS
          "css-loader",
          // Compiles Sass to CSS
          {
            loader: "sass-loader",
            options: {
              prependData: jsToScss(globals)
            }
          }
        ]
      }
    ]
  }
};

Here is what you should see:

https://glitch.com/edit/#!/shared-variables-webpack?path=webpack.config.js

If you are still reading this long tutorial, thanks for your attention, hope it helps you ! Webpack is a very powerful tool you should dig it 🧐

NB: In your dist/ folder you can see there isn’t any CSS generated. That’s because I use the style-loader to keep this demo simple. To generate the CSS file take a look at the mini-css-extract-plugin.



Source link

LEAVE A REPLY

Please enter your comment!
Please enter your name here