Image Principale

Du Server Side Rendering avec VueJS


Ce qui est bien avec les nouveaux frameworks Javascript, c'est de pouvoir faire des applications qui n'ont jamais été aussi stables côté client. Mais tout le monde ne peut pas exécuter de Javascript, y compris certains moteurs de recherche. Le server side rendering est là pour vous sauver.

Contact Person Mathieu Marteau
il y a 10 mois

Initialisation d'un projet npm

Pour les besoins de cet article, je vais créer un tout nouveau projet. Puis je vais initialiser ce projet en faisant:

npm init

Je vais également créer un fichier server.js vide pour avoir l'architecture suivante:

.
+-- server.js
+-- package.json

Commençons donc simplement par installer vue:

npm install --save vue

Vous aurez également besoin du renderer qui se chargera de construire le contenu à renvoyer au client:

npm install --save vue-server-renderer

Nous aurons besoin d'une dernière dépendance afin de pouvoir écouter sur un port de notre machine depuis node:

npm install --save express

Initialisation de Vue

Entrons maintenant dans le vif du sujet en initialisant Vue dans un nouveau fichier js, que nous placerons dans un dossier assets. Dans ce fichier, nous allons créer une fonction anonyme, à qui nous enverrons un objet différent selon deux cas:

  1. Côté serveur, l'objet que nous enverrons correspondra à un objet vide.
  2. Côté client, l'objet que nous enverrons correspondra à window du navigateur.

Pour cela, rien de plus simple que d'utiliser this et d'initialiser notre fonction:

assets/app.js

(function () {
    // Notre code ici
}).call(this)

Nous allons maintenant créer une fonction chargée de retourner une instance de Vue:

(function () {

    var createApp = function () {
        return new Vue({
            // Une instance Vue
        })
    }

}).call(this)

On va suivre l'exemple du guide officiel et on va créer un petit compteur qui s'incrémente toutes les secondes:

(function () {

    var createApp = function () {
        return new Vue({
            template: '<div id="app">You have been here for {{ counter }} seconds.</div>',
            data: {
                counter: 0
            },
            created: function () {
                var vm = this
                setInterval(function () {
                    vm.counter += 1
                }, 1000)
            }
        })
    }

}).call(this)

C'est maintenant que le comportement de notre application va différer.

  1. Si on est côté serveur, on veut renvoyer cette instance de Vue en tant que module node afin de l'utiliser dans notre fichier de serveur.
  2. Si on est côté client, on veut pouvoir accéder à cette instance depuis notre navigateur.

Pour cela, rien de plus simple:

(function () {

    var createApp = function () {
        return new Vue({
            template: '<div id="app">You have been here for {{ counter }} seconds.</div>',
            data: {
                counter: 0
            },
            created: function () {
                var vm = this
                setInterval(function () {
                    vm.counter += 1
                }, 1000)
            }
        })
    }

    if (typeof module !== 'undefined' && module.exports) {
        module.exports = createApp
    } else {
        console.log('olas')
        this.app = createApp()
    }

}).call(this)

Voilà, notre instance est prête!

Création du fichier HTML:

Nous allons tout de même créer un fichier html pour notre application. Nous devrons inclure vue ainsi que notre app.js:

<!DOCTYPE html>
<html>
<head>
    <title>Mon application Vue</title>
    <script type="text/javascript" src="/node_modules/vue/dist/vue.js"></script>
</head>
<body>

<div id="app"></div>

<script type="text/javascript" src="/assets/app.js"></script>

</body>
</html>

Puis nous allons "monter" notre application sur notre div#app:

<!DOCTYPE html>
<html>
<head>
    <title>Mon application Vue</title>
    <script type="text/javascript" src="/node_modules/vue/dist/vue.js"></script>
</head>
<body>

<div id="app"></div>

<script type="text/javascript" src="/assets/app.js"></script>
<script type="text/javascript">
    app.$mount('#app')
</script>
</body>
</html>

Configuration du serveur

Il ne nous reste plus qu'à configurer notre serveur. Pour cela, nous allons éditer notre fichier server.js.

Commençons par inclure tous les modules node dont nous aurons besoin.

var fs = require('fs')
var path = require('path')
var express = require('express')

global.Vue = require('vue')

En déclarant Vue de façon globale, on s'assure qu'il soit accessible depuis notre fichier app.js depuis le serveur.

On créé ensuite notre serveur et on initialise notre renderer qui va être chargé de de générer le HTML que nous enverrons à notre client:

var renderer = require('vue-server-renderer').createRenderer()
var server = express()

Nous allons également charger le contenu de notre fichier HTML:

var layout = fs.readFileSync('./index.html','utf8')

Notre serveur va avoir besoin de deux fichiers: notre instance Vue située dans /assets/app.js et le framework situé dans node_modules/vue/dist/vue.js. Il faut donc que notre client puisse y accéder:

server.use('/assets', express.static(
    path.resolve(__dirname, 'assets')
))

server.use('/node_modules', express.static(
    path.resolve(__dirname, 'node_modules')
))

Nous allons maintenant configurer notre serveur pour qu'il soit capable de recevoir des requêtes GET. Et nous allons renvoyer le code HTML généré par notre renderer

server.get('*', function (request, response) {
    renderer.renderToString(
        require('./assets/app')(),
        function (error, html) {
            if (error) {
                console.log(error)
                return response.status(500).send('Server Error')
            }
            response.send(layout.replace('<div id="app"></div>',html))
        }
    )
})

Comme vous le voyez, on remplace la chaine de caractère <div id="app"></div> par le contenu de notre instance Vue généré par notre renderer. C'est aussi simple que ça...

Il ne nous reste plus qu'à dire à notre serveur d'écouter sur un port de notre machine, nous utiliserons ici le port 5000, comme dans le guide officiel...

server.listen(5000, function (error) {
    if (error) {
        throw error
    }
    console.log('listening on port 5000')
})

Nous n'avons plus qu'à lancer notre serveur et à accéder à notre page via l'url: http://localhost:5000:

server.listen(5000, function (error) {
    if (error) {
        throw error
    }
    console.log('listening on port 5000')
})

Crédits: