3 Secret Vue Patterns for Productivity Boost!
Tags: vue, pattern, javascript, programming
Published: 2022-03-10 22:34:54

## Productivity Boosts
Hello World! 👋

I was watching this lecture about [Secret Vue Patterns](https://www.youtube.com/watch?v=7lpemgMhi0k) and I thought about sharing with you people some vue patterns that I learned! This time it will be only about productivity and how to improve it!

Hope you like it!

Let's start with...

###🔵Smarter watchers

Imagine we are working in a search input component, so let's say we want to fetch on created, then watch the input.

```javascript
created() {
    this.fetchUserList()
},
watch: {
    searchText() {
        this.fetchUserList()
    }
}
```

We can improve this code by making the watcher accept method names as strings making it look like this:

```javascript
created() {
    this.fetchUserList()
},
watch: {
    searchText: 'fetchUserList'
}
```

This reduces a few lines and makes the code cleaner. 🤗

The next improvement we can make is by making the watcher call themselves on created:

```javascript
watch: {
    searchText: {
        handler: 'fetchUserList',
        immediate: true
    }
}
```

Notice that now the searchText was a string and now is an object!

Let's analyze some topics:

- handler: Is the function (or string that has the name of the method) that we want to call.
- immediate: When true means that we don't need to use created hook anymore because the handler will be called as soon as the component is ready, it will be immediately.

Now, since everything is in a watcher now you can reduce the surface area for bugs in your code. Writing this way makes your code cleaner.


###🔵Component Registration

We see in almost every project the following pattern in component registration:

```javascript 
import BaseButton from './base-button'
import BaseIcon from './base-icon'
import BaseInput from './base-input'

export default {
    components: {
        BaseButton,
        BaseIcon,
        BaseInput,
    }
}
```

It might be a lot of code at first, but we can make it cleaner and more productivity-focused using it like this:

```javascript
// Can be used on main.js or in a components/_globals.js
import Vue from 'vue'
import upperFirst from 'lodash/upperFirst'
import camelCase from 'lodash/camelCase'

// Requeire in a base component context
const requireComponent = require.context(
    '.', false, /base-[\w-]+\.vue$/
)

requireComponent.keys().forEach(fileName => {
    // Get component config
    const componentConfig = requireComponent(fileName)
    // Get PascalCase name of component
    const componentName = upperFirst(
        camelCase(fileName.replace(/^\.\//, '').replace(/\.\w+$/, ''))
)

    // Register component globally
    Vue.component(componentName, componentConfig.default || componentConfig)
```

First: This code we usually place in the main.js file, but we can also create a file called '_globals.js' and place it at our components directory.

Second: The following part gets all the files with the 'base' prefix and is a '.vue' file, which is commonly used to create custom vue components that are used everywhere. But hey, you can change it if you want to.

```javascript
const requireComponent = require.context(
    '.', false, /base-[\w-]+\.vue$/
)
```

After that, we need to get the component config and the pascal case version of that component:

```javascript
requireComponent.keys().forEach(fileName => {
    // Get component config
    const componentConfig = requireComponent(fileName)
    // Get PascalCase name of component
    const componentName = upperFirst(
        camelCase(fileName.replace(/^\.\//, '').replace(/\.\w+$/, ''))
)
```

And then we register the component at the bottom:

```javascript
Vue.component(componentName, componentConfig.default || componentConfig)
```

This is a global registration, which means it will be available to the whole app.

Also, I need to say that this tip only works with webpack

**Extra advanced webpack tip:**

In this part of the code:


```javascript
Vue.component(componentName, componentConfig.default || componentConfig)
```

If in your .vue component you export default that means your component options will be under `component.config.default`, which means it will be under the default option at the exported module.

If you are importing using the ES6 syntax (import something from 'something'), that automatically will look for a default. When you are using required tho, it doesn't.

So we have to specify that we want the default or, if you never exported default in your .vue component (`module.exports =`), then your component options will be under componentConfig.

Also, if your vue component doesn't have a script tag, then your component will also be under `componentConfig.default`.

After all, using that pattern, we don't need to import any 'base' component, just use it when needed.

**But why not then import all the components like that?**
Well, there's a reason, when you import everything globally, the components that you are not using will be in the distribution bundle when building using webpack. So, imagine that you make a specific navbar for a specific category of the user since every component is imported globally, even if you are not showing it to the final user, it's at the webpack bundle.

That's bad because your bundle will be big and over time will be difficult to maintain.


###🔵Module Registration

A bit similar to the previous tip, but this time is for modules.
For those who don't know, vuex modules are little pieces of state management that you can bring to your application.

PS: this isn't a pattern exclusive to vuex, you can find it in redux for example.

You will find it in projects like this:

```javascript
import auth from './modules/auth'
import posts from './modules/posts'
import comments from './modules/comments'
// ...

export default new Vuex.Store({
    modules: {
        auth,
        posts,
        comments,
        // ...
    }
})
```

That's one way to improve the code:

```javascript
// index.js
import camelCase from 'lodash/camelCase'
const requireModule = require.context('.', false, /\.js$/)
const modules = {}

requireModule.keys().forEach(fileName => {
    // Don't register this file as a Vuex module
    if (fileName === './index.js') return

    const moduleName = camelCase(
        fileName.replace(/(\.\/|\.js)/g, '')
    )
    modules[moduleName] = requireModule(fileName)
})

export default modules
```

First: 
We are requiring all of the js files, inside the current folder and we are going through each of those files, and if the file name is index.js we jump it. It's the only thing in that folder that won't be a module.

```javascript
// modules/index.js
import camelCase from 'lodash/camelCase'
const requireModule = require.context('.', false, /\.js$/)
const modules = {}
```


We then camel case the file name and add it to a modules hash, or modules object. Requiring the module by its file name.

```javascript
requireModule.keys().forEach(fileName => {
    // Don't register this file as a Vuex module
    if (fileName === './index.js') return

    const moduleName = camelCase(
        fileName.replace(/(\.\/|\.js)/g, '')
    )
    modules[moduleName] = requireModule(fileName)
})
```

Then we just export all those modules:

```javascript
export default modules
```

**Extra tip**

If you want to use namespaced modules, you can change them to this:

```javascript
// [...]
    modules[moduleName] = {
        namespaced: true,
        ...requireModule(fileName),
    }
})
```

Now our store file will look like this:

```javascript
import modules from './modules'

export default new Vuex.Store({
    modules
})
```

Much better.

Hope you enjoyed the reading! Any tips or mistakes I committed, please feel free to write them down below!

See ya next time!🤠