28
#atlassian

Walk on the Client Side - Chris Mountford

Embed Size (px)

DESCRIPTION

Well-engineered JavaScript is the best way to provide rich user experiences on the web today. However, there are many gnarly challenges to a modular approach on the client side, especially across multiple domains. In this talk we’ll cover the frameworks, techniques, and principles Atlassian uses to build a client-side application with authenticated server-side integration that is designed as an embeddable cross-domain component.

Citation preview

Page 1: Walk on the Client Side - Chris Mountford

#atlassian

Page 2: Walk on the Client Side - Chris Mountford

CHRIS MOUNTFORD • SENIOR DEVELOPER • ATLASSIAN • @CHROMOSUNDRIFT

A Walk on the Client SideJavaScript Apps as Cross-Domain

Embeddable Components

Page 3: Walk on the Client Side - Chris Mountford

A “green fields” project

Page 4: Walk on the Client Side - Chris Mountford

Profile

Page 5: Walk on the Client Side - Chris Mountford
Page 6: Walk on the Client Side - Chris Mountford
Page 7: Walk on the Client Side - Chris Mountford

• Atlassian ID Single Sign-On (SSO)

• Java, Spring, JSPs• Full page forms• Avatar experience• test automation

• Ignores Atlassian Design Guidelines (ADG)

Legacy Profile

Page 8: Walk on the Client Side - Chris Mountford

• Identity Card design• Client-side architecture• Can be embedded in any

Atlassian application• Transition path from

legacy profile application

Profile Card Design

Page 9: Walk on the Client Side - Chris Mountford

D E V L O O P

A R C H I T E C T U R E

Profile

D E P L O Y M E N T

E M B E D D I N G

Page 10: Walk on the Client Side - Chris Mountford

P R O F I L E S E RV E R H O S T A P P L I C AT I O N - ( e . g . B I T B U C K E T, J I R A )

A R C H I T E C T U R E

Full Stack

R E S T R E S O U R C E S

B A C K B O N E / U N D E R S C O R E

A U I S O Y T E M P L AT E SJ Q U E RY

M I C R O -S E RV I C E S

R E Q U I R E . J S & A L M O N D O T H E R

C L O U D S E RV I C E B R O W S E R

P R O F I L E

Scala, Java

JavaScript, LESS, Soy

Page 11: Walk on the Client Side - Chris Mountford

Automated Testing

Page 12: Walk on the Client Side - Chris Mountford

Automated Testing

Page 13: Walk on the Client Side - Chris Mountford

A R C H I T E C T U R E

Automated Testing

T E S T I N G F R A M E W O R K S !

•Java•JUnit

•Scala•Specs2

•JavaScript•Karma and PhantomJS•Node.js

•Selenium with page objects

Page 14: Walk on the Client Side - Chris Mountford

A R C H I T E C T U R E

Security• CSRF, XSS• Cookies are domain-scoped• http://id.foo.com/

• CORS• Cross-Origin Resource Sharing• request and response headers

• JSONP• is always a security hole*• never use this!

• Never trust client data

Page 15: Walk on the Client Side - Chris Mountford

A R C H I T E C T U R E

D E V L O O P

Profile

D E P L O Y M E N T

E M B E D D I N G

Page 16: Walk on the Client Side - Chris Mountford

D E V L O O P

Working with JavaScript Modules

• Require JS• Almond• Node.js• NPM• Karma• Soy and LESS• Maven

Page 17: Walk on the Client Side - Chris Mountford
Page 18: Walk on the Client Side - Chris Mountford

D E P L O Y M E N T

D E V L O O P

A R C H I T E C T U R E

Profile

E M B E D D I N G

Page 19: Walk on the Client Side - Chris Mountford

D E P L O Y M E N T

Maven drives the build

• Maven • Node.js & NPM• Require JS and Almond• Karma test runner• PhantomJS

• Soy to JS Compiler• LESS transformed to CSS

Page 20: Walk on the Client Side - Chris Mountford

E M B E D D I N G

D E V L O O P

A R C H I T E C T U R E

Profile

D E P L O Y M E N T

Page 21: Walk on the Client Side - Chris Mountford

<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Test profile embed</title> <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui.min.css" media="all"> <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-experimental.min.css" media="all"> <!--[if lt IE 9]><link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-ie.min.css" media="all"><![endif]--> <!--[if IE 9]><link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-ie.min.css" media="all"><![endif]--> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.0/backbone-min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui.min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-experimental.min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-soy.min.js"></script> <!--[if lt IE 9]><script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-ie.min.js"></script><![endif]--> </head> <body> <div class="profile-card-container" data-base-url="https://id-stg1.atlassian.com/profile"></div> <script src="https://id-stg1.atlassian.com/profile/pjs/embedded.js"></script> <script> AID.ProfileCard('.profile-card-container'); </script> </body> </html>

