SlideShare a Scribd company logo
EnterJS 2015 - Continuous Integration for Frontend Code
Continuous Integration for
Frontend Code
Presentation
Marcel Birkner - Software Consultant
Bastian Krol - Software Consultant
Marcel Birkner Bastian Krol
@marcelbirkner
github.com/marcelbirkner
marcel.birkner@codecentric.de



@bastiankrol
github.com/basti1302
bastian.krol@codecentric.de



3/62
About codecentric
Big Data Nerds Agile Ninjas Continuous Delivery Gurus
Java Specialists Performance Geeks Hipster Developers
4/62
EnterJS 2015 - Continuous Integration for Frontend Code
> 280 employees
And we are looking for more!
6/62
Continuous Integration for Frontend Code
Why should you use it?
What is the benefit?
JavaScript & CSS have grown up
8/62
Frontend Code is Mission Critical!
Broken JavaScript → broken app
Broken CSS → broken layout and/or broken app
It impacts the perceived performance drastically
Even more so on mobile
·
·
·
·
9/62
And Still ...
We often build superior CI/CD pipelines for our backends
But frontend code is often neglected
For our users, it's always the whole package
·
·
·
10/62
We can do better!
11/62
What we will cover
This is frontend only
Ideal: backend & frontend in one CD pipeline
Asset Optimization
Testing
The Delivery Pipeline
Local Development (Docker)
·
·
·
·
12/62
Asset Optimization
Common Problems
Bad Code Quality
Misconfigured Caching
Lots of assets (JS, CSS, images) ⇒Lots of HTTP requests ⇒Slow
·
·
·
14/62
Tools
Grunt — Task Runner
ESLint — Static Code Analysis
grunt-contrib-concat — Concatenation
grunt-contrib-uglify/UglifyJS — Minification
SASS — CSS preprocessor
compass — images → base 64 data URIs
grunt-version-assets — Versioned File Names
·
·
·
·
·
·
·
15/62
Alternatives
Grunt: Gulp | Broccoli | npm | make | ...
ESLint: JSHint | JSLint
SASS: Less | Stylus
Module System + Bundler: Webpack | Browserify
·
·
·
·
16/62
# of HTTP Requests — Concatenation
concat:{
options:{
separator:'n;'
},
app:{
src:[
'<%=jsSrcDir%>/js/**/*.js',
],
dest:'<%=jsTargetDir%>/app.js'
}
}
GRUNT
17/62
Download Size — Minification
uglify:{
app:{
files:{
'<%=jsTargetDir%>/app.min.js':['<%=jsTargetDir%>/app.js'],
}
}
}
GRUNT
18/62
# of HTTP Requests — Embed Images in CSS
.img-foo{
background-image:inline-image("foo.png");
}
SCSS
sass:{
app:{
options:{compass:true,},
files:{'<%=cssTargetDir%>/master.css':'<%=cssSrcDir%>/master.scss',}
}
},
GRUNT
.img-foo{
background-image:
url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAA...');
}
CSS
19/62
Use the Browser Cache
Versioned File Names
time stamp: app.min.20150619-0913.js
hash: app.min.2412fbca2a07a.js
content changes ⇒file name changes
file can be kept in browser cache forever
·
·
·
·
20/62
Versioned File Names (cont'd)
versioning:{
options:{
grepFiles:['<%=appTargetDir%>/**/*.html',]
},
css:{
src:[
'<%=cssTargetDir%>/app.min.css',
]
},
js:{
src:[
'<%=jsTargetDir%>/app.min.js',
'<%=jsTargetDir%>/vendor.min.js',
]
},
},
GRUNT
21/62
Versioned File Names — Before
<!DOCTYPEhtml>
<htmllang="en">
<head>
...
<linkhref="css/app.min.css"rel="stylesheet">
...
</head>
<body>
...
<scriptsrc="js/vendor.min.js"type="text/javascript"></script>
<scriptsrc="js/app.min.js"type="text/javascript"></script>
</body>
</html>
HTML
22/62
Versioned File Names — After
<!DOCTYPEhtml>
<htmllang="en">
<head>
...
<linkhref="css/app.min.b678e30139fc04.css"rel="stylesheet">
...
</head>
<body>
...
<scriptsrc="js/vendor.min.dda09628f6e1da.js"type="text/javascript"></script>
<scriptsrc="js/app.min.8e46534a4f66158.js"type="text/javascript"></script>
</body>
</html>
HTML
23/62
Development: Turnaround Time Is Important
Production Mode vs. Development Mode
grunt watch
Live Reload
·
·
·
24/62
Production Mode versus Development Mode
Production Development
JS concatenated, minified source files, not minified
CSS compiled (SASS), concatenated, minified only compiled (SASS)
Images Embedded into CSS Embedded into CSS (by Sass/Compass)
HTML references optimized assets references source assets
25/62
Development Mode - Replace References
<!DOCTYPEhtml>
<htmllang="en">
<head>
...
<!--build:csscss/app.min.css-->
<linkrel="stylesheet"href="css/master.css">
<linkrel="stylesheet"href="css/dashboard.css">
...
<!--/build-->
</head>
<body>
<!--build:jsjs/app.min.js-->
<scriptsrc="js/app.js"type="text/javascript"></script>
<scriptsrc="js/routes.js"type="text/javascript"></script>
...
<!--/build-->
</body>
</html>
HTML
26/62
Development Mode - Replace References (cont'd)
Alternative: grunt-usemin to concat, minify & replace in one step
processhtml:{
dist:{
files:{
'<%=appTargetDir%>/index.html':['<%=appSrcDir%>/index.html']
}
}
},
GRUNT
27/62
grunt watch
watch:{
files:[
'<%=jsSrcDir%>/**/*.js',
'<%=cssSrcDir%>/**/*.scss',
'<%=htmlSrcDir%>/**/*.html',
],
tasks:[
'dev-build',
],
options:{
livereload:true,
}
}
GRUNT
28/62
dev-build
grunt.registerTask('dev-build',[
'copy:cssThirdParty',
'sass',
]);
GRUNT
29/62
Live Reload
See changes instantly
Never press F5 again
Let's see this in action!
·
·
·
30/62
Measure it
Google PageSpeed
Yslow
Fiddler
·
·
·
31/62
Comparison
Unoptimized Version
Optimized Version
32/62
Testing
Front end unit tests
34/62
Karma
Open Source Test Runner
Created by the AngularJS team
Write tests in Jasmine, Mocha, QUnit
CI support (Jenkins, Travis)
Based on Node.js and Socket.io
Run in Headless Modus with PhantomJS
Supported Browsers: Firefox, Chrome, Safari, IE (Desktop and Mobile)
·
·
·
·
·
·
·
35/62
Karma and Mocha (JS Test Framework)
Running Unit Tests with Karma
varexpect=chai.expect;
beforeEach(module('project-staffing'));
describe('UpperCaseTest',function(){
it('shouldconvertfirstcharactortoUpperCase',inject(function(uppercaseFilter){
expect(uppercaseFilter('a')).to.equal('A');
expect(uppercaseFilter('helloworld')).to.equal('HelloWorld');
}));
});
JAVASCRIPT
npminstall-gkarma-cli
karmastartkarma.conf.js
//or
gruntkarma
BASH
36/62
Sinon (Mocking Framework)
varActivityService;
var$http;
beforeEach(inject(function(_ActivityService_,_$http_){
ActivityService=_ActivityService_;
$http=_$http_;
sinon.stub($http,'post',function(){});
}));
describe('ActivityService',function(){
it('shouldhavesendhttpPOSTtobackendaftersavingoneactivity',
inject(function(ActivityService){
ActivityService.saveActivity('user','action','object');
expect($http.post.callCount).to.equal(1);
}));
});
JAVASCRIPT
37/62
Chai Assertion Library (BDD/TDD framework)
Should
Expect
Assert
chai.should();
foo.should.be.a('string');
foo.should.equal('bar');
JAVASCRIPT
varexpect=chai.expect;
expect(foo).to.be.a('string');
expect(foo).to.equal('bar');
JAVASCRIPT
varassert=chai.assert;
assert.typeOf(foo,'string');
assert.equal(foo,'bar');
JAVASCRIPT
38/62
End2End tests
39/62
Protractor
Open Source E2E Testframework for AngularJS Apps
Tests run in a real browser
Tests can be written with Jasmine (default), Mocha, Cucumber
No more waits and sleeps
Build with Node.js on top of WebdriverJS
·
·
·
·
·
40/62
Protractor and Jasmine (BDD framework)
describe('Managecustomer',function(){
varptor;
beforeEach(function(){
browser.get('/');
ptor=protractor.getInstance();
element(by.id('navEmployees')).click();
element(by.id('navListEmployees')).click();
});
it('shouldnavigatetolistemployeespage',function(){
expect(ptor.getCurrentUrl()).toMatch(/#/list-employees/);
});
});
JAVASCRIPT
41/62
Protractor and Jasmine
Running End2End Tests with Protractor
it('shouldfindemployeeMariaonlistsearchpage',function(){
createMultipleEmployees();//Createsemployees:Max,Maria,Daniel,John
...
element(by.id('searchText')).sendKeys('Ma');
expect(element.all(by.id('employee')).count()).toBe(2);
element(by.id('searchText')).sendKeys('ria');
expect(element.all(by.id('employee')).count()).toBe(1);
});
JAVASCRIPT
npminstall-gprotractor
webdriver-managerstart
protractortest/client/e2e/conf.js
BASH
42/62
Demo :: Project Staffing App
44/62
45/62
46/62
Project Staffing App - TEST Environment
http://54.170.140.7:9000/
Delivery Pipeline
http://54.75.209.193/jenkins/view/EnterJS-Pipeline/
Info: Server will be shutdown after talk
47/62
Delivery Pipeline
48/62
Delivery Pipeline Steps
49/62
Collect the reports
Mocha reporter ⇒unit test
Jasmine reporter ⇒end2end tests
ESLint ⇒static code analysis
·
·
·
50/62
Mocha Report (unit tests)
51/62
Protractor Report (end2end tests)
52/62
ESLint Report (static code analysis)
53/62
Using Container during Development
Docker / boot2docker
docker-compose aka fig
Docker Hub / Registry
·
·
·
Docker
Container Technology, Lightweight, Portable
55/62
boot2docker
Based on Tiny Core Linux (required for MacOS and Windows)
56/62
docker-compose
project-staffinggit:(master)✗ docker-compose
Commands:
build Buildorrebuildservices
help Gethelponacommand
kill Killcontainers
logs Viewoutputfromcontainers
port Printthepublicportforaportbinding
ps Listcontainers
pull Pullsserviceimages
rm Removestoppedcontainers
run Runaone-offcommand
scale Setnumberofcontainersforaservice
start Startservices
stop Stopservices
restart Restartservices
up Createandstartcontainers
BASH
57/62
docker-compose up
➜ project-staffinggit:(master)✗ docker-composeup
Recreatingprojectstaffing_mongodb_1...
Creatingprojectstaffing_nodejsserver_1...
Buildingnodejsserver...
Step0:FROMtcnksm/centos-ruby
--->255207061af8
Step1:RUNyuminstall-ynpm
--->Usingcache
--->c8ca0ad1bec0
Step2:COPY./opt/project-staffing/
--->dc70b159f357
...
Step5:CMDnode/opt/project-staffing/server.js
--->Runningin78d831b9f0f0
--->88b07ba248a0
Successfullybuilt88b07ba248a0
...
BASH
58/62
Docker Hub
https://registry.hub.docker.com/
Official Repositories: redis, ubuntu, WordPress, MySQL, mongoDB, nodeJS, ...
Share your own Containers
·
·
·
59/62
estions?
Consultant
nsultant
EnterJS 2015 - Continuous Integration for Frontend Code

More Related Content

What's hot (20)

PDF
Adobe Experience Manager Core Components
Gabriel Walt
 
PPTX
MVC Frameworks for building PHP Web Applications
Vforce Infotech
 
PDF
TDC2017 | Florianopolis - Trilha DevOps How we figured out we had a SRE team ...
tdc-globalcode
 
PPTX
Playframework + Twitter Bootstrap
Kevingo Tsai
 
PDF
Sightly - AEM6 UI Development using JS and JAVA
Yash Mody
 
PDF
Building a Secure App with Google Polymer and Java / Spring
sdeeg
 
PPT
Java script Tutorial - QaTrainingHub
QA TrainingHub
 
PPTX
Google Developer Group(GDG) DevFest Event 2012 Android talk
Imam Raza
 
PDF
AEM Sightly Template Language
Gabriel Walt
 
PDF
Play Framework vs Grails Smackdown - JavaOne 2013
Matt Raible
 
PDF
The Complementarity of React and Web Components
Andrew Rota
 
PDF
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
Evan Mullins
 
PDF
Web Components & Polymer 1.0 (Webinale Berlin)
Hendrik Ebbers
 
PDF
Booting up with polymer
Marcus Hellberg
 
PPTX
Authentication in Node.js
Jason Pearson
 
PPTX
Dynamic components using SPA concepts in AEM
Bojana Popovska
 
PDF
CIRCUIT 2015 - Content API's For AEM Sites
ICF CIRCUIT
 
PDF
Angular vs React for Web Application Development
FITC
 
PPTX
Polymer and web component
Imam Raza
 
PDF
Building Progressive Web Apps for Android and iOS
FITC
 
Adobe Experience Manager Core Components
Gabriel Walt
 
MVC Frameworks for building PHP Web Applications
Vforce Infotech
 
TDC2017 | Florianopolis - Trilha DevOps How we figured out we had a SRE team ...
tdc-globalcode
 
Playframework + Twitter Bootstrap
Kevingo Tsai
 
Sightly - AEM6 UI Development using JS and JAVA
Yash Mody
 
Building a Secure App with Google Polymer and Java / Spring
sdeeg
 
Java script Tutorial - QaTrainingHub
QA TrainingHub
 
Google Developer Group(GDG) DevFest Event 2012 Android talk
Imam Raza
 
AEM Sightly Template Language
Gabriel Walt
 
Play Framework vs Grails Smackdown - JavaOne 2013
Matt Raible
 
The Complementarity of React and Web Components
Andrew Rota
 
WordCamp Greenville 2018 - Beware the Dark Side, or an Intro to Development
Evan Mullins
 
Web Components & Polymer 1.0 (Webinale Berlin)
Hendrik Ebbers
 
Booting up with polymer
Marcus Hellberg
 
Authentication in Node.js
Jason Pearson
 
Dynamic components using SPA concepts in AEM
Bojana Popovska
 
CIRCUIT 2015 - Content API's For AEM Sites
ICF CIRCUIT
 
Angular vs React for Web Application Development
FITC
 
Polymer and web component
Imam Raza
 
Building Progressive Web Apps for Android and iOS
FITC
 

Similar to EnterJS 2015 - Continuous Integration for Frontend Code (20)

PDF
Building Performance - ein Frontend-Build-Prozess für Java mit Maven
Oliver Ochs
 
PDF
Not Just a Pretty Face: How to design and build a cross-CMS CSS framework
crystalenka
 
PPT
Using a CSS Framework
Gareth Saunders
 
PDF
Scott Jehl - Delivering Responsibly - beyond tellerrand Düsseldorf 2015
beyond tellerrand
 
PDF
Death of a Themer
James Panton
 
PDF
Hardboiled Front End Development — Found.ation
Spiros Martzoukos
 
PPTX
10 Tips to make your Website lightning-fast - SMX Stockholm 2012
Bastian Grimm
 
PDF
Build Better Responsive websites. Hrvoje Jurišić
MeetMagentoNY2014
 
PDF
Front End Workflow
Matt Bailey
 
PPTX
EdTechJoker Spring 2020 - Lecture 4 - HTML
Bryan Ollendyke
 
PDF
Building performance auf der Developer Conference Hamburg
Oliver Ochs
 
PDF
BADCamp 2012 -Beginner Best Practices
meghsweet
 
PPTX
HTML / CSS / JS Web basics
btopro
 
PDF
Structuring your CSS for maintainability: rules and guile lines to write CSS
Sanjoy Kr. Paul
 
PPTX
The Need for Speed - SMX Sydney 2013
Bastian Grimm
 
PPTX
Presentation Tier optimizations
Anup Hariharan Nair
 
PPTX
Backbone.js
898RakeshWaghmare
 
DOCX
css-tools
Desarae Veit
 
PDF
Generate SSIS packages automatically with Biml and BimlScript (SQLKonferenz 2...
Cathrine Wilhelmsen
 
PPTX
.NET Fest 2018. Martin Ullrich. MSBuild: Understand and Customize Your .NET B...
NETFest
 
Building Performance - ein Frontend-Build-Prozess für Java mit Maven
Oliver Ochs
 
Not Just a Pretty Face: How to design and build a cross-CMS CSS framework
crystalenka
 
Using a CSS Framework
Gareth Saunders
 
Scott Jehl - Delivering Responsibly - beyond tellerrand Düsseldorf 2015
beyond tellerrand
 
Death of a Themer
James Panton
 
Hardboiled Front End Development — Found.ation
Spiros Martzoukos
 
10 Tips to make your Website lightning-fast - SMX Stockholm 2012
Bastian Grimm
 
Build Better Responsive websites. Hrvoje Jurišić
MeetMagentoNY2014
 
Front End Workflow
Matt Bailey
 
EdTechJoker Spring 2020 - Lecture 4 - HTML
Bryan Ollendyke
 
Building performance auf der Developer Conference Hamburg
Oliver Ochs
 
BADCamp 2012 -Beginner Best Practices
meghsweet
 
HTML / CSS / JS Web basics
btopro
 
Structuring your CSS for maintainability: rules and guile lines to write CSS
Sanjoy Kr. Paul
 
The Need for Speed - SMX Sydney 2013
Bastian Grimm
 
Presentation Tier optimizations
Anup Hariharan Nair
 
Backbone.js
898RakeshWaghmare
 
css-tools
Desarae Veit
 
Generate SSIS packages automatically with Biml and BimlScript (SQLKonferenz 2...
Cathrine Wilhelmsen
 
.NET Fest 2018. Martin Ullrich. MSBuild: Understand and Customize Your .NET B...
NETFest
 
Ad

Recently uploaded (20)

PDF
Unlocking FME Flow’s Potential: Architecture Design for Modern Enterprises
Safe Software
 
PDF
EIS-Webinar-Engineering-Retail-Infrastructure-06-16-2025.pdf
Earley Information Science
 
PDF
The Future of Product Management in AI ERA.pdf
Alyona Owens
 
PPTX
UserCon Belgium: Honey, VMware increased my bill
stijn40
 
PPTX
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
PPTX
Curietech AI in action - Accelerate MuleSoft development
shyamraj55
 
PDF
Python Conference Singapore - 19 Jun 2025
ninefyi
 
PPTX
CapCut Pro Crack For PC Latest Version {Fully Unlocked} 2025
pcprocore
 
PDF
Why aren't you using FME Flow's CPU Time?
Safe Software
 
PDF
How to Visualize the ​Spatio-Temporal Data Using CesiumJS​
SANGHEE SHIN
 
PDF
ArcGIS Utility Network Migration - The Hunter Water Story
Safe Software
 
PDF
Redefining Work in the Age of AI - What to expect? How to prepare? Why it mat...
Malinda Kapuruge
 
PPTX
Paycifi - Programmable Trust_Breakfast_PPTXT
FinTech Belgium
 
PDF
Java 25 and Beyond - A Roadmap of Innovations
Ana-Maria Mihalceanu
 
PDF
Optimizing the trajectory of a wheel loader working in short loading cycles
Reno Filla
 
PDF
Database Benchmarking for Performance Masterclass: Session 2 - Data Modeling ...
ScyllaDB
 
PDF
UiPath Agentic AI ile Akıllı Otomasyonun Yeni Çağı
UiPathCommunity
 
PDF
Hello I'm "AI" Your New _________________
Dr. Tathagat Varma
 
PDF
Database Benchmarking for Performance Masterclass: Session 1 - Benchmarking F...
ScyllaDB
 
PPTX
Smarter Governance with AI: What Every Board Needs to Know
OnBoard
 
Unlocking FME Flow’s Potential: Architecture Design for Modern Enterprises
Safe Software
 
EIS-Webinar-Engineering-Retail-Infrastructure-06-16-2025.pdf
Earley Information Science
 
The Future of Product Management in AI ERA.pdf
Alyona Owens
 
UserCon Belgium: Honey, VMware increased my bill
stijn40
 
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
Curietech AI in action - Accelerate MuleSoft development
shyamraj55
 
Python Conference Singapore - 19 Jun 2025
ninefyi
 
CapCut Pro Crack For PC Latest Version {Fully Unlocked} 2025
pcprocore
 
Why aren't you using FME Flow's CPU Time?
Safe Software
 
How to Visualize the ​Spatio-Temporal Data Using CesiumJS​
SANGHEE SHIN
 
ArcGIS Utility Network Migration - The Hunter Water Story
Safe Software
 
Redefining Work in the Age of AI - What to expect? How to prepare? Why it mat...
Malinda Kapuruge
 
Paycifi - Programmable Trust_Breakfast_PPTXT
FinTech Belgium
 
Java 25 and Beyond - A Roadmap of Innovations
Ana-Maria Mihalceanu
 
Optimizing the trajectory of a wheel loader working in short loading cycles
Reno Filla
 
Database Benchmarking for Performance Masterclass: Session 2 - Data Modeling ...
ScyllaDB
 
UiPath Agentic AI ile Akıllı Otomasyonun Yeni Çağı
UiPathCommunity
 
Hello I'm "AI" Your New _________________
Dr. Tathagat Varma
 
Database Benchmarking for Performance Masterclass: Session 1 - Benchmarking F...
ScyllaDB
 
Smarter Governance with AI: What Every Board Needs to Know
OnBoard
 
Ad

EnterJS 2015 - Continuous Integration for Frontend Code