Building SharePoint client web part with Vue.js and single-file components

Vue.js becomes more and more popular and it’s time to build real life sample using Vue’s single-file components. Single-files components are the building blocks for Vue application. It’s not required to use single files components for Vue application, but they give you some advantages:

  • recommended style for Vue applications
  • modern components-based approach
  • good separation of concern between markup, css and code
  • we don’t need to use standalone version of Vue and can use runtime version, which is smaller
  • since we are using runtime version of Vue, our app works a bit faster, because not need to compile templates (already compiled by vue-loader)

Original sample can be founded under SharePoint Framework client-side web part samples – that’s a basic todo web part built with Vue. This a companion post describing some concepts.

The most difficult part is to setup our SPFx build pipeline to support Vue. Here are the steps required in order to make SPFx vue-compatible:

  1. We are going to use Vue’s component decorators - vue-class-component and vue-property-decorator thus need to modify tsconfig.json and add experimentalDecorators and allowSyntheticDefaultImports:
    "experimentalDecorators": true
    "allowSyntheticDefaultImports": true
  2. Install required node modules:
    npm install vue vue-class-component vue-property-decorator vue-template-compiler --save
    npm install vue-loader webpack-merge css-loader sass-loader node-sass --save-dev
  3. Add vue.js as external dependency for our sharepoint client web part project (note: we are adding runtime version of vue.js, read above why). For that purpose open config/config.json and add to external new library:
    "externals": {
        "vue": "node_modules/vue/dist/vue.runtime.js"
      },
  4. The most difficult part is to adjust build pipeline. You can read more here for different options available for build config modifications. Basically we need to “disable” default sass task (because all styles will be processed by vue-loader), add vue-loader as new loader for webpack, copy .vue files into the output folder. Below is the full code needed to be inserted into the gulpfile.js before build.initialize task:
    var merge = require('webpack-merge');
    
    build.sass.setConfig({
        sassMatch: []
    });
    
    build.configureWebpack.setConfig({
        additionalConfiguration: function (config) {
            var vueConfig = {
                module: {
                    rules: [
                        {
                            test: /\.vue$/,
                            use: [{
                                  loader: 'vue-loader',
                                    options: {
                                        esModule: true
                                    }
                            }]
                        }
                    ]
                }
            };
    
            return merge(config, vueConfig);
        }
    });
    
    build.copyStaticAssets.setConfig({
        includeExtensions: ['vue', 'scss']
    });

That’s it for configurations. Now we can write our amazing vue components.

Bootstrapping code is very simple. Inside web part’s render method: 

new Vue({
  el: `#app-${this.context.instanceId}`,
  render: h => h(TodoComponent, {
	props: this.data
  })
});

TodoComponent is our root component for the web part. It consist of .vue file which contains markup and references to .scss styles and typescript logic. Below is full content for todo.vue:

<template>
    <div>
        <h1>{{message}}</h1>
        <div id="new-todo">
            <input type="text" @keyup.enter="addTodo" v-model="todoTitle" placeholder="what needs to be done?">
        </div>
        <ul>
            <todo-item v-for="(todo, index) in mytodos" :key="index + todo" :todoText="todo" v-on:completed="completed"></todo-item>
        </ul>        
    </div>
</template>

<script>
    module.exports = require('./todo');
</script>

<style scoped src="./todo.scss" lang="scss"></style>

Basically that all you need to start building Vue.js SharePoint client web parts. If you are interested, I recommend you to clone SPFx samples repo and run it to see it in action.

The links:

Feel free to ask any questions.