The Quickest, Dirtiest, Automatic…est Vue Documenter Ever

Behold, the Vue Component Documenter… Component

Ian Johnson
Skilljar Engineering
5 min readJul 17, 2019

--

By Ian Johnson, a Sr. Front-End Engineer at Skilljar

The Vue Documenter in question so you can follow along at home —

I’m one of three front-end engineers on our team of about a dozen back-end engineers, which means the front-end team needs to support far more than ourselves when rolling out components the entire team will use.

Meaning? Drumroll, keeping some form of documentation on all our components has become a necessity (for our sanity)… otherwise we are the documentation. And if you’ve ever spent your time fielding questions on Slack about which props go in which component, it’s not super scalable.

Documentation you say?

“Easy!” you think, “there are a bunch of documenters out there already!”

Like:

And these are great! But Skilljar doesn’t yet live entirely within Vue-land (Vueville? The E-Vue?) — we live within a large, pre-existing jQuery and Django (a Python framework) project that we’re slowly introducing Vue into.

Slowly.

And since we’re not yet using Vue Router or Vuex, and adding a static site generator tool just isn’t going to get traction when everybody has actual work-things to get done, we arrive at my favorite type of solution — a simple, drop-in component. That outputs… components. Uhh…

I’ll just show you.

Yer a wizard, ’arry

(Because it’s just like magic. It’s cool, I swear)

Given something as simple as this:

// YourVueDocumentationPage.vue<template>
<div>
<vue-documenter>
<sj-datatable></sj-datatable>
<sj-calendar></sj-calendar>
</vue-documenter>
</div>
</template>
<script>
import VueDocumenter from 'vue-documenter';
import SjDatatable from './components/Datatable.vue';
import SjCalendar from './components/Calendar.vue';
export default {
components: {
VueDocumenter,
SjDatatable,
SjCalendar,
},
data () {
return {}
}
}
</script>

Vue Documenter will output something like this example of our Datatable.vue component:

Vue Documenter‘s output for our real Datatable.vue component (I pared down some of the properties for readability)

And for our Calendar.vue component, which has a single date-selected event it emits:

Vue Documenter’s output for our actual Calendar.vue component

Finally! A solution that gives all our components a bare minimum of documentation with almost no additional effort.

Almost… no effort?

“Lame,” I see you thinking, I didn’t sign up for effort.

But it’s only a little, I promise! You only need to add a dash of metadata to the components you want documented to fill in what the Vue Documenter can’t analyze on the fly, and Bam!™

Effort tl;dr

  • Component name: Match the component’s name property (in PascalCase) to however you register it in your app (in kebab-case) so the Vue Documenter can generate the <tag></tag> example correctly
  • Component metadata: Add some metadata to the component itself for events and slots
  • Prop metadata: Add some metadata to the component’s props for it’s default value, example, and required/deprecated flags

Effort kol;bpd (Kind of Long, But Pretty Detailed)

Component name

You must define (and match) the component’s name property to whatever you register it as in your application, ie:

This ComponentA name property in your ComponentA.vue

<script>export default {
name: 'ComponentA', // Vue Documenter will generate <component-a> ... </component-a>
data() {
// etc
}
}
</script>

Component metadata (optional)

There are a few things we just can’t pull out of the component by loading it and analyzing it, so to get events and slots in our documentation, let’s add a few benign properties at the component level (see bold part below).

// Datatable.vue
export default {
name: 'SjDatatable',
// Our magic
meta: {
events: [{
name: 'date-selected',
on: 'click',
example: '2019-02-11',
}],
slots: {
default: {
type: 'component',
valid: ['ValidComponent', 'AnotherValidComponent'],
},
named: [
{
name: 'some-slot-name',
type: 'html'
}
],
},
},

// etc
}

Note: There’s currently only limited support for slot type and valid properties, but I’ll roll out more in the future as we see where this goes.

Prop metadata (semi-optional)

The “semi” part only means that all of your component’s properties will need to be objects with their type and default properties — and now — (the optional part) with a new meta property!

// Datatable.vueprops: {
apiEndpoint: {
type: String, // Standard Vue
default: '', // Standard Vue
// Our magic
meta: {
example: '/api/v1/users',
required: true,
// deprecated: 'Message explaining deprecation reason',
},

},
// etc
}

Pass in your components (pretty non-optional)

The only actually mandatory step here is to pass your components into the <vue-documenter> ... </vue-documenter>

Like so (basically the exact same example snippet from the very beginning):

// YourVueDocumentationPage.vue<template>
<div>
// Our magic
<vue-documenter>
<sj-datatable></sj-datatable>
<sj-calendar></sj-calendar>
</vue-documenter>


</div>
</template>
<script>
import VueDocumenter from 'vue-documenter';
import SjDatatable from './components/Datatable.vue';
import SjCalendar from './components/Calendar.vue';
export default {
components: {
VueDocumenter,
SjDatatable,
SjCalendar,
},
data () {
return {}
}
}
</script>

And that’s the way the cookie crumbles. Stay tuned for next time when I explain just how I took this thing from local component to published NPM component to be consumed by the world, because boy was that a cluster.

Interested in learning more about Skilljar? Check us out at https://www.skilljar.com/. We’d love to chat with you if you’re interested in joining the team. You can learn more about open positions at https://www.skilljar.com/about/careers/

--

--

Ian Johnson
Skilljar Engineering

Owner, Front End Engineer, Data Engineer, Product Manager - Currently a Sr. Front End Engineer at Skilljar