React+Webpack1/2/3+Semantic UI and how to do theming
Semantic UI is a great UI framework which can make your UI development much easier, but it’s still not a joyful job to make it work with webpack especially for theming.
This tutorial works for both webpack 1/2/3, though you need to make small change just to follow webpack2/3’s syntax. For the main differences for webpack2/3, scroll to the bottom!
Use Semantic-UI without theming
If you just want to use Semantic-UI with your Webpack-React project, it’s quite easy.
You only need to follow two steps:
npm install semantic-ui-react --save(see semantic-ui-react)- Since the
semantic-ui-reactdoes not include style, you can use the default Semantic UI stylesheet by including a Semantic UI CDN link in your index.html file.
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.2/semantic.min.css"></link>
Just create a simple button in your code to test if it is working:
import React from 'react';
import { Button } from 'semantic-ui-react';
const ButtonExampleButton = () => (
<Button>
Click Here
</Button>
)
export default ButtonExampleButton
Instead of using a Semantic UI CDN link, you can manually handle the CSS by yourself, just:
npm install semantic-ui-CSS --save- In your entry file, include the entry file:
// app.js
import 'semantic-less-css/semantic.css';
Remember to turn off the “CSS-Module” functionality for .css file. And notice that both using CDN or semantic-ui-css do not provide the theming feature.
Theming
To be able to use the theming feature, you need to use semantic-ui-less. It’s a pure less part of Semantic UI aiming to help you get rid of all the unnecessary dependencies from Semantic-UI.
npm install semantic-ui-less --save
And since it’s Less, and there are also Icon Fonts involved in this module, make sure your webpack can handle them well:
// webpack configs:
.....
loaders: [
{
test: /\.less/,
loader: 'style!css!less',
},
{
test: /\.(png|jpg|gif|woff|svg|eot|ttf|woff2)$/,
loader: 'url-loader?limit=1024&name=[name]-[hash:8].[ext]!image-webpack',
},
],
...
Before we start the work, let’s take a look at the project structure (you can check out the demo project):
app/
-- index.js
-- index.html
-- semantic-ui/ // all the semantic-ui related files
----- site/ // theming related files
webpack.config.js
package.json
rewrite less import for ../../theme.config
semantic-ui-less tries to import a file that does not exist( node_modules/semantic-ui-less/theme.config ), this file includes some key variables used throughout the whole module.
So first of all, you need to create a theme.config by yourself ( create a directory named semantic-ui in your project root):
app/semantic-ui
- theme.config
And copy the content of node_modules/semantic-ui-less/theme.config.example into theme.config and remember to do a import path fix, change @import "theme.less" to @import "~semantic-ui-less/theme.less":
Also don’t forget to change the @siteFolder to your folder:
@siteFolder : '../../app/semantic-ui/site';
After that, we can use a Less plugin to make the ../../theme.config refer to our own theme.config. Let’s intall the module first:
npm install less-plugin-rewrite-import --save-dev
Then add the configuration to webpack.config.js:
const RewriteImportPlugin = require("less-plugin-rewrite-import");
... below is just part of the webpack config
essLoader: {
lessPlugins: [
new RewriteImportPlugin({
paths: {
'../../theme.config': __dirname + '/app/semantic-ui/theme.config',
},
}),
],
},
...
You can now import the main entry of semantic-ui-less from /app/index.js:
import "semantic-ui-less/semantic.less";
Anyway, you will still get build error complaining about that it can’t find font files.
Fix @fontPath error
What you need to do is just add one line of code showed bellow at the bottom of your theme.config ( make sure it’s bellow the line that imports theme.less ):
@fontPath : '../../../themes/@{theme}/assets/fonts';
Now the build process should work like a charm.
Setup customization for your site
Create extra structure for your semantic-ui directory:
/semantic-ui
- theme.config
- site/
Most of custom style code goes into site/ folder, the structure will be like this:
site/
- collections/
- elements/
- globals/
- modules/
- views/
To verify whether the customisation is working, just create /app/semantic-ui/site/elements/button.variables and change background color for all buttons:
@backgroundColor: yellow;
Put a button into your page /app/index.ejs to see if it works:
<div class="ui button">Button</div>

Yellow Button
If you see the same, it works.
Theming for Webpack2 / 3
For those working with Webpack2 or 3, except for general syntax change, there’re two differences you need to make for the theming to work. (Thanks for @MarkPerryBV’s idea from this issue)
Use less-resolver
By default, less-loader will use webpack’s resolver to resolve all the less files, making plugins like less-plugin-rewrite-import fail to handle less files. That’s why you will find the plugin not working for webpack2.
To make less-loader use its own resolver, you need to manually specify option paths for it to search, your config should be:
{
loader: 'less-loader',
options: {
paths: [ROOT_DIR, NODE_MODULES_DIR], // this will force less-loader to use its own resolver, both should be absolute path
plugins: [
new RewriteImportPlugin({
paths: {
'../../theme.config': __dirname + '/app/semantic-ui/theme.config',
},
}),
],
},
},
You can get more details about less resolver from here
Remove ~ in your theme.config
Since now we are using less resolver, we are not able to use ~ to refer modules in the node_modules anymore, so open your theme.config and change the @import "~semantic-ui-less/theme.less"; to @import "semantic-ui-less/theme.less";
For more specific example, checkout my example project: demo-semantic-ui-theming-with-webpack2
Comments