Skip to content
This repository has been archived by the owner on Aug 26, 2021. It is now read-only.

UI Application

igorstoyanov edited this page Aug 26, 2016 · 1 revision

Used technologies

The project is built on Javascript and uses modern tools for development, application architecture and purely UI and front end components.

Build and Package manager

A javascript project typically consists of static .html, .js and .css files. And if the size of the project is small it is enough. However as the project grows, it becomes hard to maintain, so tools for building and developing have been introduced. Such tools can allow you to modularize your app, check for script errors, minimize the code and make it easier to test your code.

node.js

nodejs.org Whatever build or package manager tool we choose, all of them are based on the node.js runtime as it is cross platform, small and lightweight and it runs Javascript application. We will depend on node.js only for build. It is optional for developers to install node.js on their environments from https://nodejs.org/, recommended version v0.12.2. It is not required as the default maven build will download and use node.js if needed, see #frontend-maven-plugin

gulp

gulp Gulp is a task based build tool. It can do things like running tests for your code, verify it for correctness and stylings using a set of rules (jshint/jslint), minify it, etc. It can modify the source files any possible way with various plugins and it's plugin base is very large. Writing a custom plugin in javascript is also easy, but not needed at this point.

Alternatives:

grunt

The main alternative to gulp is grunt. Gulp was chosen because of it's simpler and easier to extend with JS code tasks, rather than grunt's JSON configurations.

npm

npmjs Npm stands for Node packaging manager. It has a public repository and manages public and private dependencies. It was introduced for node libraries, but now almost every open source client side javascript project use it. In our project we use it for node.js (build time) dependencies.

bower

Bower is similar to npm, but designed for client side components only. In our project we use it for client side (runtime) dependencies

maven

Due to the maven nature of the other modules. frontend-maven-plugin https://github.com/eirslett/frontend-maven-plugin This plugin is built for similar configuration as ours - JS project using gulp or grunt as a maven module. It is useful as during the "generate-resources" phase it executes tasks as Downloading and setting up node.js locally in the JS module directory, if none is present. Ignored in ".gitignore" Running npm install to download all node modules defined in "package.json" Running gulp build that builds all .html, .js, .css, from src/ to dest/

Tests

In typical front-end setup there are 2 sets of tests - unit and integration.

Unit tests

Unit test verifies small pieces of code. They test a given part of the app, while mocking and stubbing the interaction with the other parts. Unit tests must be very fast, so fast that they can be added as part of the development cycle where the build tool listens for changes of the source files, compiles them, and tests them in the same time while refreshes the browser. They must NOT modify DOM or any other visual components.

Integration tests

Integration tests on the other hand test how different parts of the system work together. They can validate end-to-end functional requirement, by simulating user interaction, and interaction with the server. These tests can load and render the whole application and start changing UI element values to validate correctness. Using this setup, we can isolate specific parts of the application like talking with the backend.

Jasmine

jasmine.github.io For both unit and integration tests we will use Jasmine as testing framework, very popular in the community and used in many VMware products.

Karma + PhantomJS

http://karma-runner.github.io/0.12/index.html http://phantomjs.org/ For executing the unit and integration tests we will use the Karma runner. It gives us the benefits of specifying which browsers to run the tests on, generates reports for different build systems and tools. In our main maven build, we will invoke karma on the headless PhantomJS browser and will generate junit, surefire report that Jenkins understands. However developers can chose their browser of preference and can use it to debug tests.

Alternatives

For the unit tests only we could have chosen to run them with native node, since they don't depend on browser. However for simplicity and keeping the same setup for both unit and integration tests, we will use the browser environment (phantomjs) For functional testing Selenium is used and Jasmine and PhantomJS based integration tests are used to give the developer writing the tests all needed for validation.

Runtime

Architecture

When building a bigger JS app, it is crucial to define an architecture or design pattern to organize the pieces of the app, the user interaction and data flows.

Flux

https://facebook.github.io/flux/ Flux is an application architecture designed by Facebook for their UI projects. It is also a library, that helps build on top of this architecture, but in this section we focus only on the architecture.

It promotes the uni-directional data flow, where actions are invoked by the views, when the user is interacting with it, or by a server call (callback / message) and propagated through a dispatcher through all stores that are interested in this action. It commands all of the application state to be in a data model. This has the added benefit of being able to "persist" the last user application state, or to implement a history mechanism. It also simplifies the application routing (url change, browser back and forward).

