Développement front-end avancé

Vincent Garreau

 

Slides disponibles sur
slides.com/vincentgarreau

Workflows, outils et astuces pour un développement front-end avancé

H1 à H5 / P2015

vincentgarreau.com

Au programme

Lundi 29/04 Workflow CSS + ES2015/18
​Workflow JS + Modules et composants web
Mardi 30/04 Frameworks JS + Introduction à Vue.js
Jeudi 02/05 Suite intro Vue.js + Consignes TP n°1
Vendredi 03/05 Correction du TP n°1
Suite intro Vue.js + Consignes TP n°2
Vendredi 10/05 Correction du TP n°2 + Synthèse

18 heures avec vous ! 😅

Workflow CSS

Les bases du CSS

Préprocesseurs CSS

Postprocesseurs CSS

Méthodologies CSS

Astuces CSS

ES 2015/18 (ES6)

Les méthodes à connaître

Workflow JavaScript
Modules et composants web

Package managers

Linters JavaScript

Modules et composants web

Systèmes de modules

Module bundlers

Frameworks JavaScript
Introduction à Vue.js

Présentation rapide des frameworks JavaScript actuels

Introduction à Vue.js

Workflow CSS

Les bases du

CSS

Comment ajouter du CSS ?

<style>.element { width: 200px; }</style>  
<span style="width:200px"></span>
<link rel="stylesheet" href="style.css">

Internal style

Inline style

External style

Les sélecteurs CSS ont un poids qui détermine un ordre de priorité

 

Terme en anglais : CSS specificity

Terme en français : Poids des sélecteurs

<span style="color: red"> // 1000

#element // 100

.element // 10

span // 1

#element > div > li:hover // 100 + 1 + 1 + 10

.element !important // S'applique en priorité
Style inline
(HTML)

IDs
Classes, attributs,
pseudo classes (:)
Elements,
pseudo elements
(::)
1000 100 10 1

En CSS, on évite de se répéter

DRY :

Don't Repeat Yourself

cela dit...

 

KISS :

Keep It Simple, Stupid

.button-push { padding: 10px; }
<button class="button-push">Push 1</button>
<button class="button-push">Push 2</button>

.classes = réutilisables 👍🏻

#ids = uniques

 

D'après les standards W3C

Le  CSS doit être le plus

maintenable possible

💪

Préprocesseurs CSS

Un préprocesseur CSS contient une palette d'outils qui permet d'écrire un CSS plus maintenable

Plusieurs
préprocesseurs CSS
existent

 

Less

 

Sass

 
Stylus

Stylus

// CSS
.element {
  width: 200px;
  height: 80px;
  font-size: 1.2em;
}

// Stylus ({}, : et ; sont chacun optionnel)
.element
  width 200px
  height 80px
  font-size 1.2em

Léger et rapide à écrire

Stylus

// CSS
.element > li { padding:10px; }
.element > li:hover { padding:20px; }

// Stylus
.element
  > li
    padding 10px
    &:hover
      padding 20px

Principe d'indentation (évitez plus de 3 niveaux)

Variables

// Sans préprocesseur
.element
  width 20px
  height 20px
  margin-right 10px

// Avec préprocesseur
$element-size = 20px
.element
  width $element-size
  height $element-size
  margin-right $element-size / 2 // Opération

De nombreuses fonctionnalités

sont disponibles selon les préprocesseurs...

Mixins
Fonctions
Opérateurs

Conditions

Itérations

@extend

@block

....

Postprocesseurs CSS

Un postprocesseur CSS est un outil qui permet d'effectuer
des tâches spécifiques sur un fichier CSS

Exemple d'outil : PostCSS

 

PostCSS est un outil JavaScript qui permet d'effectuer des transformations d'un fichier CSS grâce à des plugins

 

Plugins PostCSS populaires :

autoprefixer : préfixe les propriétés

cssnext : permet d'écrire dès aujourd'hui du CSS4

Méthodologies CSS

Ensemble de conseils et de lignes de conduite

