Adding Vuepress to a Vue CLI project with Typescript

Vuepress is one of the most commonly used documentation frameworks in the Vue ecosystem. Adding it to an already existing Vue CLI based project that uses Typescript isn’t entirely trivial though.

The 7 steps below will get you up and running.

  1. If you don’t have a project yet, create a new project with Vue CLI. Be sure to pick Typescript in the setup steps.
  2. Install Vuepress, its Typescript plugin and the related type definitions:

    yarn add vuepress vuepress-plugin-typescript vuepress-types --dev
    
  3. Create subfolders docs and docs/.vuepress in your project folder. docs will hold your content, .vuepress will contain the necessary configuration to get Vuepress up and running.

    mkdir -p docs/.vuepress
    
  4. Configure Vue shims for Vuepress. This is necessary to support .vue files.

    // docs/.vuepress/shims-vue.d.ts
    declare module '*.vue' {
        import Vue from 'vue';
        export default Vue;
    }
    
  5. Configure the Typescript plugin along with the default @ alias used by Vue CLI.
    This is the tricky bit and all non-standard options are documented below:

    // docs/.vuepress/config.js
    const path = require('path');
    
    const projectRoot = process.cwd();
    const alias = path.resolve(projectRoot, 'src');
    
    module.exports = {
        // If you need to configure any plugins etc, this is the call to do so
        configureWebpack(config) {
            // Solely to speed up Vuepress, reenable if you need to debug your setup
            config.devtool = false;
            // Match standard Vue CLI aliasing
            config.resolve.alias['@'] = alias;
        },
        plugins: [
            ['vuepress-plugin-typescript', {
                tsLoaderOptions: {
                    // Vuepress compilation is ridiculously slow without this, type checking belongs in development not documentation anyway
                    transpileOnly: true,
                    compilerOptions: {
                        // Vuepress needs an older target (as opposed to esnext) to correctly transpile optional chaining and nullish coalescing
                        'target': 'ES2019',
                    },
                },
            }],
        ],
    }
    

    The key takeaways are that:

    1. You need an older target to ensure optional chaining and nullish coalescing are handled correctly in Vuepress. Vue CLI uses esnext out of the box, targeting ES2019 should cover most use cases.
    2. Vuepress is slow with handling Typescript, turning off checks you don’t use in documentation writing will save you loads of time.
  6. Update your package.json with scripts for Vuepress:
    {
        "scripts": {
            "docs:dev": "vuepress dev docs",
            "docs:build": "vuepress build docs"
        }
    }
    
  7. Write some documentation. You’re now able to use your existing components as live examples in documentation:
    <script lang="ts">
    // docs/README.md
    import Vue from 'vue';
    import Component from 'vue-class-component';
    
    import HelloWorld from '@/components/HelloWorld.vue';
    
    @Component({
        components: {
            HelloWorld,
        },
    })
    export default class extends Vue {}
    </script> 
    
    # Sample docs
    
    <HelloWorld />
    

You can now run the documentation in development mode with docs:dev or bundle it to a static site with docs:build.

This setup is far from trivial (and will hopefully be more streamlined over time), but it allows you the benefit of tracking your documentation along with your project as well as having live code samples in project documentation.