Parallel Universe

Java Developer’s Guide to Front-End Development

Kito Mann (@kito99), Virtua, Inc.

Kito D. Mann (@kito99)

  • Principal Consultant at Virtua (http://virtua.tech)

  • Training, consulting, architecture, mentoring

    • Java microservices, Jakarta EE, Web Components, Angular

  • Official US PrimeTek partner

    • PrimeNG, PrimeVue, PrimeFaces, PrimeReact

  • Author, JavaServer Faces in Action

Kito D. Mann (@kito99)

  • Co-host, Stackd Podcast (http://stackdpodcast.com)

  • Java Champion

  • Member of Jakarta EE Ambassadors Leadership Council

  • Java Community Process (JCP) Member

    • JSF, MVC, JSF Portlet Bridge, Portlets, CDI, JSP

  • Google Developer Expert in Web Technologies

  • Internationally recognized speaker

    • JavaOne, JavaZone, Devoxx, Devnexus, NFJS, etc.

Topics

  • Vocabulary

  • JavaScript

  • Tooling

  • Web Frameworks

  • Web Platform

Become a Full Stack Developer!

full stack developer

Vocabulary

monkeypatch

A monkey patch is a way for a program to extend or modify supporting system software locally (affecting only the running instance of the program). In Ruby, Python, and many other dynamic programming languages, the term monkey patch only refers to dynamic modifications of a class or module at runtime, motivated by the intent to patch existing third-party code as a workaround to a bug or feature which does not act as desired.

 — Wikipedia

shim

In computer programming, a shim is a small library that transparently intercepts API calls and changes the arguments passed, handles the operation itself, or redirects the operation elsewhere. Shims can be used to support an old API in a newer environment, or a new API in an older environment. Shims can also be used for running programs on different software platforms than they were developed for.

 — Wikipedia

polyfill

In web development, a polyfill (or polyfiller) is downloadable code which provides facilities that are not built into a web browser. It implements technology that a developer expects the browser to provide natively, providing a more uniform API landscape. For example, many features of HTML5 are not supported by versions of Internet Explorer older than version 8 or 9, but can be used by web pages if those pages install a polyfill. Web shims and HTML5 Shivs are related concepts.

 — Wikipedia

middleware

Middleware functions are functions that have access to the request object (req), the response object (res), and the next function in the application’s request-response cycle. The next function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware. [Similar to Servlet Filters.]

 — Express site

transpiler

A source-to-source compiler, transcompiler or transpiler is a type of compiler that takes the source code of a program written in one programming language as its input and produces the equivalent source code in another programming language. A source-to-source compiler translates between programming languages that operate at approximately the same level of abstraction, while a traditional compiler translates from a higher level programming language to a lower level programming language.

 — Wikipedia

design system

A Design System is a set of interconnected patterns and shared practices coherently organized. Design Systems aid in digital product design and development of products such as apps or websites. They may contain, but are not limited to, pattern libraries, design languages, style guides, coded components, brand languages, and documentation.

It serves as a reference or source of truth that helps the different teams involved (such as designers, developers, copywriters and project managers) to design and build digital products.

 — Wikipedia

tree shaking

Tree shaking is a term commonly used within a JavaScript context to describe the removal of unused code.

It relies on the import and export statements in recent versions of JavaScript in order to detect if code modules are exported and imported for use between JavaScript files.

JavaScript

History

  • JavaScript really was written in 10 days in 1995 by Brendan Eich

  • ECMAScript 2 released in 1998

  • ECMAScript 3 released in 1999

  • ECMAScript 5 released in 2009 (ES5)

History

JavaScript Engines

  • JavaScript Engine ≈ Java Execution Environment

  • Java implementations

    • Rhino (Mozilla)

      • Ships with JDK 6

    • Nashorn (Oracle)

      • Ships with JDK 7+

      • Deprecated in JDK 11

JavaScript Engines

  • Java implementations

    • GraalVM (Oracle)

      • Supports ECMAScript 2021+ as well as Java, Python, Ruby, R, C/C++

JavaScript Engines

JavaScript Engines

  • Node.js = ECMAScript Engine + Standard Libraries + Package Manager (NPM)

Support for new JavaScript Features

  • Most engines include a subset of new features

Modern JavaScript Features

  • Class syntax

  • let and const

  • Arrow functions

  • Template literals

  • Spread operator

  • Async functions and promises

  • Optional chaining

  • Nullish coalescing operator (??)

Modern JavaScript Features

  • Modules

  • Generators and Iterators

  • Maps and Sets

  • Proxying and Reflection

  • Internationalization / Localization

  • Atomics

  • Shared memory

  • Weak references

Transpilers

Transpilers: New JavaScript Features

  • Traceur

  • Babel

  • TypeScript

Transpilers: Type Saftey

  • Flow

  • TypeScript

Transpilers: TypeScript

interface CanGreet<T> {
    greeting: T;
    greet();
}

class Greeter<T> implements CanGreet<T> {
    greeting: T;
    constructor(message: T) {
        this.greeting = message;
    }
    greet() {
        return this.greeting;
    }
}

class HappyGreeter<T> extends Greeter<T> {
    constructor(message: T) {
        super(message);
    }
    happyGreet() {
        return "Hello! Happy " + super.greet();
    }
}

type NumberOrString = string | number;

let greeter = new Greeter<string>("Hello, world");
let happyGreeter = new HappyGreeter<NumberOrString>(55);

console.log(greeter.greet());
console.log(happyGreeter.greet());
console.log(happyGreeter.happyGreet());

Transpilers: TypeScript

Hello, world
55
Hello! Happy 55

Transpilers: Other Languages

WebAssembly (wasm)

  • Binary iunstruction format for a stack-based virtual machine

  • Similar to Java bytecode but more low-level

  • Supported by all major browsers, Node.Js, and GraalVM (early stages)

  • Supports C/C++, Rust, C#, F#, Go, Kotlin, Swift, Java (TeaVM)

Tools

Package Managers

  • Package Manager ≈ Dependency Manager

  • Popular Package Managers

    • Bower (deprecated)

    • Node Package Manager (NPM)

    • Yarn

npm

npm package.json

{
  "name": "ExampleApp",
  "version": "1.0.0",
  "license": "COMMERCIAL",
  "scripts": {
    "ng": "ng",
    "start": "ng serve --host localhost --port 4201",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "doc": "compodoc -p tsconfig.json"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^4.4.6",
    "@angular/common": "^4.4.6",
    "@angular/compiler": "^4.4.6",
    "@angular/core": "^4.4.6",
    "@angular/forms": "^4.4.6",
    "@angular/http": "^4.4.6",
    "@angular/platform-browser": "^4.4.6",
    "@angular/platform-browser-dynamic": "^4.4.6",
    "@angular/router": "^4.4.6",
    "@types/html2canvas": "^0.5.35",
    "@types/jspdf": "^1.1.31",
    "chart.js": "2.6.0",
    "core-js": "^2.5.3",
    "crypto-js": "^3.1.9-1",
    "fullcalendar": "^3.8.0",
    "html2canvas": "^1.0.0-alpha.9",
    "jquery": "^3.2.1",
    "jspdf": "^1.3.5",
    "moment": "^2.20.1",
    "nanoscroller": "0.8.7",
    "primeng": "^4.3.0",
    "quill": "^1.3.4",
    "rxjs": "^5.5.6",
    "zone.js": "^0.8.20"
  },
  "devDependencies": {
    "@angular/cli": "1.2.4",
    "@angular/compiler-cli": "^4.4.6",
    "@compodoc/compodoc": "^1.0.5",
    "@types/googlemaps": "3.26.17",
    "@types/jasmine": "2.5.53",
    "@types/node": "^8.5.9",
    "codelyzer": "~3.1.2",
    "jasmine-core": "~2.6.4",
    "jasmine-spec-reporter": "~4.1.1",
    "karma": "^1.7.1",
    "karma-chrome-launcher": "~2.2.0",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "^1.3.3",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.2",
    "protractor-screenshoter-plugin": "^0.3.2",
    "ts-node": "~3.3.0",
    "tslint": "~5.5.0",
    "typescript": "~2.4.2"
  }
}

CSS Preprocessors

  • "Transpilers" for CSS

  • Add language features

    • Variables, imports, mixins, inheritance, operators, new functions, etc.

  • SASS

  • Less

  • Stylus

Saas Example

@import '../sass/variables-app-global';

$primaryColor: $appPrimaryBlue;
$primaryTextColor: $appBrightTextColor;
$toggleButtonBgColor: $appDefaultBackgroundColor;

@import '../sass/theme/_theme-app';

body, .app-body, .ui-widget {
  font-family: $appBodyFontFamily;
  font-size: $appBodyFontSize;
  line-height: $appLineHeight;
  color: $appPrimaryTextColor;
}

.app-base-padding {
  padding: .5 * $appBaseUnit;
}

.app-button {
  @extend .app-base-padding
}

.ui-dialog {
  @include overlay-shadow();
  border: $overlayBorder;
  font-size: 1.25 * $appBaseUnit;

  .ui-dialog-titlebar {
    padding: $headerPadding;
    padding-top: 1em;
    padding-bottom: 1em;

    .ui-dialog-title {
      margin: 0;
      float: none;
      vertical-align: middle;
      @extend .app-display;
    }

    .ui-dialog-titlebar-icon {
      color: $headerIconColor;
      border: 0 none;
      @include transition(color $transitionDuration);
      padding: 0;
      margin-left: .35em;
      font-size: $fontSize + 2;

      &:hover {
        color: darken($headerIconHoverColor, 10%);
      }
    }
  }
}

CSS Utility Libraries

  • Provide CSS classes that can be mixed and matched

TailwindCSS Example

<div class="max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden md:max-w-2xl">
  <div class="md:flex">
    <div class="md:flex-shrink-0">
      <img class="h-48 w-full object-cover md:w-48" src="/img/store.jpg" alt="Man looking at item at a store">
    </div>
    <div class="p-8">
      <div class="uppercase tracking-wide text-sm text-indigo-500 font-semibold">Case study</div>
      <a href="#" class="block mt-1 text-lg leading-tight font-medium text-black hover:underline">Finding customers for your new business</a>
      <p class="mt-2 text-gray-500">Getting a new business off the ground is a lot of hard work. Here are five ideas you can use to find your first customers.</p>
    </div>
  </div>
</div>

Build Tools and Bundlers

  • What is there to build?

Build Tools and Bundlers

build process

Build Tools and Bundlers

  • Grunt

  • Gulp

  • Browserify

  • Brunch

  • Webpack

  • Rollup

Gulpfile.js

'use strict';

var gulp = require('gulp');
var del = require('del');
var browserSync = require('browser-sync');
var reload = browserSync.reload;
var merge = require('merge-stream');
var path = require('path');
var glob = require('glob-all');
var gulpIf = require('gulp-if');
var gulpIgnore = require('gulp-ignore');
var runSequence = require('run-sequence');
var sourcemaps = require('gulp-sourcemaps');
var ts = require('gulp-typescript');
var tsProject = ts.createProject('tsconfig.json');

var src = '.';
var DIST = '.';
var dist = function(subpath) {
	return !subpath ? DIST : path.join(DIST, subpath);
};

gulp.task('typescript', function() {
	var tsResult = gulp.src()
		.pipe(sourcemaps.init())
		.pipe(ts(tsProject, undefined, ts.reporter.longReporter()));
	return merge([
		tsResult.dts.pipe(gulpIgnore.exclude(src + '/test/**/*')).pipe(gulp.dest(dist())),
		tsResult.js.pipe(sourcemaps.write('.')).pipe(gulp.dest(src))
	]);
});

gulp.task('clean', function() {
	var filesToDelete = ['.tmp', src + '/{test,demo}/**/*.{js,map,d.ts}',
		src + '/*.{js,map,d.ts}', '!' + src + '/{gulpfile,wct.conf}.js'];
	if (dist() != '.') {
		filesToDelete.push(dist());
	}
	return del(filesToDelete);
});

// Watch files for changes & reload
gulp.task('serve', ['typescript'], function() {
	browserSync({
		port: 5000,
		notify: false,
		logConnections: true,
		server: {
			baseDir: ['.tmp', '.'],
			routes: {
				'/': 'bower_components/'
			},
			index: 'index.html',
			directory: true
		}
	});
	gulp.watch([
			'{' + src + ',demo,test}/**/*.{ts,html}',
			'!{' + src + ',demo,test}/**/*.d.ts'
		],
		['typescript', reload]);
	gulp.watch([src + '/styles/**/*.css'], reload);
});

// Build production files, the default task
gulp.task('default', ['clean'], function(callback) {
	runSequence(['typescript'], callback);
});

Webpack

  • Module bundler, but anything can be a module

  • More of a Maven approach

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
const path = require('path');

const config = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin(),
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

module.exports = config;

Other Tools

yeoman logo

JavaScript Web Frameworks

What about jQuery?

jquery logo

What is a JavaScript Web Framework?

  • Apps can be entirely separated from the back-end

    • Communicate with server via REST

  • Support single-page apps

    • Support routing

  • Custom programming model

    • Component models, support for "model" objects, other feaures like services and pipes

    • Provides a way to structure the app

What is a JavaScript Web Framework?

  • Facilities for common tasks

    • Views

    • Communicaion with back-end (Ajax, parsing JSON)

    • State management

  • Run-time or compile-time optimizations

    • Angular’s AOT compiler

    • React’s Virtual DOM

What is a JavaScript Web Framework?

  • Command Line Interface (CLI)

  • Multiple deployment targets

    • Web, Desktop (Electron), Mobile

What is a JavaScript Web Framework?

  • Two-way data binding

  • One-way data binding

    • Properties flow down to children; changes sent via events

Older JavaScript Web Frameworks

  • Backbone / Marionnete (dormant)

  • Ember (active)

  • AngularJS (deprecated)

  • Polymer (deprecated)

  • Bootstrap (not an app framework)

Newer JavaScript Web Frameworks

  • React

  • Angular

  • Vue

  • Svelte

  • LitElement/LitHtml (not really a framework)

  • Many more…​

React

  • Specifies only view layer

  • Components are functions

  • JSX ≈ JSP

  • Usually uses Flux or Redux handle global state and actions

React JSX Example

class MarkdownEditor extends React.Component {
  constructor(props) {
    super(props);
    this.md = new Remarkable();
    this.handleChange = this.handleChange.bind(this);
    this.state = { value: 'Hello, **world**!' };
  }

  handleChange(e) {
    this.setState({ value: e.target.value });
  }

  getRawMarkup() {
    return { __html: this.md.render(this.state.value) };
  }

  render() {
    return (
      <div className="MarkdownEditor">
        <h3>Input</h3>
        <label htmlFor="markdown-content">
          Enter some markdown
        </label>
        <textarea
          id="markdown-content"
          onChange={this.handleChange}
          defaultValue={this.state.value}
        />
        <h3>Output</h3>
        <div
          className="content"
          dangerouslySetInnerHTML={this.getRawMarkup()}
        />
      </div>
    );
  }
}

ReactDOM.render(
  <MarkdownEditor />,
  document.getElementById('markdown-example')
);

Angular

angular architecture

Angular Example

hello-world-bindings.ts

import { Component } from '@angular/core';

@Component ({
  selector: 'hello-world-bindings',
  templateUrl: './hello-world-bindings.component.html'
})
export class HelloWorldBindingsComponent {
  fontColor = 'blue';
  sayHelloId = 1;
  canClick = false;
  message = 'Hello, World';

  sayMessage() {
    alert(this.message);
  }

}

Angular Example

hello-world-bindings.html

<button
  [disabled]="canClick"
  (click)="sayMessage()">
  Trigger alert message
</button>
<p
  [id]="sayHelloId"
  [style.color]="fontColor">
  You can set my color in the component!
</p>
<p>My color is {{ fontColor }}</p>

JavaScript Web Frameworks

Component-oriented architecture is now standard.

Managing State

  • Command Query Responsibility Segregation (CQRS) pattern

  • Implemented by Flux, Redux, Ngrx, Ngxs, etc.

  • Used to handle state in larger apps

Redux

redux

The Web Platform Has Matured

Do we still need web frameworks?

Remember the Browser Wars?

HTML(5)

  • Web Hypertext Application Technology Working Group (WHATWG) Living Standard

  • Signed agreement in 2019 to work with W3C to maintain it

HTML(5)

  • Web Sockets

  • WebRTC

  • Web Storage

HTML(5)

  • IndexedDB

  • Canvas

  • WebGL

  • And more (Bluetooth, USB, etc.)

Web Components

  • Custom Elements

  • Shadow DOM

  • HTML Template

CSS3

  • Technnically, there is no such thing as CSS3

  • Collection of "Modules" released after CSS2.1

  • Different snapshots published periodically by W3C

CSS3

  • Rounded corners, shadows, gradients, animations

  • Custom properties (variables)

  • Better layout

    • Flexible Box Layout (Flexbox)

    • Columns Layout

    • Grid Layout

Progressive Web Apps (PWAs)

Baseline PWA Technologies

  • Responsive Design

  • HTTPS

  • Web Manifest

  • Service Worker

Additional PWA Technologies

  • History API

  • Payment Request API

  • Credential Management API

Additional PWA Technologies

  • Notifications API

  • Network Information API

  • HTTP/2

Do We Still Need Web Frameworks?

  • It depends.

  • At the very least, you will probably have dependencies and some tools.

  • So you’ll need a package manager…​

  • and a build or bundler tool…​

Questions?