pour un CSS organisé et maintenable 

Catégorisation / Structure

 

Avantage d'un préprocesseur CSS :

 

Pouvoir générer un fichier CSS

à partir de plusieurs fichiers

 

Remarque

Sans préprocesseur, il est possible d'importer plusieurs fichiers CSS avec la méthode @import, mais cela est lourd car sans préprocesseur aucun fichier n'est généré.
Sans préprocesseur, 1 import = 1 requête HTTP en plus.

Exemple d'architecture CSS

7-1 Pattern
7 dossiers, 1 fichier

📁 base

📁 components

📁 layout

📁 pages

📁 themes

📁 abstracts

📁 vendors

main.scss

Convention de nommage

des classes

 

Permet d' éviter des cas problématiques comme écraser du style précédemment appliqué / mélanger des styles

 

Si plusieurs développeurs travaillent sur un même projet, appliquer une règle de  nommage  commune est  plus facile à comprendre / lire et à maintenir

Plusieurs conventions de nommage CSS existent

 

OOCSS  

Object-Oriented CSS


SMACSS  

Scalable and Modular Approach for CSS


BEM

Block Element Modifier

Convention de nommage

avec la méthodologie BEM

// block-name__element-name--modifier-name

<header class="app-header">
  <nav class="app-header-nav">
    <ul>
      <li class="app-header-nav__item"></li>
      <li class="app-header-nav__item app-header-nav__item--on"></li>
    </ul>
  </nav>
</header>

Block__Element--Modifier

Scoped CSS
&
CSS Modules

Quelques astuces CSS

Trucs et astuces, propriétés utiles...

flex

// CSS2
.nav
  .nav-item
    display inline-block
    vertical-align middle


// CSS3
.nav
  display flex
  align-items center

calc

// Largeur responsive à gauche, fixe à droite

.wrapper
  display flex
  width 100%

  .left // Largeur variable
    width calc(100% - 300px)

  .right // Largeur toujours égale à 300px
    width 300px

box-sizing

// Largeur de 100px, padding inclus
.myElement
  width 100px
  padding 20px
  box-sizing border-box

// border-box = padding inclus
// content-box (par défaut) = padding exclus

Bootstrap ?

Oui, mais avec modération 🍻

Classes vraiment utiles :

 

dropdown

modal

tooltip

Un fichier à part pour

réappliquer les classes Bootstrap 

// custom-bootstrap.styl (chargé après BS.)

.modal-header
  border-radius .25rem .25rem 0 0
  background $white-alabaster
  text-align center
  border-bottom 0

.form-control
  border 1px solid $grey-alto

Méthode pour nommer les

variables de couleurs

// var-colors.styl
$blue-picton = #36AAEA

// button.styl
.custom-button
  background-color $blue-picton

Gestion des icônes

Icon Fonts vs SVG

css-tricks.com/icon-fonts-vs-svg

 

Méthode SVG Inline

Insertion du code de l'icône SVG directement dans le HTML

 

Méthode SVG Symbols

Insertion de l'icône SVG dans le HTML en utilisant les symboles

Icônes : Méthode SVG Symbols​

// On sélectione l'icône en ciblant l'id du symbole dans la balise "use"
<div class="svg-wrap">
  <svg>
    <use xlink:href="#icon-cross"></use>
  </svg>
