voorhoede - front-end architecture

37
Jasper Moelker @jbmoelker

Upload: jasper-moelker

Post on 19-May-2015

3.691 views

Category:

Technology


4 download

DESCRIPTION

Presented during Javascript MVC Amsterdam meetup, 29 Jan 2014: http://www.meetup.com/JavaScript-MVC-Meetup-Amsterdam/events/156767102/ At De Voorhoede (http://voorhoede.nl) I'm responsible for setting up new front-end projects in such a way that it's easy for teams to work with. This presentation explains how we structure these projects. The presentation includes some tips on structuring larger AngularJS projects.

TRANSCRIPT

Page 1: Voorhoede - Front-end architecture

Jasper Moelker @jbmoelker

Page 2: Voorhoede - Front-end architecture

(ng) Architecturebest practices for setting up front-end / AngularJS projects

! warning: opinions ahead

Page 3: Voorhoede - Front-end architecture

de voorhoede

(NG) Architecture

Why care about front-end architecture? !

How to approach setting it up? !

modular structures !

Use tools that help you

image source: http://static.onemansblog.com/wp-content/uploads/2011/05/impossible-lego-03.jpg

Page 4: Voorhoede - Front-end architecture

Why care?aim: easy to use for (new) team members

Page 5: Voorhoede - Front-end architecture

de voorhoede

Why care?

• easy to understand

• easy to maintain

• easy to extend

• easy to re-use

• easy to deploy

• easy to distribute

Aim: easy to use for (New) team members

image source: http://www.registrycleaner.us.com

Page 6: Voorhoede - Front-end architecture

Ok, so how?approach: clear rules and standards

Page 7: Voorhoede - Front-end architecture

de voorhoede

Ok, so how?

• clear naming conventions

• clear directory structure

• clear dependency declarations

• clear code styles

• clear documentation (for what’s still unclear)

• clear tests & tasks for everything else

Approach: clear rules & standards

image source: http://www.carlosdinares.com

Page 8: Voorhoede - Front-end architecture

Think Modular-

Page 9: Voorhoede - Front-end architecture

de voorhoede

think modular

Atomic design by Brad Frost

source: http://bradfrostweb.com/blog/post/atomic-web-design/ see also: http://demo.pattern-lab.info/

Page 10: Voorhoede - Front-end architecture

de voorhoede

think modular

BEM blocks on smashing

source: http://coding.smashingmagazine.com/2012/04/16/a-new-front-end-methodology-bem/ see also: http://bem.info/

Page 11: Voorhoede - Front-end architecture

de voorhoede

think modular

source: https://github.com/angular/angular-seed/tree/master/app/js

used in ng tutorial

Page 12: Voorhoede - Front-end architecture

de voorhoede

think modular

source: http://briantford.com/blog/huuuuuge-angular-apps.html see also: https://github.com/angular/angularjs-batarang/

Brian ford on huuuuuge (5x) angular apps

used in batarang

Page 13: Voorhoede - Front-end architecture

de voorhoede

think modular

source: https://github.com/angular-app/angular-app/tree/master/client/src/app see also: https://github.com/ngbp/ngbp/tree/v0.3.1-release/src/app/home

read: http://cliffmeyers.com/blog/2013/4/21/code-organization-angularjs-javascript

ng app & ng boilerplate

Page 14: Voorhoede - Front-end architecture

de voorhoede

• Symfony 1: plugins

• Symfony 2: bundles (example on right)

• Web components

• Component.io

• Bower?

think modular

source: http://blog.solutionset.com/2012/09/14/easy-way-to-transform-a-twitter-oauth-library-into-a-symfony-2-bundle/

other frameworks / concepts

Page 15: Voorhoede - Front-end architecture

de voorhoede

think modular

Atomics

original image: http://bradfrostweb.com/blog/post/atomic-web-design/

Views

Components

Page 16: Voorhoede - Front-end architecture

de voorhoede

Think modular

App source structure

