NodeAtlas fonctionne avec une configuration via l'utilisation d'un webconfig.json
qui lui permet d'étendre les possibilités du site de manière évolutive tout au long de sa vie. Par exemple, pour créer un site sans JavaScript côté serveur (pas de controller), il suffit de ne renseigner qu'un template
pour chaque route.
Cependant, vous pourrez toujours utilisé du JavaScript inline dans ses templates grâce à l'utilisation du moteur de template EJS2 avec lequel fonctionne NodeAtlas.
Voyons les possibilités de nos sites par agrégat simple de fichiers templates.
Ci-dessous un exemple de configuration.
{
"templatesRelativePath": "templates",
"routes": {
"/": {
"template": "index.htm"
},
"/member.html": {
"template": "member.htm",
"postSupport": false
},
"/member-without-extension/": {
"template": "member.htm",
"getSupport": false
},
"about.html": {
"template": "about.htm"
},
"/error.html": {
"template": "error.htm",
"statusCode": 404,
"mimeType": "text/plain"
}
}
}
Pour faire tourner cet ensemble de fichier :
├─ templates/
│ ├─ index.htm
│ ├─ member.htm
│ └─ error.htm
└─ webconfig.json
aux adresses :
Note : Si templatesRelativePath n'est pas présent dans « webconfig.json », par défaut le dossier des templates est bien templates. templatesRelativePath est donc utile seulement pour changer le nom/chemin du répertoire.
La configuration ci-dessous est équivalente à la configuration de la section juste au-dessus
{
"templatesRelativePath": "templates",
"routes": {
"/": "index.htm",
"/member.html": {
"template": "member.htm",
"postSupport": false
},
"/member-without-extension/": {
"template": "member.htm",
"getSupport": false
},
"about.html": "about.htm",
"/error.html": {
"template": "error.htm",
"statusCode": 404,
"mimeType": "text/plain"
}
}
}
car
"about.html": "about.htm",
est un raccourci de
"about.html": {
"template": "about.htm"
}
Évidemment ce raccourci ne sert que si template
est le seul paramètre à déclarer de la route.
Vous pouvez également héberger tout un tas de fichier sur votre site dans un dossier public. Par exemple avec cette configuration :
{
"assetsRelativePath": "assets",
"routes": {
"/": {
"template": "index.htm"
}
}
}
et cet ensemble de fichiers :
├─ assets/
│ ├─ stylesheets/
│ │ └─ common.css
│ ├─ javascript/
│ │ └─ common.js
│ └─ media/
│ └─ images/
│ └─ logo.png
├─ templates/
│ └─ index.htm
└─ webconfig.json
vous aurez accès aux adresses :
Note : Si assetsRelativePath n'est pas présent dans « webconfig.json », par défaut le dossier public est bien assets. assetsRelativePath est donc utile seulement pour changer le nom/chemin du répertoire.
Il est possible de manager les informations livrées par NodeAtlas à la demande d'une ressource (comme le maxAge
, l'etag
, etc.) via la propriété staticOptions
du webconfig. Pour connaître la totalité des possibilités, voir les options d'Express.
Par exemple, pour un webconfig de développement, il peut être intéressant de mettre le maxAge
à 0 de manière à toujours avoir la dernière modification d'un fichier sans s'acharner sur le rechargement de page.
{
"staticOptions": {
"maxAge": 0
},
"routes": {
"/": {
"template": "index.htm"
}
}
}
Vous pouvez segmenter vos codes HTML afin de ne pas répéter le code redondant comme par exemple les parties « head » et « foot » ou tout autre fragment de code :
{
"componentsRelativePath": "components/",
"routes": {
"/": {
"template": "index.htm"
},
"/liste-des-membres/": {
"template": "members.htm"
}
}
}
avec les fichiers suivants :
├─ assets/
│ ├─ stylesheets/
│ │ └─ common.css
│ └─ javascript/
│ └─ common.js
├─ components/
│ ├─ head.htm
│ └─ foot.htm
├─ templates/
│ ├─ index.htm
│ └─ members.htm
└─ webconfig.json
components/head.htm
<!DOCTYPE html>
<html lang="fr-fr">
<head>
<meta charset="utf-8" />
<title>Hello world</title>
<link type="text/css" rel="stylesheet" href="stylesheets/common.css" media="all" />
</head>
<body>
components/foot.htm
<script async type="text/javascript" src="javascript/common.js"></script>
</body>
</html>
templates/index.htm
<%- include('head.htm') %>
<div>
<h1>Bienvenue</h1>
<p>C'est la page d'accueil.</p>
</div>
<%- include('foot.htm') %>
templates/members.htm
<%- include('head.htm') %>
<div>
<h1>Liste des members</h1>
<p>C'est la page des membres.</p>
</div>
<%- include('foot.htm') %>
vous aurez accès aux adresses :
Note : Si componentsRelativePath n'est pas présent dans « webconfig.json », par défaut le dossier des includes est bien components. componentsRelativePath est donc utile seulement pour changer le nom/chemin de répertoire.
Il est possible avec le même template et les mêmes includes de générer des pages au contenu différent (utile en mode génération d'assets HTML). Activer les variations avec la configuration suivante :
{
"commonVariation": "common.json",
"variationsRelativePath": "variations",
"routes": {
"/": {
"template": "template.htm",
"variation": "index.json",
},
"/liste-des-membres/": {
"template": "template.htm",
"variation": "members.json",
}
}
}
avec les fichiers suivants :
├─ assets/
│ ├─ stylesheets/
│ │ ├─ common.css
│ │ ├─ index.css
│ │ └─ members.css
│ └─ javascript/
│ ├─ common.js
│ ├─ index.js
│ └─ members.js
├─ components/
│ ├─ head.htm
│ └─ foot.htm
├─ variations/
│ ├─ common.json
│ ├─ index.json
│ └─ members.json
├─ templates/
│ └─ template.htm
└─ webconfig.json
components/head.htm
<!DOCTYPE html>
<html lang="fr-fr">
<head>
<meta charset="utf-8" />
<title><%- specific.titlePage %></title>
<link type="text/css" rel="stylesheet" href="stylesheets/<%= common.classCssCommon %>.css" media="all" />
<link type="text/css" rel="stylesheet" href="stylesheets/<%= specific.classPage %>.css" media="all" />
</head>
<body class="<%= specific.classPage %>">
components/foot.htm
<script async type="text/javascript" src="javascript/<%= common.classJsCommon %>.js"></script>
</body>
</html>
templates/template.htm
<%- include('head.htm') %>
<div class="title"><%- common.titleWebsite %></div>
<div>
<h1><%- specific.titlePage %></h1>
<%- specific.content %>
</div>
<%- include('foot.htm') %>
variations/common.json
{
"titleWebsite": "Titre du site",
"classCssCommon": "common",
"classJsCommon": "common"
}
variations/index.json
{
"titlePage": "Bienvenue",
"classPage": "index",
"content": "<p>C'est la page d'accueil.</p>"
}
variations/members.json
{
"titlePage": "Liste des membres",
"classPage": "members",
"content": "<p>C'est la page des membres.</p>"
}
vous aurez accès aux adresses :
Note : Si variationsRelativePath n'est pas présent dans « webconfig.json », par défaut le dossier des variations est bien variations. variationsRelativePath est donc utile seulement pour changer le nom/chemin de répertoire.
Sur le même principe, les variations peuvent être utilisées pour créer la même page, mais dans des langues différentes :
{
"languageCode": "en-gb",
"variationsRelativePath": "languages",
"routes": {
"/": {
"template": "landing.htm",
"variation": "landing.json"
},
"/home/": {
"template": "home.htm",
"variation": "home.json"
},
"/accueil/": {
"template": "home.htm",
"variation": "home.json",
"languageCode": "fr-fr"
}
}
}
Note : Dans cet exemple j'ai décidé de me passer d'un fichier de variation commune, car je n'ai pas précisé de commonVariation. J'ai également totalement arbitrairement décidé de renommer mon dossier variations en languages.
avec les fichiers suivants :
├─ components/
│ ├─ head.htm
│ └─ foot.htm
├─ languages/
│ ├─ landing.json
│ ├─ en-gb
│ │ └─ home.json
│ └─ fr-fr
│ └─ home.json
├─ templates/
│ ├─ landing.htm
│ └─ home.htm
└─ webconfig.json
components/head.htm
<!DOCTYPE html>
<html lang="<%= languageCode %>">
<head>
<meta charset="utf-8" />
<title><%= specific.titlePage %></title>
</head>
<body class="<%= specific.classPage %>">
components/foot.htm
</body>
</html>
templates/landing.htm
<%- include('head.htm') %>
<select>
<% for (var i = 0; i < specific.selectLabel.length; i++) { %>
<option><%= specific.selectLabel[i] %></option>
<% } %>
</select>
<%- include('foot.htm') %>
templates/home.htm
<%- include('head.htm') %>
<div>
<h1><%- specific.titlePage %></h1>
<%- specific.content %>
</div>
<%- include('foot.htm') %>
languages/landing.json
{
"titlePage": "Landing",
"classPage": "landing",
"selectLabel": [
"English",
"Français"
]
}
languages/en-gb/home.json
{
"titlePage": "Welcome",
"classPage": "home",
"content": "<p>This is a home page.</p>"
}
languages/fr-fr/home.json
{
"titlePage": "Bienvenue",
"classPage": "home",
"content": "<p>C'est la page d'accueil.</p>"
}
vous aurez accès aux adresses :
Note : Par défaut c'est le languageCode racine qui conditionne la langue d'affichage du site. Cependant, spécifiquement par page on peut changer la langue avec également le languageCode. Il faut également savoir que dès que le site ou une page à un languageCode dans la configuration, ses fichiers de variations doivent être placées dans un sous répertoire portant le nom du languageCode.
Vous avez peut-être constaté dans l'exemple précédent que le fichier landing.json
n'était pas dans le dossier en-gb/
ou fr-fr/
. Cela est tout à fait possible et signifie qu'il sera utilisé dans les langues qui ne le possèdent pas dans leur dossier.
Aussi, quand un languageCode
est précisé, NodeAtlas part d'abord chercher la valeur dans le fichier du dossier correspondant. Si celle-ci n'y ai pas, alors il part la chercher dans le dossier parent (celui utilisé en standard pour les variations sans multilingue).
Cela va vous permettre par exemple de manager la langue maître directement dans le dossier de variation. Ainsi avec l'exemple suivant :
│
┊┉
├─ variations/
│ ├─ common.json
│ ├─ home.json
│ ├─ fr-fr
│ │ ├─ common.json
│ │ └─ home.json
┊┉
vous pouvez
en-gb
directement à la racine de variations/
(comme NodeAtlas ne trouve rien dans en-gb
il utilise alors les valeurs des fichiers racines) etfr-fr
dans le dossier fr-fr/
,ainsi, si une phrase n'est pas encore traduite dans un fichier fr-fr
, au lieu de renvoyer une erreur, NodeAtlas renverra la version racine, soit la version en-gb
.
Vous pouvez également décider de faire tourner chaque langue dans un « webconfig.json » différent. Avec l'ensemble de fichier suivant :
├─ components/
│ ├─ head.htm
│ └─ foot.htm
├─ variations/
│ ├─ landing.json
│ ├─ en-gb
│ │ ├─ home.json
│ │ └─ members.json
│ └─ fr-fr
│ ├─ home.json
│ └─ members.json
├─ templates/
│ ├─ landing.htm
│ ├─ home.htm
│ └─ members.htm
├─ webconfig.json
├─ webconfig.en-gb.json
└─ webconfig.fr-fr.json
vous pourriez avoir les « webconfig.json » suivant :
webconfig.json
{
"routes": {
"/": {
"template": "landing.htm",
"variation": "landing.json"
}
}
}
webconfig.en-gb.json
{
"httpPort": 81,
"urlRelativeSubPath": "english",
"languageCode": "en-gb",
"routes": {
"/": {
"template": "home.htm",
"variation": "home.json"
},
"/members-list/": {
"template": "members.htm",
"variation": "members.json"
}
}
}
webconfig.fr-fr.json
{
"httpPort": 82,
"urlRelativeSubPath": "francais",
"languageCode": "fr-fr",
"routes": {
"/": {
"template": "home.htm",
"variation": "home.json"
},
"/liste-des-membres/": {
"template": "members.htm",
"variation": "members.json"
}
}
}
et avoir accès aux adresses :
Il est ensuite possible de faire du reverse proxy avec Bouncy (par exemple) pour ramener l'ensemble des urls sur le port 80 afin d'obtenir :
Par défaut, si vous utilisez la configuration suivante :
{
"routes": {
"/": {
"template": "index.htm"
}
}
}
cela est identique à utiliser celle-ci :
{
"httpHostname": "localhost",
"httpPort": 80,
"httpSecure": false,
"urlRelativeSubPath": "",
"routes": {
"/": {
"template": "index.htm"
}
}
}
et vous pourrez accéder à l'url : http://localhost/.
Changez alors la configuration en ceci :
{
"httpHostname": "127.0.0.1",
"httpPort": 7777,
"httpSecure": true,
"urlRelativeSubPath": "sub/folder",
"routes": {
"/": {
"template": "index.htm"
}
}
}
pour accéder à : https://127.0.0.1:7777/sub/folder/
Imaginons deux webconfigs dans lesquels nous allons créer nos propres variables comme suit :
{
"routes": {
"/": {
"template": "index.htm"
}
},
"_minified": ""
}
{
"routes": {
"/": {
"template": "index.htm"
}
},
"_minified": ".min"
}
avec cet ensemble de fichiers
├─ assets/
│ ├─ stylesheets/
│ │ ├─ common.css
│ │ └─ common.min.css
│ └─ javascript/
│ ├─ common.js
│ └─ common.min.js
├─ templates/
│ └─ index.htm
├─ webconfig.json
└─ webconfig.prod.json
et « index.htm » contenant :
<!DOCTYPE html>
<html lang="fr-fr">
<head>
<meta charset="utf-8" />
<title>Hello world</title>
<link rel="stylesheet" type="text/css" href="stylesheets/common<%= webconfig._minified %>.css" />
</head>
<body>
<div>Ceci est un test de récupération de ressources minifiées/non-minifiées.</div>
<script type="text/javascript" src="javascript/common<%= webconfig._minified %>.js"></script>
</body>
</html>
En lançant (depuis le dossier du site) la commande :
\> node </path/to/>node-atlas/
Nous aurons à l'adresse « http://localhost/ » la sortie suivante avec les fichiers non minifiés :
<!DOCTYPE html>
<html lang="fr-fr">
<head>
<meta charset="utf-8" />
<title>Hello world</title>
<link rel="stylesheet" type="text/css" href="stylesheets/common.css" />
</head>
<body>
<div>Ceci est un test de récupération de ressources minifiées/non-minifiées.</div>
<script type="text/javascript" src="javascript/common.js"></script>
</body>
</html>
Cependant en lançant la commande :
\> node </path/to/>node-atlas/server.js --webconfig webconfig.prod.json
Nous aurons à l'adresse « http://localhost/ » la sortie suivante avec les fichiers minifiés :
<!DOCTYPE html>
<html lang="fr-fr">
<head>
<meta charset="utf-8" />
<title>Hello world</title>
<link rel="stylesheet" type="text/css" href="stylesheets/common.min.css" />
</head>
<body>
<div>Ceci est un test de récupération de ressources minifiées/non-minifiées.</div>
<script type="text/javascript" src="javascript/common.min.js"></script>
</body>
</html>
Note : Il vaut mieux préfixer ses variables personnelles avec « _ » pour éviter des conflits avec des variables de configuration existantes ou futures.
Avec la configuration suivante il est possible de générer des assets HTML du rendu de chaque page dans un fichier associé. Le fichier sera (re)créé à chaque affichage de la page dans votre navigateur.
{
"htmlGeneratesBeforeResponse": true,
"generatesRelativePath": "generates",
"routes": {
"/": {
"template": "index.htm",
"generate": "/index.html"
},
"/liste-des-membres/": {
"template": "members.htm",
"generate": "/members/list.html"
},
"/liste-des-membres/?foo=bar": {
"template": "members.htm",
"generate": false
},
"/no/generate/property/": {
"template": "members.htm"
}
}
}
et l'ensemble de fichiers suivant :
├─ assets/
│ ├─ stylesheets/
│ │ ├─ common.css
│ └─ javascript/
│ └─ common.js
├─ generates/
├─ templates/
│ ├─ index.htm
│ └─ members.htm
└─ webconfig.json
on peut créer physiquement les assets :
├─ assets/
│ ┊┉
├─ generates/
│ ├─ stylesheets/
│ │ ├─ common.css
│ ├─ javascript/
│ │ └─ common.js
│ ├─ index.html
│ ├─ members/
│ │ └─ list.html
│ └─ no/
│ └─ generate/
│ └─ property ⤆ Ceci est un fichier
├─ templates/
│ ┊┉
└─ webconfig.json
en se rendant aux adresses :
Note : Il n'y a pas de génération pour « /liste-des-membres/?foo=bar » car generate
est à false
. Utilisez cette valeur pour ignorer des routes à la génération.
La génération s'enclenche quand on affiche la page uniquement parce que htmlGeneratesBeforeResponse existe et est à true. S'il est passé à false (ou enlevé) le seul moyen de générer toutes les pages du site sera via la commande node </path/to/>node-atlas/server.js --generate
qui génèrera toutes les pages d'un coup uniquement si le dossier de generatesRelativePath
existe. Bien entendu dans tous les cas cette commande marche et permet de régénérer toutes les pages suite à un changement telle qu'une modification dans un composant appelé sur toutes les pages.
De plus avec --generate
, l'intégralité du dossier assetsRelativePath
(dossier des fichiers publiques) sera copié dans le dossier generatesRelativePath
si les deux dossiers n'ont pas un chemin identique, et que generatesRelativePath
existe. Cela vous permet réellement d'obtenir en sortie dans le dossier de génération des pages « stand-alone » avec l'intégralité des fichiers auxquelles elles font appel (CSS / JS / Images, etc.).
Vous pouvez également désactiver la génération, même si un dossier generatesRelativePath
existe dans les dossiers, avec htmlGenerateEnable
à false
.
Note : Si generatesRelativePath n'est pas présent dans « webconfig.js », par défaut le dossier des générations est bien generates/. generatesRelativePath est donc utile seulement pour changer le nom/chemin répertoire.
Il est également possible de manager la création d'un site en simple page HTML avec la configuration suivante :
{
"languageCode": "fr-fr",
"enableIndex": true,
"htmlGeneratesBeforeResponse": true,
"generatesRelativePath": "../HTML/",
"assetsRelativePath": "../HTML/",
"routes": {
"/cv.html": {
"template": "index.htm",
"variation": "index.json"
},
"/en/cv.html": {
"template": "index.htm",
"variation": "index.json",
"languageCode": "en"
}
}
}
et l'ensemble de fichiers suivant :
├─ HTML/
│ ├─ stylesheets/
│ │ └─ common.css
│ └─ javascript/
│ └─ common.js
└─ engine/
├─ variations/
│ ├─ fr-fr/
│ │ └─ index.json
│ └─ en/
│ └─ index.json
├─ templates/
│ └─ index.htm
└─ webconfig.json
À l'adresse http://localhost/ s'affichera la liste des pages composants votre site (grâce à enableIndex à true).
Il ne restera plus qu'à, une fois votre travail terminé, admirer votre site HTML dans le dossier :
└─ HTML/
├─ stylesheets/
│ └─ common.css
├─ javascript/
│ └─ common.js
├─ cv.html
└─ en/
└─ cv.html