</div>
// On insère le fichier définition SVG dans le HTML (en haut, juste après l'ouverture du body)

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>

  <symbol id="icon-cross" viewBox="0 0 32 32">
    <title>cross</title>
    <path fill="#222" class="path1" d="M15.392 13.984l12.32-12.32c0.384-0.384 0.384-0.992 0-1.376s-0.992-0.384-1.376 0l-12.32 12.32-12.352-12.32c-0.384-0.384-0.992-0.384-1.376 0s-0.384 0.992 0 1.376l12.32 12.32-12.32 12.352c-0.384 0.384-0.384 0.992 0 1.376s0.992 0.384 1.376 0l12.352-12.32 12.32 12.32c0.384 0.384 0.992 0.384 1.376 0s0.384-0.992 0-1.376l-12.32-12.352z"></path>
  </symbol>

  <symbol id="icon-arrow" viewBox="0 0 32 32">
    <title>arrow</title>
    <path fill="#666" class="path1" d="M0.29 8.875l0.18 0.21 13.6 15.65c0.46 0.53 1.15 0.86 1.92 0.86s1.46-0.34 1.92-0.86l13.82-15.88c0.17-0.25 0.27-0.55 0.27-0.87 0-0.87-0.74-1.58-1.66-1.58v0h-28.68c-0.92 0-1.66 0.71-1.66 1.58 0 0.33 0.11 0.64 0.29 0.89z"></path>
  </symbol>

</defs>
</svg>

            

ES 2015/18 (ES6)

ES 2015 / ES 2018

 

Le standard JavaScript

ECMAScript 2015  = 6e édition / ES6

ECMAScript 2016  = 7e édition / ES7

ECMAScript 2017  = 8e édition / ES8

ECMAScript 2018  = 9e édition / ES9

let is the new var

// Anciennement var (ES5)
for (var i = 0; i <= 10; i++) {
  console.log(i)
}
console.log(i) // 11


// Avec let (ES6)
for (let i = 0; i <= 10; i++) {
  console.log(i)
}
console.log(i) // undefined 
var school = 'HETIC'

// Anciennement var (ES5)
if (school === 'HETIC') {
  var director = 'M. Beaux'
}
console.log(director) // M. Beaux

// Avec let (ES6)
if (school === 'HETIC') {
  let director = 'M. Beaux'
}
console.log(director) // undefined

var = portée des fonctions
let = portée de blocs (if, for...)

const / let

let age = 21
const firstname = 'Marie'
const identity = {}


age = 22 // let donc OK

firstname = 'Elodie' // const donc FAIL

identity = { firstname: 'Marie' }  // FAIL

identity.firstname = 'Marie' // OK

let = variable modifiable*
const  = variable non modifiable*
*non modifiable = non redéclarable

Fonctions fléchées

let obj = {
  bar: function () {
    return this
  }
}

console.log(obj.bar()) // obj

Règles de portée :
Le "this" d'une fonction fléchée n'est pas le même que le "this" d'une fonction "classique"

let obj = {
  bar: () => {
    return this
  }
}

console.log(obj.bar()) // window 

Littéraux de gabarits

year = '2021'

// ES5
var str = 'La P' + year + ' est au top'

// ES6 : Entre backticks (différents des quotes)
const str = `La P${year} est au top`


// La P2021 est au top

Argument "par défaut"

const setColor(value = '#FF0000') = () {
  console.log(`Couleur : ${value}`)
}

setColor("#000000") // Couleur : #000000

setColor() // Couleur : #FF0000

Includes

str = 'Les cours de marketing en H2 sont intenses'
youtubers = ['DirtyBiology', 'E-Penser']

// ES5
str.indexOf('marketing') !== -1 // true
youtubers['E-Penser'] !== undefined // true

// ES6
str.includes('marketing') // true 
youtubers.includes('E-Penser') // true

Promise

const getAvatar = (email) => {
  return new Promise((resolve, reject) => {
    $.ajax({
      url: `https://www.gravatar.com/${email}.json`,
      dataType: 'jsonp',
      success(data) { resolve(data) },
      error(data) { reject(data) }
    })
  })
}

getAvatar('08e83ed895943c88b5d11db6665ee8b4')
  .then((response) => {
    console.log('resolve data', response)
  })
  .catch((response) => {
    console.log('reject data', response)
  })

Async / Await

const ajax = (email) => {
  return new Promise((resolve, reject) => {
    $.ajax({
      url: `https://www.gravatar.com/${email}.json`,
      dataType: 'jsonp',
      success(data) { resolve(data) },
      error(data) { reject(data) }
    })
  })
}

const getAvatar = async function(email) {
  const res = await ajax(email)
  return res
}