E M B E D D I N G

Page 22: Walk on the Client Side - Chris Mountford

<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Test profile embed</title> <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui.min.css" media="all"> <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-experimental.min.css" media="all"> <!--[if lt IE 9]><link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-ie.min.css" media="all"><![endif]--> <!--[if IE 9]><link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-ie.min.css" media="all"><![endif]--> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.0/backbone-min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui.min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-experimental.min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-soy.min.js"></script> <!--[if lt IE 9]><script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-ie.min.js"></script><![endif]--> </head> <body> <div class="profile-card-container" data-base-url="https://id-stg1.atlassian.com/profile"></div> <script src="https://id-stg1.atlassian.com/profile/pjs/embedded.js"></script> <script> AID.ProfileCard('.profile-card-container'); </script> </body> </html>

E M B E D D I N G

Page 23: Walk on the Client Side - Chris Mountford

<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Test profile embed</title> <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui.min.css" media="all"> <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-experimental.min.css" media="all"> <!--[if lt IE 9]><link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-ie.min.css" media="all"><![endif]--> <!--[if IE 9]><link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-ie.min.css" media="all"><![endif]--> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.0/backbone-min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui.min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-experimental.min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-soy.min.js"></script> <!--[if lt IE 9]><script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-ie.min.js"></script><![endif]--> </head> <body> <div class="profile-card-container" data-base-url="https://id-stg1.atlassian.com/profile"></div> <script src="https://id-stg1.atlassian.com/profile/pjs/embedded.js"></script> <script> AID.ProfileCard('.profile-card-container'); </script> </body> </html>

E M B E D D I N G

R O O T E L E M E N T

Page 24: Walk on the Client Side - Chris Mountford

<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Test profile embed</title> <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui.min.css" media="all"> <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-experimental.min.css" media="all"> <!--[if lt IE 9]><link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-ie.min.css" media="all"><![endif]--> <!--[if IE 9]><link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-ie.min.css" media="all"><![endif]--> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.0/backbone-min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui.min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-experimental.min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-soy.min.js"></script> <!--[if lt IE 9]><script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-ie.min.js"></script><![endif]--> </head> <body> <div class="profile-card-container" data-base-url="https://id-stg1.atlassian.com/profile"></div> <script src="https://id-stg1.atlassian.com/profile/pjs/embedded.js"></script> <script> AID.ProfileCard('.profile-card-container'); </script> </body> </html>

E M B E D D I N G

E M B E D S C R I P T

R O O T E L E M E N T

Page 25: Walk on the Client Side - Chris Mountford

<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Test profile embed</title> <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui.min.css" media="all"> <link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-experimental.min.css" media="all"> <!--[if lt IE 9]><link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-ie.min.css" media="all"><![endif]--> <!--[if IE 9]><link rel="stylesheet" href="//aui-cdn.atlassian.com/aui-adg/5.5.5/css/aui-ie.min.css" media="all"><![endif]--> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.5.2/underscore-min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.0/backbone-min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui.min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-experimental.min.js"></script> <script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-soy.min.js"></script> <!--[if lt IE 9]><script src="//aui-cdn.atlassian.com/aui-adg/5.5.5/js/aui-ie.min.js"></script><![endif]--> </head> <body> <div class="profile-card-container" data-base-url="https://id-stg1.atlassian.com/profile"></div> <script src="https://id-stg1.atlassian.com/profile/pjs/embedded.js"></script> <script> AID.ProfileCard('.profile-card-container'); </script> </body> </html>

E M B E D D I N G

A P I C A L LE M B E D S C R I P T

R O O T E L E M E N T

Page 26: Walk on the Client Side - Chris Mountford

TODO: Embedded Screenshot

Page 27: Walk on the Client Side - Chris Mountford

Key takeaways: #atlassian

• Require.js: Build modular JavaScript, ship compact bundles.• JSONP is always a security hole• FYI: CDN FTW• Karma is good for testing JavaScript. Testing JavaScript is good Karma.

@chromosundrift

Page 28: Walk on the Client Side - Chris Mountford

Thank you!

CHRIS MOUNTFORD • SENIOR DEVELOPER • ATLASSIAN • @CHROMOSUNDRIFT