./source/ common/ <— atomics modules/ components/ <— re-usable components views/ <— unique views vendor/ <— third party modules app.js <— app core (config), include views bootstrap.js (+json) <— bootstrap app if supported index.html

Page 17: Voorhoede - Front-end architecture

de voorhoede

Atomics

typically no dependencies or only dependent on other atomics, examples:

• global css rules and variables (style guide)

• global assets like logo, fonts, icons

• high level (AngularJS) services: pub sub, rest service, transformers

• common (AngularJS) directives

• common (AngularJS) filters

elementary app rules & assets

source: http://www.heringinternational.com/de/beton/betoglass-4505.htm

Page 18: Voorhoede - Front-end architecture

de voorhoede

Atomics

structure atomics

common/ assets/ fonts/ images/ scss/ atomics/ _icons.scss mixins/ _mixin-name.scss directives/ view-box-directive.js filters/ services/ <— providers, services, factories rest-service.js

Page 19: Voorhoede - Front-end architecture

de voorhoede

Atomics in AngularJS

/** * @ngdoc directive * @name directives.viewBox.directive:viewBox * @description Supports using expression for SVG viewBox, by using `data-view-box` which sets * `viewBox` attribute. Code adapted from http://stackoverflow.com/a/14596319 * @example <doc:example> <doc:source> <svg data-view-box="{{ APP_VIEWPORT.viewBox }}"></svg> </doc:source> </doc:example> */ angular.module('directives.viewBox', []) // no dependencies .directive('viewBox', [ function () { 'use strict'; return { // no template, or other dependencies link: function (scope, element, attributes) { attributes.$observe('viewBox', function(value) { element.attr('viewBox', value); }); } }; } ]);

Page 20: Voorhoede - Front-end architecture

de voorhoede

Components

source: http://www.heringinternational.com/en/news&cmd=details&newsid=1179.htm

Re-usable encapsulated building blocks

• include structure (markup), presentation (style), behaviour (scripts), assets, docs, tests.

• important: declare dependencies

• in AngularJS use isolate scope to encapsulate component

Page 21: Voorhoede - Front-end architecture

de voorhoede

componentS

Structure component

modules/ components/ my-component/ media/ _my-component.scss / .less my-component-template.html my-component.js <— dependencies, config, ngdocs my-component-directive.js my-component-controller.js my-component-controller.test.js my-component-service.js my-component-service.test.js README.md

Page 22: Voorhoede - Front-end architecture

de voorhoede

Component in AngularJS

/** * @ngdoc overview * @name components.pager * @requires common/services.isPositiveInteger */ angular.module('components.pager', ['services.isPositiveInteger']); !/** * @ngdoc directive * @name components.pager.directive:pager */ angular.module('components.pager') .directive('pager', ['isPositiveInteger', function (isPositiveInteger) { 'use strict'; return { templateUrl: 'modules/components/pager/pager-template.html', replace: true, scope: { page: '=', itemsPerPage: '@', itemsTotal: '@' }, link: function (scope, element, attributes) {} } }]);

Page 23: Voorhoede - Front-end architecture

de voorhoede

Views

source: http://demavo.nl/literatuur/mondriaan.html

Unique compilation of components

in AngularJS

• uses ngView

• $routeProvider

• $stateProvider

Page 24: Voorhoede - Front-end architecture

de voorhoede

Views

Structure view

modules/ views/ my-view/ media/ _my-view.scss / .less my-view-view.html my-view.js <— dependencies, config, ngdocs my-view-directive.js my-view-controller.js my-view-controller.test.js README.md

Page 25: Voorhoede - Front-end architecture

de voorhoede

View in AngularJS

/** * @ngdoc overview * @name views.myView * @description My view module. * [detailed description of 'my view' module, which doesn't fit in this presentation] */ angular .module('views.myView', [ 'ngRoute', 'components.modal', 'components.pager', 'services.restService' ]) ! .config([ '$routeProvider', function ($routeProvider) { 'use strict'; $routeProvider .when('/view/my-view/:action', { templateUrl: 'modules/views/my-view/my-view-view.html', controller: 'MyViewController' }); } ]);

