This is the second post about SharePoint Framework and Vue.js. In this post I'm going to implement basic Client-Side Web Part using Vue.js - basically, "wrap" the markup from Web Part template project with Vue.js component. List of posts:
In the first post we went through the basic configuration of a project to use both TypeScript and Vue.js. Now let's go further and include Vue.js in SharePoint Framework project
1. Scaffolding
So, the first thing we should do, as with any other SPFx project, is to "scaffold" it from the template how it is described here This will create a basic project with a markup implemented using HTML with no framework used.
Now we have a SPFx project prepared and the goal is to replace the HTML markup with a Vue component.
2. Including Vue into the Project
I'm going to implement a web part as a Single File Component (SFC) with a help of vue-class-component. This is one of two available options how to implement an SFC using Vue.js. Another one is to use Vue.extend which is more "classic" way for Vue developers. But vue-class-component is more similar to SPFx development itself. So, as mentioned, I'll use this one. First of all, we need to install vue module as we did in the first post:
Next, we're going to create SFC and implement components inside .vue files. To let webpack know about this type of files we need to install vue-loader. Also, we need to install vue-template-compiler as it is a dependency of vue-loader. Additionally, we need ts-loader and sass-loader to correctly process TypeScript code and SCSS styles inside SFCs. We need these modules for bundling only. That's why we'll install them with --save-dev parameter:
Now, as mentioned, we need vue-class-component and additionally vue-property-decorator to mark Vue component properties:
And one more thing... By default, ts-loader creates additional assets that are not recognized by SharePoint Framework in release mode. It leads to errors in gulp bundle --ship command and inability to package the solution. To avoid that we can use transpileOnly: true option of ts-loader (see Webpack config modifications below). But it leads to disabling of type and syntactic checking inside .vue files. To keep the checking we can use fork-ts-checker-webpack-plugin:
And combining all the modules:
3. Modifying Webpack config and Gulp tasks
Next step is to modify gulpfile.js. We need to change multiple things to build our Vue components correctly:
Copy Vue files to the destination folder.
apply correct loaders for .vue files
The first step is to copy .vue files to the destination folder. For that we can create a Gulp sub task and add it after the TypeScript compiler task:
With version 1.6 of SharePoint Framework we can also create a task to initiate build when we're in debug session (gulp serve) and .vue file has been saved. For that we can use next flow: add watch task on .vue files. When watch fires event that the files has been saved we're copying empty index.ts file from src folder to itself. It will kick of the build process. Thanks to Stefan Bauer for the idea.
Next thing to do is to modify Webpack config to use vue-loader, ts-loader and sass-loader for .vue files and Fork TS Checker plugin for type and syntactical checking:
Few words about the code above First, we're instantiating 2 plugins:
VuePlugin to correctly kick off processing of .vue files by vue-loader and
ForkTsCheckerWebpackPlugin to check typings in .vue files and use tslint rules for syntactical checking
Next, we're adding loader configurations.
vue-loader to process .vue files
ts-loader to process TypeScript code from .vue files. The interesting thing here is that we don't want to process .ts files with ts-loader. To avoid that we're using resourceQuery rule to process only code from files that have vue&type=script&lang=ts in query string parameters. These parameters are added by vue-loader for <script lang="ts"> blocks
For<style> blocks we're adding multiple loaders to work sequentially: @microsoft/loader-load-themed-styles loader to process theme variables;css-loader to be able to use CSS Modules; and sass-loader to process scss or sass if needed.
With these configurations in place .vue files will be processed correctly.
4. Implementing Vue Single File Component
Now we're ready to implement web part's markup as a Vue SFC. For that let's create components folder, SimpleWebPart subfolder, and SimpleWebPart.vue file in it. Now let's move the markup from the Web Part .ts file to .vue file. The markup (HTML) should be placed inside template element. So, after copying, the .vue file should look like this:
Next step in SFC creation is to add "model" - the Component class that contains properties, events handlers and business logic. For that we need to add <script lang="ts"> section in .vue file and add our TypeScript code there. The code should contain a "component" class (marked with @Component attribute and extend Vue interface. To be more close to SPFx development standarts, I will also define ISimpleWebPartProps interface to contain component's properties declaration:
Note: you can implement TypeScript logic in separate .ts file and reference it inside .vue using src attribute:
After implementing the Component class we can reference description property in our template. For that we need to use mustache syntax and replace ${escape(this.properties.description)} with {{description}}:
Now, let's copy web part styles to our component in <style lang="scss">section. One change to be done in copied styles is to change @import statement: file name should be changed from SPFabricCore.scss to _SPFabricCore.scss. The reason for that is that physically there is no SPFabricCore.scss file in SP Office UI Fabric Core module. This name is process by custom SharePoint Framework Gulp task and resolved correctly to actual file _SPFabricCore.scss. In our case we don't have access to that custom Gulp task and need to reference actual file directly. The code in style section should look like that:
We're also using module attribute to use CSS Modules. Now the styles can be used in the template (in markup) using pre-defined $style variable:
:class syntax here is a shorthand for v-bind:class that allows to bind property to the class HTML attribute.
5. Adding Vue SFC Component in Web Part
The last step is to add created element instead default HTML in the Web Part. For that, let's import Vue object, our component and the properties:
And now let's add the component to markup and provide description value from the Web Part's properties.
I'm using unique id in the div element to inject Vue component. Usually it's not a good idea to use ids for any references, but here I've tried to reference directly this.domElement in the Vue constructor. But in that case "reactive" change of web part's properties will not work. So I decided to go with id. If you have any other ideas - feel free to share! Now, if you try to compile the project with gulp command, you'll receive the error
That is because TypeScript compiler doesn't know how .vue files look like when they're imported. To notify TypeScript about the structure of .vue files (and modules) we need to add vue-shims.d.ts file in the src folder with the next content:
Now everything should work fine and you should see a standard web part markup on your page:
The code for this example is available here That's it for now! Have fun and stay tuned!
Comments