How to customize Semantic UI with React, MiniCssExtractPlugin, LESS and Webpack 4? 
Published: 2020-02-11 08:29:03

###Introduction
This tutorial assumes that you already know how to set up a basic react app and webpack. 

Setting up [Semantic UI](https://react.semantic-ui.com/) and extending/overriding the default themes with your custom styles in a React app can give you a bad day if not done carefully.

On the webpack side, after `ExtractTextPlugin` was deprecated and replaced with `MiniCssExtractPlugin`, configuring your webpack to recognise your Semantic UI less and fonts can also be a pain if you haven't done that before. 

This tutorial can help you get started within a few minutes, it can also work with [Fomantic UI Less](https://github.com/fomantic/Fomantic-UI-LESS).

Code for this tutorial can be found on [https://github.com/kudakwashegore/custom-semanticui-react](https://github.com/kudakwashegore/custom-semanticui-react)

###Dependencies
First things first, a basic setup will require installation of the following dependencies (I use npm, yarn can also work). 

`npm i -D mini-css-extract-plugin semantic-ui-less less@2.7.3 less-loader css-loader url-loader`

`npm i -S semantic-ui-react`

**Please note the version of `less` used (2.7.3). Later versions will give you endless nightmares.** 

I also deliberately used `url-loader` instead of `file-loader`, `file-loader` will give you issues when you want to use your favourite Semantic UI `<Icon />`. 

###Folder Structure
Assuming the following project structure, you can always update your code to match your folder structure.

```
node_modules/
app/
  app.js
  index.html
my-custom-semantic-theme/
webpack.config.js
package.json
```

###Webpack
Below are some additional webpack configuration that you need to add in your webpack configuration file.

```
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');

module.exports = {
    resolve: {
      alias: {
        '../../theme.config$': path.join(
          __dirname,
          '../my-custom-semantic-theme/theme.config',
        ),
      },
    },
    module: {
      rules: [
        {
          test: /\.less$/,
          use: [
            {
              loader: MiniCssExtractPlugin.loader,
            },
            'css-loader',
            'less-loader',
          ],
        },
        {
          test: /\.woff($|\?)|\.woff2($|\?)|\.ttf($|\?)|\.eot($|\?)|\.svg($|\?)/,
          use: 'url-loader',
        }
      ],
    },
    plugins: [
      new MiniCssExtractPlugin({
        filename: 'styles/[name].[contenthash].css',
      }),
    ],
  };

```

###Semantic UI
* Go on [https://github.com/Semantic-Org/Semantic-UI-LESS](https://github.com/Semantic-Org/Semantic-UI-LESS) and download the repo into your `my-custom-semantic-theme/` folder. 
* Rename file `theme.config.example` to `theme.config`. 
* Rename _site folder to site
* Delete other folders and files in your `my-custom-semantic-theme/` folder and remain with 

  ```
  my-custom-semantic-theme/
      site/
      theme.config
      theme.less
  ```
* Open `theme.config` and have the last lines match the following
  ```
   /*******************************
            Folders
   *******************************/

   /* Path to theme packages */
   @themesFolder : 'themes';

   /* Path to site override folder */
   @siteFolder  : '../../my-custom-semantic-theme/site';


   /*******************************
         Import Theme
   *******************************/

   @import (multiple) "~semantic-ui-less/theme.less";

   @fontPath : "../../../themes/@{theme}/assets/fonts";

   /* End Config */
  ``` 

###App
We are almost ready. Below is an example of a basic app.js using `semantic-ui-react` components.

 ```
  import React from 'react';
  import ReactDOM from 'react-dom';
  import { Icon, Button, Segment, Label } from 'semantic-ui-react';
  import 'semantic-ui-less/semantic.less'; // if you do this once in your entry point file, you don't have to do it again in other files.

  ReactDOM.render(
  <Segment>
    <p>Hello semantic-ui button with icon</p>
    <Button as='div' labelPosition='right'>
      <Button color='red'>
        <Icon name='heart' />
        Like
      </Button>
      <Label as='a' basic color='red' pointing='left'>
        2,048
      </Label>
    </Button>
  </Segment>,
  document.getElementById('appRoot'),
);
 ```

###Testing our app
We are now ready to test if semantic-ui-less is correctly setup. Do the `npm start` thing. 

To check if you can now override the default semantic-ui styles with your own, open `/my-custom-semantic-theme/site/elements/button.variables` and add the following line

`@backgroundColor: green;`

Refresh your app and you should see your button background color changing to brown.

You can download example code on [https://github.com/kudakwashegore/custom-semanticui-react](https://github.com/kudakwashegore/custom-semanticui-react)