diff --git a/LANGS.md b/LANGS.md index 17534973..5f855067 100644 --- a/LANGS.md +++ b/LANGS.md @@ -1,4 +1,5 @@ * [English](en/) +* [Français](fr/) * [中文](zh/) * [Русский](ru/) * [한국어 (Korean)](ko/) diff --git a/fr/README.md b/fr/README.md new file mode 100644 index 00000000..8b455b84 --- /dev/null +++ b/fr/README.md @@ -0,0 +1,50 @@ +# Guide du rendu côté serveur avec Vue.js + +> **Note :** Ce guide nécessite les versions de Vue et de ses bibliothèques de support suivantes : +> - vue & vue-server-renderer >= 2.3.0 +> - vue-router >= 2.5.0 +> - vue-loader >= 12.0.0 & vue-style-loader >= 3.0.0 + +> Si vous avez déjà utilisé le rendu côté serveur (SSR pour *Server-Side Rendering*) avec Vue 2.2, vous vous apercevrez que la structure de code recommandée est maintenant [légèrement différente](./structure.md) (avec la nouvelle option [runInNewContext](./api.md#runinnewcontext) mise à `false`). Votre application devrait continuer à fonctionner, mais il est recommandé de migrer vers les nouvelles recommandations. + +## Le rendu côté serveur ou SSR, qu'est-ce que c'est ? + +Vue.js est un framework pour créer des applications côté client. Par défaut, Vue génère en sortie un DOM manipulable dans le navigateur. Il est cependant également possible de faire le rendu des mêmes composants sous forme de chaîne de caractères HTML côté serveur, de les envoyer directement au navigateur et d'« hydrater » les balises statiques fournies en une application cliente pleinement interactive. + +Une application Vue.js rendue du côté serveur peut également être considérée comme « isomorphique » ou « universelle », dans le sens où la majorité du code est exécutable côté serveur **et** coté client. + +## Pourquoi faire du SSR ? + +En comparaison des applications monopages traditionnelles (SPA pour *Single-Page Application*), l'avantage du SSR se manifeste dans : + +- De meilleures optimisations pour les moteurs de recherche (SEO pour *Search Engine Optimisations*), ainsi les moteurs d'indexation voient directement le rendu complet de la page. + + À noter qu'à présent, Google et Bing savent parfaitement indexer des applications JavaScript synchrones. Synchrone est le mot important ici. Si votre application débute avec une animation de chargement, puis va chercher le contenu via Ajax, l'indexeur n'attendra pas que cette action soit finie. Cela signifie que si vous avez du contenu asynchrone injecté sur des pages où la SEO est importante, du SSR serait nécessaire. + +- De meilleurs temps d'accès au contenu, en particulier pour les connexions Internet lentes ou les appareils lents. Le rendu des balises côté serveur n'a pas besoin d'attendre le chargement de tous les fichiers JavaScript pour que le code soit exécuté en vue d'être affiché. Ainsi votre utilisateur verra apparaître une page complètement rendue très tôt. Cela conduit généralement à une meilleure expérience utilisateur, ce qui peut-être critique pour les applications où le temps d'accès au contenu est directement lié au taux de conversion. + +Il y a aussi des contraintes à prendre en considération quand on utilise du SSR : + +- Des contraintes de développement. Le code spécifique aux navigateurs ne peut être utilisé que dans certains hooks ; plusieurs bibliothèques nécessitent une utilisation particulière pour être capable d'être exécutées dans une application côté serveur. + +- Plus d'étapes de pré-compilation et de déploiement requises. Contrairement à une SPA qui peut être déployée sur un serveur de fichiers statiques, une application rendue côté serveur nécessite un environnement où un serveur Node.js peut tourner. + +- Plus de charge côté serveur. Faire le rendu d'une application complète en Node.js est évidemment une tâche demandant plus de ressources CPU que de simplement renvoyer des fichiers statiques. Aussi si vous vous attendez à un fort trafic, préparez-vous un serveur tenant la charge et utilisez astucieusement des stratégies de mise en cache. + +Avant d'utiliser du SSR pour vos applications, la première question que vous devriez vous poser est si vous en avez réellement besoin. Cela dépendra de l'importance du temps d'accès au contenu pour votre application. Par exemple, si vous créez une interface d'administration avec un chargement initial de quelques secondes, cela n'a pas d'importance ; du SSR n'aurait pas de pertinence dans ce cas. Cependant, dans le cas où l'accès au contenu est une priorité absolue, du SSR peut vous aider à obtenir les meilleures performances de chargement initial. + +## Rendu côté serveur vs. pré-rendu + +Si vous envisagez d'utiliser du SSR seulement pour améliorer votre SEO sur des pages informatives à valeur ajoutée (par ex. `/`, `/about`, `/contact`, etc), alors vous devriez plutôt utiliser du pré-rendu. Plutôt que d'utiliser un serveur web pour compiler le HTML en temps réel, faites le simple pré-rendu de vos pages statiques en HTML pour des routes bien spécifiques lors d'une phase de pré-compilation. L'avantage est que faire du pré-rendu est plus simple et vous permet de garder un site avec une partie cliente statique. + +Si vous utilisez webpack, vous pouvez facilement ajouter du pré-rendu avec le plugin [prerender-spa-plugin](https://github.com/chrisvfritz/prerender-spa-plugin). Il a particulièrement bien été testé avec des applications Vue (en fait, [son créateur](https://github.com/chrisvfritz) est lui-même un membre de l'équipe principale de Vue). + +## À propos de ce guide + +Ce guide est dédié au rendu côté serveur des applications monopages utilisant Node.js en tant que serveur web. Utiliser le SSR de Vue avec une autre configuration serveur est un sujet qui ne sera pas abordé dans ce guide. + +Ce guide va réellement entrer dans le détail et présuppose que vous êtes déjà familiarisé avec Vue.js et que vous avez un niveau de connaissance correcte concernant Node.js et webpack. Si vous préférez une solution de haut niveau fournissant une expérience de développement prête à l'emploi, vous devriez probablement essayer [Nuxt.js](http://nuxtjs.org/). Il est construit par-dessus l'écosystème de Vue et vous fourni des éléments préconçus ainsi que des fonctionnalités supplémentaires pour générer des sites web statiques. Il ne vous conviendra cependant pas si vous souhaitez avoir un contrôle plus direct sur la structure de votre application. Dans tous les cas, il reste toujours intéressant de parcourir ce guide pour mieux comprendre comment chaque élément fonctionne avec le reste. + +Au fil de votre lecture, il peut être intéressant également de vous référer à la [démo HackerNews](https://github.com/vuejs/vue-hackernews-2.0/) qui utilise bon nombre des techniques expliquées dans ce guide. + +Pour finir, notez que les solutions de ce guide ne sont pas définitives. Nous avons trouvé que cela fonctionnait bien pour nous, mais cela ne veut pas dire qu'il n'y a pas d'améliorations à faire. Nous pourrons les réviser dans le futur. N'hésitez donc pas à y contribuer en soumettant des pull requests ! diff --git a/fr/SUMMARY.md b/fr/SUMMARY.md new file mode 100644 index 00000000..c3e396e8 --- /dev/null +++ b/fr/SUMMARY.md @@ -0,0 +1,27 @@ +- [Utilisation de base](basic.md) +- [Écrire du code universel](universal.md) +- [Structure de code](structure.md) +- [Routage et scission du code](routing.md) +- [Récupération de données et état](data.md) +- [Hydratation côté client](hydration.md) +- [Introduction au moteur de dépaquetage](bundle-renderer.md) +- [Configuration de pré-compilation](build-config.md) +- [Gestion des CSS](css.md) +- [Gestion des entêtes (En)](head.md) +- [Mise en cache](caching.md) +- [Envoi par flux](streaming.md) +- [Référence de l'API](api.md) + - [createRenderer](api.md#createrendereroptions) + - [createBundleRenderer](api.md#createbundlerendererbundle-options) + - [Class: Renderer](api.md#class-renderer) + - [Class: BundleRenderer](api.md#class-bundlerenderer) + - [Options de Renderer](api.md#renderer-options) + - [template](api.md#template) + - [clientManifest](api.md#clientmanifest) + - [inject](api.md#inject) + - [shouldPreload](api.md#shouldpreload) + - [runInNewContext](api.md#runinnewcontext) + - [basedir](api.md#basedir) + - [cache](api.md#cache) + - [directives](api.md#directives) + - [Plugins webpack](api.md#webpack-plugins) diff --git a/fr/api.md b/fr/api.md new file mode 100644 index 00000000..dd1a2f12 --- /dev/null +++ b/fr/api.md @@ -0,0 +1,236 @@ +# Référence de l'API + +## `createRenderer([options])` + +Crée une instance de [`Renderer`](#class-renderer) avec des [options](#renderer-options) optionnelles. + +``` js +const { createRenderer } = require('vue-server-renderer') +const renderer = createRenderer({ ... }) +``` + +## `createBundleRenderer(bundle[, options])` + +Crée une instance de [`BundleRenderer`](#class-bundlerenderer) avec un paquetage serveur et des [options](#renderer-options) optionnelles. + +``` js +const { createBundleRenderer } = require('vue-server-renderer') +const renderer = createBundleRenderer(serverBundle, { ... }) +``` + +L'argument `serverBundle` peut être l'un des éléments suivants : + +- Un chemin absolu pour générer un fichier de paquetage (`.js` ou `.json`). Doit commencer par `/` pour être considéré comme un chemin de fichier. + +- Un objet de paquetage généré par webpack + `vue-server-renderer/server-plugin`. + +- Une chaîne de caractères de code JavaScript (non recommandé). + +Voyez l'[Introduction au moteur de dépaquetage](./bundle-renderer.md) et la [Configuration de pré-compilation](./build-config.md) pour plus de détails. + +## `Class: Renderer` + +- #### `renderer.renderToString(vm[, context], callback)` + + Fait le rendu d'une instance de Vue sous forme de chaîne de caractères. L'objet de contexte est optionnel. La fonction de rappel est une fonction de rappel typique de Node.js avec en premier argument l'erreur potentielle et en second argument la chaîne de caractères du rendu. + +- #### `renderer.renderToStream(vm[, context])` + + Fait le rendu d'une instance de Vue sous forme de flux. L'objet de contexte est optionnel. Voir l'[Envoi par flux](./streaming.md) pour plus de détails. + +## `Class: BundleRenderer` + +- #### `bundleRenderer.renderToString([context, ]callback)` + + Fait le rendu d'un paquetage sous forme de chaîne de caractères. L'objet de contexte est optionnel. La fonction de rappel est une fonction de rappel typique de Node.js avec en premier argument l'erreur potentielle et en second argument la chaîne de caractères du rendu. + +- #### `bundleRenderer.renderToStream([context])` + + Fait le rendu d'un paquetage sous forme de flux. L'objet de contexte est optionnel. Voir l'[Envoi par flux](./streaming.md) pour plus de détails. + +## Options de `Renderer` + +- #### `template` + + Fournit un modèle de page pour la page HTML complète. Le modèle de page devrait contenir en commentaire `` qui permet de définir l'emplacement du contenu de chaque rendu de l'application. + + Le modèle de page supporte également l'interpolation basique en utilisant le contexte du rendu : + + - utilisez les double moustaches pour de l'interpolation avec HTML échappé et + - utilisez les triple moustaches pour de l'interpolation avec HTML non échappé. + + Le modèle de page injecte automatiquement le contenu quand certaines données sont trouvées dans le contexte du rendu : + + - `context.head`: (string) n'importe quelle balise d'entête qui devrait être injectée dans la balise `` de la page. + + - `context.styles`: (string) n'importe quelle CSS qui devrait être injectée dans la balide `` de la page. Notez que cette propriété va automatiquement être injectée si vous utilisez `vue-loader` + `vue-style-loader` pour la CSS de vos composants. + + - `context.state`: (Object) L'état initial du store Vuex devrait être injecté dans la page sous la variable `window.__INITIAL_STATE__`. Le JSON en ligne est automatiquement désinfecté avec [serialize-javascript](https://github.com/yahoo/serialize-javascript) pour éviter les injections XSS. + + En plus, quand `clientManifest` est fourni, le modèle de page injecte automatiquement les éléments suivants : + + - JavaScript client et fichiers CSS nécessaires pour le rendu (avec les fragments asynchrones automatiquement déduits), + - utilisation optimal des indices de ressources `` pour le rendu de la page. + + Vous pouvez désactiver toutes ces injections en passant `inject: false` au moteur de rendu. + + Voir également : + + - [Utiliser un modèle de page](./basic.md#utiliser-un-modele-de-page) + - [Injection manuelle des fichiers](./build-config.md#injection-manuelle-des-fichiers) + +- #### `clientManifest` + + - 2.3.0+ + + Fournit un objet de build de manifeste généré par `vue-server-renderer/client-plugin`. Le manifeste client fournit le paquetage de moteur de rendu avec ses propres informations pour l'injection automatique de fichiers dans le modèle de page HTML. Pour plus de détails, consultez [Générer le `clientManifest`](./build-config.md#generer-le-clientmanifest). + +- #### `inject` + + - 2.3.0+ + + Contrôle la manière d'exécuter des injections automatiques en utilisant `template`. Par défaut à `true`. + + Voir aussi : [Injection manuelle des fichiers](./build-config.md#injection-manuelle-des-fichiers). + +- #### `shouldPreload` + + - 2.3.0+ + + Une fonction pour contrôler quels fichiers doivent avoir une ressource d'indice `` de générée. + + Par défaut, seuls les fichiers JavaScript et les fichiers CSS seront pré-chargés, car ils sont absolument nécessaires pour le démarrage de l'application. + + Pour les autres types de fichiers comme les images et les polices, le pré-chargement pouvant gâcher de la bande passante inutilement et même baisser les performances, cela est laissé à votre appréciation. Vous pouvez contrôler précisément le pré-chargement en utilisant l'option `shouldPreload` : + + ``` js + const renderer = createBundleRenderer(bundle, { + template, + clientManifest, + shouldPreload: (file, type) => { + // le type est déduit en se basant sur l'extension du fichier. + // https://fetch.spec.whatwg.org/#concept-request-destination + if (type === 'script' || type === 'style') { + return true + } + if (type === 'font') { + // pré-charger uniquement les polices woff2 + return /\.woff2$/.test(file) + } + if (type === 'image') { + // charger uniquement les images importantes + return file === 'hero.jpg' + } + } + }) + ``` + +- #### `runInNewContext` + + - 2.3.0+ + - seulement utilisée avec `createBundleRenderer` + - Requiert : `boolean | 'once'` (`'once'` est seulement supporté dans la 2.3.1+) + + Par défaut, pour chaque rendu, le moteur de dépaquetage va créer un nouveau contexte V8 et ré-exécuter le paquetage complet. Cela a plusieurs bénéfices, comme par exemple, isoler le code de l'application des processus du serveur ce qui permet d'[Eviter les singletons d'état](./structure.md#eviter-les-singletons-detat) mentionnés dans la documentation. Cependant, ce mode a des coûts de performance importants car ré-exécuter le paquetage est quelque chose de coûteux, surtout quand l'application est grosse. + + Cette option est par défaut à `true` pour la rétro-compatibilité, mais il est recommandé d'utiliser `runInNewContext: false` ou `runInNewContext: 'once'` si vous le pouvez. + + > Dans la 2.3.0 cette option a un bogue car `runInNewContext: false` exécute toujours le paquetage en utilisant un contexte global séparé. Les informations suivantes sont donc valables pour la version 2.3.1+. + + Avec `runInNewContext: false`, le code de paquetage va tourner dans le même contexte `global` du processus serveur, donc faites attention au code qui modifie `global` dans le code de votre application. + + Avec `runInNewContext: 'once'` (2.3.1+), le paquetage est évalué dans un contexte `global` séparé, cependant cela n'est effectué qu'au démarrage. Cela permet une meilleur isolation du code de l'application puisqu'il empêche le paquetage d'accidentellement polluer l'objet `global` du processus serveur. Les limitations sont les suivantes : + + 1. Les dépendances qui modifient l'objet `global` (ex. polyfills) ne peuvent être externalisées dans ce mode, + 2. Les valeurs retournées lors de l'exécution du paquetage utiliseront des constructeurs globaux différents. Par ex. une erreur levée à l'intérieur du paquetage ne sera pas une instance de `Error` dans le processus serveur. + + Voir aussi : [Structure de code](./structure.md) + +- #### `basedir` + + - 2.2.0+ + - seulement utilisée avec `createBundleRenderer` + + Déclarer explicitement le dossier de base du paquetage serveur afin de résoudre les dépendances `node_modules`. Cela est nécessaire si le fichier de paquetage généré est placé à un endroit différent de là où les dépendances externes npm sont installées, ou si `vue-server-renderer` est lié à npm dans votre projet courant. + +- #### `cache` + + Fournit une implémentation de [Mise en cache au niveau du composant](./caching.md#mise-en-cache-au-niveau-du-composant). L'objet de cache doit implémenter l'interface suivante (utilisation des notations Flow) : + + ``` js + type RenderCache = { + get: (key: string, cb?: Function) => string | void; + set: (key: string, val: string) => void; + has?: (key: string, cb?: Function) => boolean | void; + }; + ``` + + Une utilisation typique est de passer un [objet de mise en cache qui supprime l'objet le plus récemment utilisé](https://github.com/isaacs/node-lru-cache) : + + ``` js + const LRU = require('lru-cache') + + const renderer = createRenderer({ + cache: LRU({ + max: 10000 + }) + }) + ``` + + Notez que cet objet de mise en cache doit au moins implémenter `get` et `set`. De plus `get` et `set` peuvent être optionnellement asynchrone s'ils acceptent en second argument une fonction de rappel. Cela permet à la mise en cache d'utiliser des APIs. Par ex. un client Redis : + + ``` js + const renderer = createRenderer({ + cache: { + get: (key, cb) => { + redisClient.get(key, (err, res) => { + // gérer les erreur s'il y en a + cb(res) + }) + }, + set: (key, val) => { + redisClient.set(key, val) + } + } + }) + ``` + +- #### `directives` + + Vous permet de fournir des implémentations côté serveur pour vos directives personnalisées : + + ``` js + const renderer = createRenderer({ + directives: { + example (vnode, directiveMeta) { + // transformer les vnode en directive de liaison de metadata + } + } + }) + ``` + + Consultez l'[implementation de `v-show` côté serveur](https://github.com/vuejs/vue/blob/dev/src/platforms/web/server/directives/show.js) en tant qu'exemple. + +## Plugins webpack + +Les pluging webpack sont fournis en fichiers autonomes et devraient être requis en direct : + +``` js +const VueSSRServerPlugin = require('vue-server-renderer/server-plugin') +const VueSSRClientPlugin = require('vue-server-renderer/client-plugin') +``` + +Les fichiers générés par défaut sont : + +- `vue-ssr-server-bundle.json` pour le plugin serveur, +- `vue-ssr-client-manifest.json` pour le plugin client. + +Les noms de fichiers peuvent être personnalisés lors de la création des instances des plugins : + +``` js +const plugin = new VueSSRServerPlugin({ + filename: 'my-server-bundle.json' +}) +``` + +Voir la [Configuration de pré-compilation](./build-config.md) pour plus d'informations. diff --git a/fr/basic.md b/fr/basic.md new file mode 100644 index 00000000..b4723318 --- /dev/null +++ b/fr/basic.md @@ -0,0 +1,150 @@ +# Utilisation de base + +## Installation + +``` bash +npm install vue vue-server-renderer --save +``` + +Nous allons utiliser npm tout au long de ce guide, n'hésitez pas à utiliser [Yarn](https://yarnpkg.com/en/) à la place. + +#### Notes + +- Il est recommandé d'utiliser une version 6 ou supérieur de Node.js +- `vue-server-renderer` et `vue` doivent utiliser des numéros de version identiques. +- `vue-server-renderer` utilise plusieurs modules Node.js natifs fournis uniquement par Node.js. Nous fournirons une version exécutable qui pourra tourner sur les autres moteurs JavaScript dans le futur. + +## Faire le rendu d'une instance de Vue + +``` js +// Étape 1 : créer une instance de Vue +const Vue = require('vue') +const app = new Vue({ + template: `
Hello World
` +}) + +// Étape 2 : créer un moteur de rendu +const renderer = require('vue-server-renderer').createRenderer() + +// Étape 3 : faire le rendu de l'instance en HTML +renderer.renderToString(app, (err, html) => { + if (err) throw err + console.log(html) + // =>
Hello World
+}) +``` + +## Intégration avec un serveur + +Il est plus simple d'utiliser le code précédent avec un serveur Node.js, comme par exemple [Express](https://expressjs.com/) : + +``` bash +npm install express --save +``` +--- +``` js +const Vue = require('vue') +const server = require('express')() +const renderer = require('vue-server-renderer').createRenderer() + +server.get('*', (req, res) => { + const app = new Vue({ + data: { + url: req.url + }, + template: `
L'URL visité est : {{ url }}
` + }) + + renderer.renderToString(app, (err, html) => { + if (err) { + res.status(500).end('Erreur interne du serveur') + return + } + res.end(` + + + Bonjour + ${html} + + `) + }) +}) + +server.listen(8080) +``` + +## Utiliser un modèle de page + +Quand vous faites le rendu d'une application Vue, le moteur de rendu fournit uniquement les balises de votre application. Dans cet exemple, nous allons ajouter de part et d'autre la structure HTML nécessaire à toutes pages. + +Le plus simple est de directement fournir un modèle de page lors de la création du moteur de rendu. La plupart du temps, nous allons mettre le modèle de page dans son propre fichier. Par ex. `index.template.html` : + +``` html + + + Bonjour + + + + +``` + +Notez que le commentaire `` représente la zone où les balises de votre application vont être injectées. + +Nous allons ensuite lire et passer le contenu du fichier au générateur de rendu de Vue : + +``` js +const renderer = createRenderer({ + template: require('fs').readFileSync('./index.template.html', 'utf-8') +}) + +renderer.renderToString(app, (err, html) => { + console.log(html) // sera la page complète avec le contenu de l'application injecté. +}) +``` + +### Interpolation dans le modèle de page + +Le modèle de page supporte également une interpolation simple. Avec le modèle de page suivant : + +``` html + + + + {{ title }} + + + {{{ meta }}} + + + + + +``` + +Nous pouvons fournir les données d'interpolation suivantes à travers un « objet de contexte de rendu » en tant que second argument de `renderToString` : + +``` js +const context = { + title: 'Bonjour', + meta: ` + + + ` +} + +renderer.renderToString(app, context, (err, html) => { + // le titre de la page sera « Bonjour » + // avec les balises `` injectées +}) +``` + +L'objet `context` peut également être partagé avec l'instance de l'application de Vue, permettant aux composants de dynamiquement fournir des données pour l'interpolation du modèle de page. + +De plus, le modèle de page supporte des fonctionnalités avancées comme : + +- l'injection automatique de CSS critique lors de l'utilisation de composants `*.vue`, +- l'injection automatique de balises `` avec l'utilisation de `clientManifest`, +- l'injection automatique de l'état de Vuex pour l'hydratation cliente avec prévention XSS. + +Nous discuterons de cela quand nous introduirons ces concepts plus tard dans le guide. diff --git a/fr/build-config.md b/fr/build-config.md new file mode 100644 index 00000000..210d82e1 --- /dev/null +++ b/fr/build-config.md @@ -0,0 +1,216 @@ +# Configuration de pré-compilation + +Nous allons suposez que vous savez déjà comment configurer webpack pour un projet uniquement client. La configuration pour un projet avec du SSR va être en grande partie similaire, mais nous vous suggérons de séparer vos configurations en trois fichiers : *base*, *client* et *server*. La configuration de base contient la configuration partagée par les deux environnements, comme les chemins de sortie, les aliases et les loaders. La configuration du serveur et la configuration du client peut simplement étendre la configuration de base en utilisant [webpack-merge](https://github.com/survivejs/webpack-merge). + +## Configuration serveur + +La configuration serveur est destinée à générer le paquetage serveur qui va être passé à `createBundleRenderer`. Elle devrait ressembler à cela : + +``` js +const merge = require('webpack-merge') +const nodeExternals = require('webpack-node-externals') +const baseConfig = require('./webpack.base.config.js') +const VueSSRServerPlugin = require('vue-server-renderer/server-plugin') + +module.exports = merge(baseConfig, { + // Fichier d'entrée serveur de l'application + entry: '/path/to/entry-server.js', + + // Cela permet à webpack de gérer les imports dynamiques d'une manière + // approprié pour Node.js, et dit également à `vue-loader` d'émettre un code approprié pour le serveur + // lors de la compilation du composant Vue. + target: 'node', + + // Pour le support des sources maps des paquetages + devtool: 'source-map', + + // Cela dit au paquetage serveur d'utiliser les exports au format Node.js + output: { + libraryTarget: 'commonjs2' + }, + + // https://webpack.js.org/configuration/externals/#function + // https://github.com/liady/webpack-node-externals + // Externalise les dépendances de l'application. Cela rend le build serveur plus rapide + // et génère un fichier de paquetage plus petit. + externals: nodeExternals({ + // ne pas externaliser les dépendances qui ont besoin d'être traitées par webpack. + // vous pouvez ajouter plus de types de fichier ici, comme par ex. avec les fichiers `*.vue` + // vous devriez aussi lister des exceptions qui modifient `global` (par ex. les polyfills) + whitelist: /\.css$/ + }), + + // Ceci est le plugin qui va créer entièrement la sortie pour le build serveur + // dans un seul fichier JSON. Le fichier généré par défaut va être + // `vue-ssr-server-bundle.json` + plugins: [ + new VueSSRServerPlugin() + ] +}) +``` + +Après que `vue-ssr-server-bundle.json` ai été généré, passez simplement le chemin du fichier à `createBundleRenderer` : + +``` js +const { createBundleRenderer } = require('vue-server-renderer') +const renderer = createBundleRenderer('/path/to/vue-ssr-server-bundle.json', { + // ...autre options pour le moteur +}) +``` + +Vous pouvez alternativement tout aussi bien passer le paquetage comme un objet à `createBundleRenderer`. Cela est utile pour le rechargement à chaud pendant le développement. Voyez la démo de HackerNews pour une [référence de mise en place](https://github.com/vuejs/vue-hackernews-2.0/blob/master/build/setup-dev-server.js). + +### Limitations externes + +Notons que dans l'option `externals` nous avons exclus les fichiers CSS. C'est parce que les fichiers CSS importés par dépendances doivent quand même être gérés par webpack. Si vous importez n'importe quels autres types de fichier également pris en charge par webpack (ex : `*.vue`, `*.styl`), vous pouvez également les ajouter à la liste des exceptions. + +Si vous utilisez `runInNewContext: 'once'` ou `runInNewContext: true`, alors vous devrez également ajouter aux exceptions les polyfills qui modifient `global` comme par ex. `babel-polyfill`. Cela est dû au fait qu'en utilisant un nouveau mode de contexte, **le code à l'intérieur d'un paquetage serveur a son propre objet `global`.** Parce qu'il n'est plus nécessaire de faire cela côté serveur en utilisant Node.js 7.6+, c'est d'autant plus facile de ne les importer que côté client. + +## Configuration cliente + +La configuration cliente peut être en grande partie la même grâce à la configuration de base. Bien sur vous devez faire pointer `entry` sur votre fichier d'entrée client. En plus de cela, si vous utilisez le plugin `CommonsChunkPlugin`, assurez-vous de ne l'utiliser que dans la configuration cliente car le paquetage serveur requiert un unique fragment d'entrée. + +### Générer le `clientManifest` + +> requiert la version 2.3.0+ + +En plus du paquetage serveur, nous pouvons également générer un build de manifeste client. Avec le manifeste client et le paquetage serveur, le moteur a maintenant les informations du build serveur *et* du build client, ainsi il peut automatiquement déduire et injecter les [directives pré-chargées et récupérées](https://css-tricks.com/prefetching-preloading-prebrowsing/) ainsi que les balises `` / ` + + + + +` +``` + +### Injection manuelle des fichiers + +Par défaut, l'injection des fichiers est automatique quand vous fournissez l'option de rendu `template`. Mais parfois vous aurez besoin d'une granularité de contrôle plus fine en ce qui concerne la manière dont les templates seront injectés, ou peut-être que vous n'utiliserez pas de template du tout. Dans tous les cas, vous pouvez passer `inject: false` quand le moteur est créé et manuellement réaliser l'injection des fichiers. + +Dans la fonction de rappel de `renderToString`, l'objet `context` que vous passez va exposer les méthodes suivantes : + +- `context.renderStyles()` + + Cela va retourner une balise `