getAvatar('08e83ed895943c88b5d11db6665ee8b4')
  .then((response) => { console.log('resolve data', response) })
  .catch((response) => { console.log('reject data', response) })

Utiliser les prochains

standards JS dès aujourd'hui 

Workflow JavaScript
Modules et composants web

Package managers

Gestion des librairies / plugins via un

gestionnaire de paquets 

Package managers populaires

 

npm

 

Yarn

// package.json
{
  "name": "my-portfolio-package",
  "version": "1.0.0",
  "dependencies": {
    "jquery": "^2.2.3"
  }
}

Yarn

// Commande pour installer le package jquery par exemple :
yarn add jquery

Linters JavaScript

Outil pour garder un code JS lisible, cohérent et harmonieux

Plugins

Task runners

Outils pour automatiser certaines tâches :

compilation d'assets, etc.

Task runner populaires

 

Gulp

 

Grunt

// gulpfile.js

// Import du module gulp et gulp-stylus
var gulp = require('gulp')
var stylus = require('gulp-stylus')

// Création d'une tâche, nommée "stylus"
gulp.task('stylus', function() {
  return gulp.src('./assets/css/main.styl')
    .pipe(stylus())
    .pipe(gulp.dest('./build/css'))
})

Gulp

// 1. Aller à l'emplacement du projet dans le terminal
// 2. Lancer la tâche "stylus" en tapant la commande :
gulp stylus

Modules et composants

C'est quoi ? Pourquoi ?

Un site / application web

doit être le plus

maintenable possible

💪

Programmation modulaire

 Consiste à utiliser une

approche modulaire de l'architecture d'un projet informatique

Module Javascript

Concept appliqué au

Javascript

Composant web

Plus large qu'un module :

Template HTML + Javascript + Style CSS

Systèmes de modules

Différents systèmes pour créer des modules Javascript

Plusieurs systèmes pour créer des modules Javascript

 

AMD


CommonJS 


ES2015 Modules

// operators.js

define([], function () {
  return {
    sum: function (a, b) {
      return a + b
    },
    divide: function (a, b) {
      return a / b
    }
  }
})
// app.js

define(["./operators.js"], function (operators) {
  var test = operators.sum(10, 5) // 15
})

AMD

Asynchronous Module Definition

// operators.js

exports.sum = function (a, b) {
  return a + b
}

exports.divide = function (a, b) {
  return a / b
}
// app.js

var operators = require('./operators.js')

var test = operators.sum(10, 5) // 15

CommonJS

// operators.js

const myObject = {}

myObject.sum = (a, b) => {
  return a + b
}

myObject.divide = (a, b) => {
  return a / b
}

export default myObject
// app.js

import operators from './operators.js'

const test = operators.sum(10, 5) // 15

ES2015 Modules

Module bundlers

Un outil qui analyse les modules pour générer des assets

Module bundlers populaires

 

Browserify


Webpack

Webpack

Grafikart - Lien du tutoriel

module.exports = {

  // Points d'entrée
  entry: './assets/js/main.js',

  // Configuration de l'export
  output: {
    path: './build/js',
    filename: "main.js"
  },
  
  // Configuration des loaders
  module: {
    rules: [
      { test: /\.css$/, loader: "style-loader!css-loader" },
    ]
  },
  
  // Configuration des plugins
  plugins: []
	
}

Webpack

Frameworks JavaScript
Introduction à Vue.js

Frameworks JavaScript

Un outil tout en un pour créer une application maintenable

Frameworks JS populaires

2010

2011

2011

2013

 

2009

2013

2014

Jeremy Ashkenas

Yehuda Katz

Meteor

Google

 

Google

Facebook

Evan You

Facile à prendre en main

Développement rapide

Un écosystème flexible grâce aux différents plugins Vue

Mises à jour régulières

Communauté active

Développement front-end avancé - WSF 4A P2020

By Vincent Garreau

Développement front-end avancé - WSF 4A P2020

Workflows, outils et astuces pour un développement front-end avancé

  • 702