The Many Faces of CSS
I started with vanilla CSS – inline styles, <style> tags in the head, and dedicated .css files. It worked, but repetition was killing me.
Then I discovered preprocessors: Less, Sass, and Stylus. They reduced boilerplate dramatically. Nesting, variables, mixins – I loved them.
Bootstrap: The First Library I Truly Hated
When I tried Bootstrap, something snapped. It wasn't flexible. I wanted to customize everything, but Bootstrap fought me at every turn. That was the first time I genuinely hated a library in my frontend journey.
Tailwind CSS: The One That Fits My Brain
Then I touched Tailwind CSS – utility‑class based. It clicked immediately. No more context switching between files. No more inventing class names. I never used another styling library after that. I've stuck with Tailwind to this day.
The Webpack Configuration Pain
Back then, to integrate these libraries I had to mess with Webpack – install loaders, edit configs, and pray. I learned some Webpack configuration from their docs and even made my own template. It was a pain.
Here's are of the configs I used to write:
- webpack.common.js - common config that i.e imported and used in both dev and prod
// webpack.common.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
index: {
import: "./src/index.js",
},
},
output: {
filename: "[name].[contenthash].js",
path: path.resolve(__dirname, "dist"),
clean: true,
},
module: {
rules: [
{
test: /\.less$/i,
use: ["style-loader", "css-loader", "less-loader"],
},
{
test: /\.styl$/i,
use: ["style-loader", "css-loader", "stylus-loader"],
},
{
test: /\.s[ac]ss$/i,
use: ["style-loader", "css-loader", "sass-loader"],
},
{
test: /\.(css)$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|gif|jpg|jepg|svg|woff|woff2|eot|ttf|otf)$/i,
type: "asset/resource",
},
{
test: /\.(?:js|mjs|cjs)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [["@babel/preset-env", { targets: "> 0.25%, not dead" }]],
},
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
],
optimization: {
moduleIds: "deterministic",
runtimeChunk: "single",
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: "vendors",
chunks: "all",
},
},
},
},
};- webpack.dev.js - development config overriding
// webpack.dev.js
const { merge } = require("webpack-merge");
const common = require("./webpack.common");
module.exports = merge(common, {
mode: "development",
devtool: "inline-source-map",
devServer: {
static: "src",
},
});- webpack.prod.js - production side config overriding
// webpack.prod.js
const { merge } = require("webpack-merge");
const common = require("./webpack.common");
module.exports = merge(common, {
mode: "production",
devtool: "source-map",
});Major Projects From My Journey
These are the key projects I built while working through The Odin Project:
And there are many more in my projects gallery!
Related Blog Posts
- The Todo List Project: Building My Own React-like Library (coming soon)
- My Modern Styling Defacto (coming soon)
Now Thanks to Evan You, I use vite and configure it as much as I want with ease!