Frontend

crash course

for backstage

Julien Bisconti

SRE / Data Engineer

Google Cloud Platform icon

contact

g.dev/julien

slides: bisconti.cloud

Before we start

  • Async is hard
  • State is hard
  • We're stupid
  • Plan accordingly
quote from Dan Abramov

I would also add:
(A few) Ops Lessons We All Learn The Hard Way

Content

  1. Browsers
  2. Javascript
  3. React
  4. Typescript
  5. Backstage

Browsers

  • HTTP (see curl)
  • HTML (see MDN HTML)
  • DOM
  • dynamic DOM with JS
  • javascript

MDN demo example

Javascript

the good part

Compilers and interpreters

source code => compiler => machine code => output

source code => interpreter => output

First class function

var give_me_one = () => 1;

// closure
function delay_add_four() {
    var a = 4;
    return function(arg) {
        return arg + a;
    }
}
var now_add_four_func = delay_add_four()

now_add_four_func(give_me_one()) // returns 5

Currying

var add = (a,b) => a + b;

add(10,20); // returns 30
var curry_add = a => b => a + b;

curry_add(10)(20); // returns 30

var add_15 = curry_add(15);

// Do something

add_15(5); // returns 20;

Callbacks

function callback(event) {
    console.log('event:', event)
}

document
    .querySelector('#callbacks')
    .addEventListener('click', callback);

Delayed execution

function make_callback(prefix) {
    var old_time = (new Date()).toISOString();
    return function(event) {
        var new_time = (new Date()).toISOString();
        console.log(prefix, event)
        console.log({old_time, new_time})
    }
}

document
    .querySelector('#delayed-execution')
    .addEventListener('click', make_callback('printing event:'));

Async JS

Modern Asynchronous Javascript

by Christophe Porteneuve

ExploreJS - Promise

by Dr. Axel Rauschmayer

Async/Await + Promise

async function github_graphql() {
  const query = { query: "query { viewer { login } }" };
  const body = { 
      method: 'post',
      headers: {
        Authorization: `bearer ${token}`
      }
      body: JSON.stringify(query)
  };
  try{
    const result = await fetch(
                    'https://api.github.com/graphql', body)
                      .then( x => x.json())
                      .catch(err => console.log({ err }));
    return result;
  } catch(err) {
    console.log({ err, from_try_catch: true })
  }
}

Async is hard

State is hard

Keeping track of all the changes in the DOM is hard

πŸ‘‰ IMMUTABILITY

Immutability

means things don’t change

var laptop = {
    ram: 16,
    cores: 8
}
var laptop2 = laptop;
laptop.ram = 2; // not immutable

console.log('laptop', laptop);
console.log('laptop2', laptop2);
console.log(laptop === laptop2) //true comparison is by reference

REACT

VDOM

It’s a pure Javascript, in-memory representation of the DOM

idea: batching changes to the DOM

JSX

// React.createElement(component, props, ...children)
const element = React.createElement('h1', null, 'Hello, world!')
// or in JSX
const element2 = <h1>Hello, world!</h1>;

Abstract Syntax Tree

Component

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
// same with javascript class
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

const element = <Welcome name="A Name" />;

// NOTE: 
// Always start component names with a capital letter.

Composing Components

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

Composition over Inheritance

Components lifecycle

  • Initialization
  • Mounting
  • Update
  • Unmounting

It is the state of the component

Redux

State is hard

Let’s make it immutable

One way data flow

Action => Reducer => Store => View (React)

  • View dispatches Actions
  • Reducer(state, action) => new state
  • the View subscribes to Store

Example

React hooks

import React, { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Replace Redux these days

React Hooks overview

  • Immutability for DOM: React
  • Immutability for app state: Redux/Hooks
  • what about the shape of data ?

Typescript

typed superset of JavaScript, transpiled to JavaScript

Typescript in 5 minutes

Imagine Javascript but with more Java

Type checking

// Javascript
function search(name, age) {
  ...
}
//Typescript
interface Person {
    name: string;
    age: number;
}
function search(name: string, age?: number): Person[] {
  ...
}

Typescript + react + hooks

interface Props {
  path: Routes
}

const TodoList: React.FC<Props> = ({ path }) => {
  const [appState, setAppState] = useAppState<AppState>()

  function toggleAllCheckbox(
      e: React.ChangeEvent<HTMLInputElement>
    ): void {
    setAppState({ 
        todoList: appState.todoList.map(
            (t: Todo): Todo => ({ ...t, completed: e.target.checked })
        ) 
    })
  }

  return (
      ...
  )
}

Build steps

transpile, optimise, bundle,…

webpack

CORS

Cross-Origin Resource Sharing

I’m sure the fullstack role was invented to avoid explaining CORS to backend developers.

Styling

CSS is worth learning.

:root {
  --color-text: #ffffff;
}
p {
  color: var(--color-text);
}
@media only screen and (max-width: 600px) {
  body {
    background-color: lightblue;
  }
}

Backstage

git clone https://github.com/spotify/backstage
cd backstage
yarn install
yarn start
yarn create-plugin

Backstage website

plugins

const ExampleFetchComponent: FC<{}> = () => {
  const { value, loading, error } = 
            useAsync(async (): Promise<User[]> => {
    const response = await fetch('https://randomuser.me/api/?results=20');
    const data = await response.json();
    return data.results;
  }, []);

  if (loading) {
    return <Progress />;
  } else if (error) {
    return <Alert severity="error">{error.message}</Alert>;
  }

  return <DenseTable users={value || []} />;
};

THANK YOU

and I'm sorry πŸ™
If you had to maintain my code
I hope you learned more by maintaining it
than me by writing it

contact

https://bisconti.cloud/

@julienBisconti

Slides made with Reveal.js and hugo-reveal