no need to update imports after moving a component
folder scoping leads to lazily named files, because they don't have to be unique
boilerplate: src/components/_base-icon.vue
import Vue from 'vue'
import Vuex from 'vuex'
import auth from './modules/auth'
import cart from './modules/cart'
import dashboard from './modules/dashboard'
import userSettings from './modules/userSettings'
import products from './modules/products'
import users from './modules/users'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
auth,
cart,
dashboard,
userSettings,
products,
users
}
})
š³
import Vue from 'vue'
import Vuex from 'vuex'
import modules from './modules'
Vue.use(Vuex)
const store = new Vuex.Store({ modules })
boilerplate: src/state/modules/index.js
const store = new Vuex.Store({ modules })
// Automatically run the `init` action for
// every module, if one exists.
dispatchActionForAllModules('init')
modules[modulePath.pop()] = {
// Modules are namespaced by default
namespaced: true,
...requireModule(fileName),
}
boilerplate:
boilerplate:
import { mapState, mapGetters, mapActions } from 'vuex'
export const authComputed = {
...mapState('auth', {
currentUser: state => state.currentUser,
}),
...mapGetters('auth', ['loggedIn']),
}
export const authMethods = mapActions('auth',
['logIn', 'logOut']
)
boilerplate: src/state/helpers.js
import {
authComputed,
authActions
} from '@state/helpers'
export default {
computed: {
...authComputed,
},
methods: {
...authActions,
},
}
great tooling can not only catch typos and potential errors, but also teach new features as developers need them
Faster reviews, more learning, more motivatingĀ
when developers feel cared for by their tooling, they take more pride in their work and write better code
module.exports = {
'*.js': [
'yarn lint:eslint',
'yarn lint:prettier',
'git add',
'yarn test:unit:file',
],
'*.vue': [
'yarn lint:eslint',
'yarn lint:stylelint',
'yarn lint:prettier',
'git add',
'yarn test:unit:file',
],
'*.scss': ['yarn lint:stylelint', 'yarn lint:prettier', 'git add'],
'*.md': ['yarn lint:markdownlint', 'yarn lint:prettier', 'git add'],
'*.{png,jpeg,jpg,gif,svg}': ['imagemin-lint-staged', 'git add'],
}
speed up development and simplify refactors
e.g. automatically generate a unit test with each module
methods: {
// Perform more complex prop validations than is possible
// inside individual validator functions for each prop.
validateProps() {
if (process.env.NODE_ENV === 'production') return
// Check for insecure URL in href.
if (!this.allowInsecure && !/^(https|mailto|tel):/.test(this.href)) {
return console.warn(
`Insecure <BaseLink> href: ${
this.href
}.\nWhen linking to external sites, always prefer https URLs.`
)
}
}
}
we stop writing and running tests when they're NOT...
Everyone knows when
tests are failing
Tests don't fail intermittently
Tests run quickly
When a test fails,
it's easy to learn why
A single codebase, with independently deployable/publishable projects that share some common resourcesĀ
(no data, computed, etc and no lifecycle)
<template functional>
<!-- ... -->
</template>
export default {
functional: true,
render (h, context) {
// ...
}
}
or
(especially for components rendered many times, e.g. with a v-for)
boilerplate: src/components/nav-bar-routes.vue
{
path: '/admin',
name: 'admin-dashboard',
component: () => import('@views/admin'),
}
{
path: '/admin',
name: 'admin-dashboard',
component: require('@views/admin').default,
}
<keep-alive>
<component :is="currentTabComponent" />
</keep-alive>
Easier refactoring
More flexible architecture
First-class TypeScript support
@chrisvfritz