Page 26: Voorhoede - Front-end architecture

Code stylehelp keep your code clean & coherent

Page 27: Voorhoede - Front-end architecture

de voorhoede

Code quality tools

Configuration files in root

./ .csslintrc .jshintrc .jscs.json dubfind.cfg README.md

resources: csslint: http://csslint.net/ jshint: http://www.jshint.com/ jscs: https://github.com/mdevils/node-jscs dufind: https://github.com/sfrancisx/dupfind

Page 28: Voorhoede - Front-end architecture

Document your app-

Page 29: Voorhoede - Front-end architecture

de voorhoede

App documentation

…/ module.js index.ngdoc README.md !!!!!and use a style and / or code guide? for rules like use ‘ngMin proof syntax’.

README’s & NGDOCS

use ngdocs: https://github.com/m7r/grunt-ngdocs

Page 30: Voorhoede - Front-end architecture

Test your code-

Page 31: Voorhoede - Front-end architecture

de voorhoede

test your code

tests structure

./tests/ end-to-end/ helpers/ report/ csslint.xml jshint.xml karma.xml vendor/ <— eg. mocks end-to-end.js <— e2e and karma.js <— unit test config !test configs use bootstrap.json tests run locally and on Jenkins CI

Page 32: Voorhoede - Front-end architecture

Automatewrite tasks for repetitive actions

Page 33: Voorhoede - Front-end architecture

de voorhoede

Automate

Tasks structure

./Gruntfile.js —————>

./tasks/ grunt/ configuration/ task-name.js tasks/ task-name.js templates/ utilities/ phing/ java/ !we run tasks both locally and on server using Jenkins CI

module.exports = function (grunt) { 'use strict'; ! // Use `tasks/grunt/configuration/index.js`, // which reads package.json and loads all task configs: var config = require('./tasks/grunt/configuration')(grunt); grunt.config.init(config); ! // Load all npm installed grunt tasks. require(‘matchdep').filterDev('grunt-*') .forEach(grunt.loadNpmTasks); ! // load all project grunt tasks. grunt.task.loadTasks('tasks/grunt/tasks'); grunt.registerTask('default', [‘task-wizard']); };

source: http://gruntjs.com/img/grunt-logo.png

Page 34: Voorhoede - Front-end architecture

de voorhoede

Grunt Task wizard

source: https://gist.github.com/jbmoelker/8384456#file-task-wizard-js

1) Select task category

2) Select project task

3) Enter arguments

Result: New component created * new directory created * html, js, scss, readme files created * registers module in index files

Page 35: Voorhoede - Front-end architecture

de voorhoede

Automate

Develop task Deploy / distribute task// tasks/grunt/tasks/develop.js (non-ng project) !module.exports = function (grunt) { 'use strict'; grunt.registerTask( 'develop', 'Setup web dir for development and watch source', function (mode) { var tasks = [ 'compile-index:development', 'compile-html:development', 'copy:development', 'sass:development', 'concat:development' ]; if(mode !== 'no-watch'){ tasks.push('watch'); } grunt.task.run(tasks); } ); };

// tasks/grunt/tasks/deploy.js (ng-project) !module.exports = function (grunt) { 'use strict'; grunt.registerTask( 'deploy', 'Concatenates and minifies source files', function () { grunt.task.run([ 'clean:distribution', 'copy', 'ngtemplates', 'concat', 'uglify', 'clean:templates' ]); } ); };

Page 36: Voorhoede - Front-end architecture

de voorhoede

Think modular

App structure

./ distribution/ <— auto generated via ‘grunt deploy’ docs/ <— auto generated via ‘grunt docs’ source/ common/ <— atomics modules/ components/ <— re-usable components views/ <— unique views vendor/ app.js bootstrap.js index.html tasks/ <— task config, templates, utilities tests/ <— test config, e2e, helpers, reports web/ <— auto generated via ‘grunt develop’

Page 37: Voorhoede - Front-end architecture