At Mastering JS, we're all about pragmatic web development. That means we aggressively avoid work that isn't related to shipping new features. We believe in spending at most 1 hour per quarter on build system work so we don't waste time bikeshedding Webpack configs or discussing "state management" (is that even a thing anymore?).
In other words, we want to spend most of our calories writing v-if and v-bind statements, not tinkering with our build.
Overview
Everything starts with an index.html
file that we typically host on Netlify. The index.html
file contains the below body
.
<body>
<div id="content"></div>
<script src="https://unpkg.com/vue@3.x"></script>
<script src="https://unpkg.com/vue-router@4.0.10"></script>
<script src="/bundle.js"></script>
</body>
We prefer to load Vue from a CDN to avoid having to bundle it ourselves. Same with Vue Router. Why? Tree shaking isn't worth it for us, because we don't put Vue on SEO-focused pages. If we want a page to rank on Google, we do vanilla JS, unless the page is specifically about Vue and needs to have some interactive examples.
Our bundle does contain most other dependencies, which is why we build our bundle using Webpack.
Webpack Config
Below is our standard Webpack config for Vue projects.
const config = require('./.config');
const webpack = require('webpack');
module.exports = {
mode: 'development',
entry: {
app: `${__dirname}/src/main.js`
},
target: 'web',
output: {
path: `${__dirname}/public`,
filename: 'bundle.js'
},
optimization: {
minimize: false // <-- Remove need for source maps
},
plugins: [
// Allow accessing config
...Object.keys(config).map(key => {
return new webpack.DefinePlugin({ [`__${key}`]: config[key] });
})
],
module: {
rules: [
{
test: /\.html$/i, // <-- Allow `require()` on HTML files
type: 'asset/source'
},
{
test: /\.css$/i, // <-- Allow `require()` on CSS files
type: 'asset/source'
}
]
}
};
3 things worth noting about this config:
- We disable minification in prod. Again, the performance benefit of minifying is so negligible in our case that it isn't worth the developer time to set up source maps, etc. If minification provides a meaningful performance benefit, that means you're shipping wayyyyyyyyyy too much JavaScript and should fix your app.
- Use plugins to import config.
- Import HTML and CSS as strings using
type: 'asset/source'
.
Why do we import HTML and CSS as strings? So we can define the HTML and CSS for our components in .html
and .css
files. For example, below is our footer/index.js
file:
'use strict';
const appendCSS = require('../appendCSS');
const css = require('./footer.css');
const template = require('./footer.html');
appendCSS(css);
module.exports = app => app.component('footer-component', {
template: template
});
This means all our layout work is done in HTML and CSS. No need to actually touch JavaScript. A huge win for us, because this means we can delegate most of our new layout work out to designers on Fiverr or similar services. They send us a complete layout, and we just put it into a component.
State
State management is largely a non-issue in Vue. Frontend devs tend to discuss state management ad infinitum because it is a huge problem in frameworks like React, which are written for pre-ES6 JavaScript and are hopelessly out of date.
For us, our top-level page components (the components we pass to Vue Router) are responsible for setting state and fetching data. To avoid prop drilling, they pass state down using Vue's provide
option.
Top comments (0)