Writing a massive javascript app

Preview:

Citation preview

Hojoon ParkSr. Software Engineer

LinkedIn

www.linkedin.com/in/justindoit

Writing a massive javascript app

2

Over the last 3 years,

Single Page Application (BackboneJS, AngularJS)

Template System(Handlebars, Dust.LI)

Web Framework (SugarAPIFramework, Java Play Framework)

Unit Test (JasmineJS, SinonJS)

3

Agenda

Web Frameworks

Single Page Application

Case Study

Performance Tuning

Demo

4

Avoid spaghetti code in Front-end development

Too much copy/paste

Too much 3rd party recourses

Hard to debug the errors

5

Web Frameworks, recommend?

Play

Spring

Ruby on Rails

Yii

Node.JS

Angular

Backbone

jQuery

YUI

Require

Knockout

Bootstrap

6

Case Study: BackboneJS on PHP

Pure SPA

Metadata Manager

Data Manager

7

Case Study: BackboneJS on Java Play

Hybrid Web Application

sbt-concat, sass compiler

Model Hierarchy

8

Case Study: AngularJS on Java Play

Pure SPA

Grunt Builder

Less compiler by Grunt

9

What is SPA (Single Page Application)?

Routing

Angular RouteProvider / Backbone Router

MVC Framework

Models as the single source

Views observe model changes

Minimized DOM dependent-code

Asset Packaging

10

SPA (Single Page Application)

Cons. Pros.

SEO OptimizationNo longer server side loading

(Read data thru AJAX)

Higher Risk, Higher Reward

(Memory Leak)Client/Server code partitioning

Large File Size No Page Refresh

11

Consideration for SPA

Resources/Assets Management

JS/CSS compressor

Template compiler

Additional: LESS/SASS compiler

12

Why Asset Management is important?

Continuously growing JS/CSS resources

Duplicated JS files / version inconsistency

13

Sync vs. Async

Sync Async

Controller

Web framework

(Compiler plugin,

AssetManager)

Front-end Tools

(Require.JS, Inject.JS)

Pros. No delay on click Lazy Load

Cons. Longer loading time Loading on click

14

Anatomy: Directory(1)

By Resource Type

15

Anatomy: Directory(2)

By Feature

16

Asset Packaging: Play Framework

sbt-concat plugin

JavascriptMinifierCompiler

17

Asset Packaging: Yii Framework

AssetManager

18

Build asset packages without web framework

Resources/Assets Management

JS/CSS compressor

Template compiler

Additional: LESS/SASS compiler

Build System

ToolPackage

Manager

Bower

19

Metadata Manager

Sort the dependent modules

FlexListView

extends: ListView

ListView

DashableListView

extends: ListView

RecordListView

Extends: FlexListView

ListView

FlexListView

extends: ListView

DashableListView

extends: ListView

RecordListView

Extends: FlexListView

/**

* Sorts components in the order they should be declared as classes. This is required since a parent

* widget class must likewise be declared before a child that depends on it.

* @param {String} type Metadata type e.g. field, view. layout

* @param {Array} components List of modules

* @param {String} module Module name

* @return {Array} Sorted components

*/

_sortControllers : function(type, components, module) {

var updated = {}, nameMap = {}, entries = {},

updateWeights = function(entry){

var controller = entry.controller;

// Here we decrement the weight of any extended components. Note, that if sorting platform

// specific components (e.g. portal), and one "extends from" a base component, that parent

// will have already been declared since _sortControllers first gets called with base components

if (_.isObject(controller) && _.isString(controller.extendsFrom) &&

entries[controller.extendsFrom] && !updated[controller.extendsFrom])

{

// Negative weights as we want to load those first

entries[controller.extendsFrom].weight--;

updated[controller.extendsFrom] = true;

updateWeights(entries[controller.extendsFrom]);

}

};

// Start by creating a mapping from short name to final class name and precompiling all the controllers that are strings

_.each(components, function(entry, name) {

if (entry.controller) {

var controller = entry.controller,

className = (module || "") + app.utils.capitalizeHyphenated(name) + app.utils.capitalize(type);

nameMap[className] = name;

if (_.isString(controller)) {

20

Metadata Manager: cont.

Implementation

Great Design patterns are reusable, modular

expressions of what’s going on in your code.

They allow you to communicate to other

developers simply by the way you code,

in addition to being easily maintainable

themselves

21

Why Patterns?

22

Software design patterns

Factory

Singleton

MVC

Strongly OOP

Mixin

Event Driven

23

Object Oriented Programming

Code Reuse and recycling

Design Benefits

More features,

same amount of time

ListView

FlexListView

SubPanelListView

DashableListView

RecordListViewSelectionListView

Mixin pool

24

Decorator: Mixin (plugin)

RecordListView

extends: ListView

ErrorDecoration

Editable

MergeDuplicates

CreateView

Audit

FindDuplicates

Tooltip

ListView MergeDuplicateView

Timeago

ActivityStreamView

25

BackboneJS: Life-cycle of View Component

Initialize Bind events

Render

template

Unbind

eventsDispose

WatchersRegister

Trigger

Unregister

26

AngularJS: Life-cycle of scope

CreationWatcher

registration

Model

mutation

Mutation

observationScope

destruction

He who binds himself to a joy

Does the winged life destroy;

But he who kisses the joy as it flies

Lives in eternity's sun rise.

27

William Blake

28

Performance tuning

Remove duplicate listeners

Watcher optimization

Backbone: _events stack

Angular: $__watchers in $digest cycle

How many watchers will be incurred?

29

Don’t blame browser

30

Memory Management

Dispose safeInitialize Bind events

Render

Unbind eventsDispose

WatchersRegister

Trigger

Unregister

31

Memory Management: cont.

Catch while unit testing

32

Debugging

Firebug

Chrome developer tool

Network filtering

Recording

Profiler

Local Storage in resources tab

33

Unit Test

Jasmine, Karma, Sinon

Travis CI

Selenium WebDriver

34

Demo