It is also complimentary to React's components, but due to license issues with React, at this point we will not use it. However our components will be built in a way that if necessary, switching to React will be easy.

Reflux

https://github.com/spoike/refluxjs Reflux is the open source library that aids us in embracing the Flux architecture. It was chosen because of it simplicity over Facebook's Flux (the library) and the same license issues.

Alternatives

Any other MV* architecture and JS framework out there. See here http://todomvc.com/ As far as a the actual frameworks, the main competitor to React/Flux we considered was AngularJs. Both of them are used a lot in the community. However there were some unknowns in the new 2.0 version of angular, like what to expect from the components, how to build against it, should you build for 1.x with no simple migration path to 2.0. One drawback we considered from angular's breaking changes is that it may be better to rely on many small components that do one thing and one thing only, rather than a huge framework that aids MVC, dependency injection, templating, binding, routing, animation etc.

Modules

Every bigger application must be modular, meaning that it is composed of a set of highly decoupled, distinct pieces of functionality stored in modules. As Javascript does not yet support modules natively there several ways to achieve modularity with the tools available today. Generally there are two formats that we can chose from AMD and CommonJS. While the first is more native fit for the browser, the second is widely used in the Node.js world, and there are several efforts into making it available in the browser, with tools like Browserify and WebPack. On the other hand there are also ES6 modules, which have already defined syntax, but are lacking a module loader.

For the minimum, as we use babel to write ES6 today, it also supports the new module syntax, therefor we will pick the ES6 modules syntax. Underneath those modules will be translated into AMD or CommonJS (supports also SystemJS). However with this approach developers don't need to worry which format we use underneath to build and load the application. We have looked at different solutions to load modules and bundle our application. The most notable ones being Webpack and Browserify. Both have their strengths, however at the moment of writing we did not see need for picking either of them so we stick with regular AMD modules, with the help of requirejs to load.

Libraries

Bootstrap

http://getbootstrap.com/ Well known library for faster and easier UI development. Supports many common components and responsive layouts.

Alternatives

No alternatives were considered.

Vue.js

vuejs.org

Vue.js is a library for building interactive web interfaces. The goal of Vue.js is to provide the benefits of reactive data binding and composable view components with an API that is as simple as possible.

Vue.js itself is not a full-blown framework - it is focused on the view layer only. It is therefore very easy to pick up and to integrate with other libraries or existing projects. On the other hand, when used in combination with proper tooling and supporting libraries, Vue.js is also perfectly capable of powering sophisticated Single-Page Applications.

Alternatives

React.js handles templating + dynamic re-rendering (using virtual DOM) perfectly. The issue from above was the reason not to use it. Ractive.js - a good alternative to React, but not so mature for creating components and handling their life-cycle.

jQuery

https://jquery.com/ Nothing much to be said, like a standard to client side JS development.

Alternatives

Pure JS

crossroads

https://millermedeiros.github.io/crossroads.js/ Routing library that handles browser location changes. Simple and yet does just enough.

Alternatives

Some MV* libraries have such built in, but in our case no alternatives were considered.

validation

https://github.com/chriso/validator.js There are many validation libraries that aids us when we need form validation. The ones that interact directly with the visual components, are very opinionated, work with a concrete set of components/UI libraries, have a specific requirement against backend/asynchronous validation and error messages. In the case where we have only bootstrap and custom inputs, such library may seem like a overhead. However we still need a way to validate if a string is an email, ip address or a phone number. For this we can use the light-weigh validator.js that has a nice set of boolean validation functions. This way we can use it to validate our inputs and we will handle showing the correct error messages ourselves. Bootstrap already has styles and help text for validation errors, so it is our job to get the input from the bootstrap component, call the validation functions agains the string values, collect any errors and build error messages for them, and apply back the errors with styles using the bootstrap components.

Project structure

Because of the Java nature of the whole project, the UI part of the project is split into 2 parts. JS only The JS only project follows the convention of other javascript projects and has a structure similar to:

root/
-- src/
---- index.html
---- js/ 
---- styles/
---- images/
-- dist/
-- node_modules/
-- package.json
-- pom.xml 

This part itself may be built with JS build tool (see Build and Package manager) but in order to be integrated with the whole project and it's maven build, there is an additional pom.xml that specifies which static resources maven to wrap in a jar, to be used by other modules. Also includes the #frontend-maven-plugin .

Java

The Java projects is another maven module that depends on the JS maven module and it's static resources. It integrates with the Java Xenon services by providing the static resources to the Xenon handlers to serve them.