Vue3 - WebPart Sharepoint Online - 1ere Partie

mercredi 17 mai 2023
Image par Mathieu LALLEMAND.
Mathieu LALLEMAND Photo de l'auteur

Sharepoint Online - Développer une WebPart en Vue 3 - Partie 1

Ce petit tutoriel a pour but de présenter comment il est possible d'utiliser VueJS dans une WebPart Sharepoint Online.

Dans cette première partie, nous allons configurer l'environnement de développement pour permettre d'utiliser des composants VueJS au sein des WebPart Sharepoint.

Pré-requis

Plusieurs pré-requis sont nécessaires pour réaliser ce développement :

  • Avoir ouvert le port 4321 sur votre machine
  • Avoir installé WSL2 sur votre poste (le terminal linux c'est le bien)
  • Avoir installé NVM (https://github.com/nvm-sh/nvm#install--update-script)
  • Avoir installé la version 16 de NPM
    • nvm install v16.18 && nvm use v16.18

Pour simplifier les choses, NCI maintient à jour son environnement de développement sous Ansible, et c'est disponible ici. Vous pouvez l'utiliser si vous souhaitez vous faciliter la vie.

Installation de l’environnement de dev Sharepoint

La compilation d'une WebPart demande quelques (beaucoup) outils, voici la ligne pour ajouter les principaux à votre environnement de développement :

sudo npm install gulp-cli yo @microsoft/generator-sharepoint --global

Initialisation du projet Sharepoint WebPart

Nous y voilà enfin.

Tout d'abord, il vous faut créer un repertoire pour le projet (ex: mkdir spvue-demo && cd spvue-demo) puis, une fois dans ce répertoire, lancez l’assistant de création de WebPart :

yo @microsoft/sharepoint
# Choisir le nom du projet
# Choisir 'WebPart'
# Choisir le nom du composant principal (ex: SpVueDemo)
# Choisir 'No Framework'

Une fois l’installation des packages terminée, il faut valider le certificat SSL généré automatiquement par yo pour localhost :

gulp trust-dev-cert

Vous pouvez maintenant ouvrir le projet avec VS Code (ou votre éditeur de code préféré)

Configuration du projet Sharepoint WebPart

Commencez par modifier l’URL de votre page Sharepoint de développement, en replaçant “SHAREPOINT_TENANT” par le nom de votre instance Sharepoint Online :

#/config/serve.json :
...
https://[SHAREPOINT_TENANT].sharepoint.com/_layouts/workbench.aspx
...

Note : Dans certaines sociétes, il vous faudra installer un plugin Microsoft dans votre navigateur pour être autorisée à accéder à Sharepoint Online en utilisant l’authentification windows.

Pour vérifier que tout est OK :

gulp serve

En cas de soucis de compilation, il faut parfois corriger directement les node_modules (et oui !). Il y a eu récemment un package interne à SPFx (le Framework SharePoint) qui ne fonctionnait pas correctement. Commenter la ligne 84 de ce package corrigeait le problème. Il semblerait que sur les dernières version le soucis soit corrigé... enfin pour l'instant.

Rendez-vous ensuite sur l'adresse https://localhost:4321/ et validez le certificat dans le navigateur afin que la connexion entre la page de développement de sharepoint et votre serveur local fonctionne.

Vérifier que la page par défaut se charge correctement en accédant à votre page : https://[SHAREPOINT_TENANT].sharepoint.com/_layouts/workbench.aspx

Il vous faut cliquer sur l'icone "+" pour ajouter votre WebPart à la page de développement ;)

Configuration du Framework VueJS

Pour inclure VueJS, il faut commencer par forcer la version de Webpack (La buildchain de Microsoft travaille avec une vielle version de Webpack… On doit suivre cette vieille version) :

npm i webpack@4.44.2

Lancer les commandes NPM pour installer VueJS

npm vue vue-loader vue-template-compiler webpack-merge

Il faut indiquer au compilateur de prendre en compte les fichiers .vue afin qu’ils soient compilés. Pour cela, il faut créer le fichier /config/copy-static-assets.json et y placer ce contenu :

{
"includeExtensions": [
"vue"
]
}

Il faut patcher le fichier /tsconfig.json.

Voici les modifications à réaliser :

  • Supprimer "jsx": "react", nous n’utiliseront pas React, ni JSX
  • Ajouter "allowSyntheticDefaultImports": true, afin de permettre le chargement des fichiers .vue
  • Ajouter "noUnusedLocals": false, pour éviter que la compilation plante si vous avez des variables non utilisées.
  • Et pour prendre en compte les fichier .vue au lieu de .tsx, il faut remplacer le bloc include par
  "include": [
"src/**/*.ts",
"src/**/*.vue"
],
"exclude": [
"node_modules"
]

Ce qui devrait vous donner un fichier /tsconfig.json qui ressemble à celui-ci

{
"extends": "./node_modules/@microsoft/rush-stack-compiler-4.5/includes/tsconfig-web.json",
"compilerOptions": {
"target": "es5",
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
//"jsx": "react",
"declaration": true,
"sourceMap": true,
"experimentalDecorators": true,
"skipLibCheck": true,
"outDir": "lib",
"inlineSources": false,
"strictNullChecks": false,
"noImplicitAny": true,

"noUnusedLocals": false,
"allowSyntheticDefaultImports": true,
//"isolatedModules": true,
"noImplicitThis" : true,

"typeRoots": [
"./node_modules/@types",
"./node_modules/@microsoft"
],
"types": [
"webpack-env"
],
"lib": [
"es5",
"dom",
"es2015.collection",
"es2015.promise"
]
},
"include": [
"src/**/*.ts",
"src/**/*.vue"
],
"exclude": [
"node_modules"
]
}

Toujours pour la prise en compte des fichiers .vue, il faut patcher le fichier /gulpfile.js. Il est responsable d'une partie de la phase de compilation.

Voici celui que j'utilise (Notez l’ajout de la prise en compte des fichiers .vue) :

'use strict';

const build = require('@microsoft/sp-build-web');
const { VueLoaderPlugin } = require('vue-loader')


build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);

var getTasks = build.rig.getTasks;
build.rig.getTasks = function () {
var result = getTasks.call(build.rig);

result.set('serve', result.get('serve-deprecated'));

return result;
};

build.configureWebpack.mergeConfig({
additionalConfiguration: (generatedConfiguration) => {

generatedConfiguration.module.rules.push({
test: /\.vue$/,
use: [
{
loader: 'vue-loader',
options: {
esModule: true
}
}
]
});

generatedConfiguration.module.rules.push({
test: /\.ts$/,
loader: 'ts-loader',
options: { appendTsSuffixTo: [/\.vue$/] }
});

generatedConfiguration.plugins.push(new VueLoaderPlugin())

return generatedConfiguration;
}
});

build.initialize(require('gulp'));

Idéalement, pour que le “hot-reload” fonctionne sur les fichiers .vue, il faut ajouter à la fin du fichier /gulpfile.js ces lignes, cependant ça ne marche pas à 100%/… Et je soupçonne le watcher de Gulp d'en être responsable. Cependant si vous souhaitez essayer, ajouter ces lignes à la fin du fichier /gulpfile.js

// Patch pour reload si modification d'un fichier vue
const gulp = require('gulp');
gulp.watch('./src/**/*.vue', event => {
gulp.src('./src/index.ts').pipe(gulp.dest('./src/'));
});

Il faut créer un fichier shim /src/shim.d.ts pour avertir TypeScript de ne pas tenter de trouver les types et les structures de VueJS :

module "vue/dist/vue.esm-bundler"
module "*.vue"

Il faut créer un composant principal dans /src/webparts/[NomComposant]/vue/App.vue avec le contenu de votre choix, pour l'exemple nous utiliserons ce contenu démontrant le fonctionne de vue 3 :

<template>
<div>
<button @click="add"></button>
</div>
</template>

<script setup>
import { ref } from "vue";

const props = defineProps([
'spContext',
'spProperties',
'spDarkTheme',
'spEnvMessage',
'spToken'
])

const counter = ref(0);

function add() {
counter.value++;
}
</script>

Intégrer vue dans le composant TypeScript.

En créant votre projet, vous avez donné un nom à votre composant principal. Vous trouverez ce fichier dans /src/webparts/[NomComposant]/[NomComposant]WebPart.ts.

Il faut ajouter les imports vue dans cette WebPart :

import * as Vue from "vue/dist/vue.esm-bundler";
import VueApp from "./vue/App.vue";

Enfin il faut patcher sa méthode de render

this.domElement.innerHTML = `<section><div id="vapp-${this.context.instanceId}"></div></section>`;
Vue.createApp(VueApp, {
spContext: this.context,
spProperties: this.properties,
spDarkTheme: this._isDarkTheme,
spEnvMessage: this._environmentMessage
}).mount(`#vapp-${this.context.instanceId}`);

Et voilà ! Vous pouvez jouer avec les props pour découvrir que la liaison des props en temps réel est fonctionnelle.

Dans les prochains articles, nous découvrirons comment utiliser le panneau de configuration de votre WebPart pour permettre aux utilisateurs de la configurer et récupérer ces valeurs dans les props ainsi que la lecture des listes sharepoint.

A très vite !