TLDR: Personal experience of a minimalist. I bit the bullet and upgraded from my extremely vanilla stack of choice. I tried React for a couple days. I tried Angular for a couple of hours. I tried Vue and it clicked near instantly. It’s now my stack of choice.
Background
I’m very much a minimalist. My motto for web development is different variations of less is more and don‘t fix what isn‘t broken. The Javascript ecosystem changes so frequently that it could probably be it‘s own separate field of study. I don‘t chase the flavor of the week.
I’ve used server side web frameworks before (.Net primarily). I dropped that in favor of going serverless with microservices when needed. Then I dropped back to working with just using bootstrap, html, jquery and various css libraries as my front end stack (I also got tired of slow IDEs and dropped down to writing code in Notepad++ for a time. I am now somewhat satisfied using VS Code).
I could ignore it at first but React was getting to the point that it was everywhere. I was beginning to feel left out. The turning point was when I discovered Material UI, but then I saw it was first-class React. That was about the last straw. I was already working on some front end code so I figured I’d at least try it out.
React
I tend to dive head first into learning a new technology. I was working on a quick mockup so I figured it’d be okay to skip the basic React tutorial and go straight to the Material UI tutorial. Big mistake.
React Card Component
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import clsx from 'clsx';
import Card from '@material-ui/core/Card';
import CardHeader from '@material-ui/core/CardHeader';
import CardMedia from '@material-ui/core/CardMedia';
import CardContent from '@material-ui/core/CardContent';
import CardActions from '@material-ui/core/CardActions';
import Collapse from '@material-ui/core/Collapse';
import Avatar from '@material-ui/core/Avatar';
import IconButton from '@material-ui/core/IconButton';
import Typography from '@material-ui/core/Typography';
import { red } from '@material-ui/core/colors';
import FavoriteIcon from '@material-ui/icons/Favorite';
import ShareIcon from '@material-ui/icons/Share';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import MoreVertIcon from '@material-ui/icons/MoreVert';
const useStyles = makeStyles((theme) => ({
root: {
maxWidth: 345,
},
media: {
height: 0,
paddingTop: '56.25%', // 16:9
},
expand: {
transform: 'rotate(0deg)',
marginLeft: 'auto',
transition: theme.transitions.create('transform', {
duration: theme.transitions.duration.shortest,
}),
},
expandOpen: {
transform: 'rotate(180deg)',
},
avatar: {
backgroundColor: red[500],
},
}));
export default function RecipeReviewCard() {
const classes = useStyles();
const [expanded, setExpanded] = React.useState(false);
const handleExpandClick = () => {
setExpanded(!expanded);
};
return (
<Card className={classes.root}>
<CardHeader
avatar={
<Avatar aria-label="recipe" className={classes.avatar}>
R
</Avatar>
}
action={
<IconButton aria-label="settings">
<MoreVertIcon />
</IconButton>
}
title="Shrimp and Chorizo Paella"
subheader="September 14, 2016"
/>
<CardMedia
className={classes.media}
image="/static/images/cards/paella.jpg"
title="Paella dish"
/>
<CardContent>
<Typography variant="body2" color="textSecondary" component="p">
This impressive paella is a perfect party dish and a fun meal to cook together with your
guests. Add 1 cup of frozen peas along with the mussels, if you like.
</Typography>
</CardContent>
<CardActions disableSpacing>
<IconButton aria-label="add to favorites">
<FavoriteIcon />
</IconButton>
<IconButton aria-label="share">
<ShareIcon />
</IconButton>
<IconButton
className={clsx(classes.expand, {
[classes.expandOpen]: expanded,
})}
onClick={handleExpandClick}
aria-expanded={expanded}
aria-label="show more"
>
<ExpandMoreIcon />
</IconButton>
</CardActions>
<Collapse in={expanded} timeout="auto" unmountOnExit>
<CardContent>
<Typography paragraph>Method:</Typography>
<Typography paragraph>
Heat 1/2 cup of the broth in a pot until simmering, add saffron and set aside for 10
minutes.
</Typography>
<Typography paragraph>
Heat oil in a (14- to 16-inch) paella pan or a large, deep skillet over medium-high
heat. Add chicken, shrimp and chorizo, and cook, stirring occasionally until lightly
browned, 6 to 8 minutes. Transfer shrimp to a large plate and set aside, leaving chicken
and chorizo in the pan. Add pimentón, bay leaves, garlic, tomatoes, onion, salt and
pepper, and cook, stirring often until thickened and fragrant, about 10 minutes. Add
saffron broth and remaining 4 1/2 cups chicken broth; bring to a boil.
</Typography>
<Typography paragraph>
Add rice and stir very gently to distribute. Top with artichokes and peppers, and cook
without stirring, until most of the liquid is absorbed, 15 to 18 minutes. Reduce heat to
medium-low, add reserved shrimp and mussels, tucking them down into the rice, and cook
again without stirring, until mussels have opened and rice is just tender, 5 to 7
minutes more. (Discard any mussels that don’t open.)
</Typography>
<Typography>
Set aside off of the heat to let rest for 10 minutes, and then serve.
</Typography>
</CardContent>
</Collapse>
</Card>
);
}Cue 3 days of going down a rabbit hole trying to figure out:
- Is this Javascript? (Me being relatively new to ES6 and lodash at the time)
- Why is there HTML in Javascript?
- Redux, JSX, Babel, Webpack
And then I gave up.
Angular
Banging my head on the wall trying to get React to work left me very little mental bandwidth to try Angular. I believe I also went straight to Angular’s version of Material UI. The seperation of HTML and Javascript was a bit of a relief but I got tired of having a bunch of files floating around. I gave up pretty quickly. I’d like to give it another shot at some point.
Angular Card HTML
<mat-card class="example-card">
<mat-card-header>
<div mat-card-avatar class="example-header-image"></div>
<mat-card-title>Shiba Inu</mat-card-title>
<mat-card-subtitle>Dog Breed</mat-card-subtitle>
</mat-card-header>
<img mat-card-image src="https://material.angular.io/assets/img/examples/shiba2.jpg" alt="Photo of a Shiba Inu">
<mat-card-content>
<p>
The Shiba Inu is the smallest of the six original and distinct spitz breeds of dog from Japan.
A small, agile dog that copes very well with mountainous terrain, the Shiba Inu was originally
bred for hunting.
</p>
</mat-card-content>
<mat-card-actions>
<button mat-button>LIKE</button>
<button mat-button>SHARE</button>
</mat-card-actions>
</mat-card>Angular CSS
.example-card {
max-width: 400px;
}
.example-header-image {
background-image: url('https://material.angular.io/assets/img/examples/shiba1.jpg');
background-size: cover;
}Vue
I went directly to Vue‘s Material UI yet again. What I immediately liked about Vue was the fact that everything related to a component is all in one file. The HTML had it’s section, same with the Javascript and CSS. I already had a habit of throwing everything in one file, so having that as the proper way to do things was a breath of fresh air. I was able to be productive almost immediately.
Vue Card Component
<template>
<div class="card-expansion">
<md-card>
<md-card-media>
<img src="/assets/examples/card-image-1.jpg" alt="People">
</md-card-media>
<md-card-header>
<div class="md-title">Title goes here</div>
<div class="md-subhead">Subtitle here</div>
</md-card-header>
<md-card-expand>
<md-card-actions md-alignment="space-between">
<div>
<md-button>Action</md-button>
<md-button>Action</md-button>
</div>
<md-card-expand-trigger>
<md-button class="md-icon-button">
<md-icon>keyboard_arrow_down</md-icon>
</md-button>
</md-card-expand-trigger>
</md-card-actions>
<md-card-expand-content>
<md-card-content>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Optio itaque ea, nostrum odio. Dolores, sed accusantium quasi non, voluptas eius illo quas, saepe voluptate pariatur in deleniti minus sint. Excepturi.
</md-card-content>
</md-card-expand-content>
</md-card-expand>
</md-card>
<md-card>
<md-card-media>
<img src="/assets/examples/card-image-1.jpg" alt="People">
</md-card-media>
<md-card-header>
<div class="md-title">Title goes here</div>
<div class="md-subhead">Subtitle here</div>
</md-card-header>
<md-card-expand>
<md-card-actions md-alignment="space-between">
<div>
<md-button>Action</md-button>
</div>
<md-card-expand-trigger>
<md-button>Learn more</md-button>
</md-card-expand-trigger>
</md-card-actions>
<md-card-expand-content>
<md-card-content>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Optio itaque ea, nostrum odio. Dolores, sed accusantium quasi non, voluptas eius illo quas, saepe voluptate pariatur in deleniti minus sint. Excepturi.
</md-card-content>
</md-card-expand-content>
</md-card-expand>
</md-card>
</div>
</template>
<script>
export default {
name: 'CardExpansion'
}
</script>
<style lang="scss" scoped>
.card-expansion {
height: 480px;
}
.md-card {
width: 320px;
margin: 4px;
display: inline-block;
vertical-align: top;
}
</style>So What’s the Point?
Is this a fair and comprehensive comparison of the three frameworks? (Nope)
Is there a better approach to learn the frameworks out there? (Probably)
I see an overwhelming trend towards React in the professional world. Maybe it has something to do with being created by Facebook. Maybe it’s just a self fulfilling cycle of people using it because they see other people using it. Occasionally I will see some Angular use, very rarely Vue. I dare say that React is not the end all of Javascript frameworks — It may not even be the best.
I think the point is that there is a framework for everyone out there. The three listed here all have practically the same offerings. You could do a more technical comparison but for most people, your choice in the long run comes down to style. We all have different mental models, and experiences which will shape which framework is the easiest to grasp. I’d simply like to see some more variation in stack choice.
If you are coming from a very vanilla background similar to myself, I would recommend you use Vue. It’s got the smallest learning curve.
Technical Resources
Most Popular Web Frameworks According to StackOverflow
Comparison of Angular, React, Vue and more from Vue perspective