Upload
atlassian
View
162
Download
6
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
#atlassian
CHRIS MOUNTFORD • SENIOR DEVELOPER • ATLASSIAN • @CHROMOSUNDRIFT
A Walk on the Client SideJavaScript Apps as Cross-Domain
Embeddable Components
A “green fields” project
Profile
• Atlassian ID Single Sign-On (SSO)
• Java, Spring, JSPs• Full page forms• Avatar experience• test automation
• Ignores Atlassian Design Guidelines (ADG)
Legacy Profile
• Identity Card design• Client-side architecture• Can be embedded in any
Atlassian application• Transition path from
legacy profile application
Profile Card Design
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
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
Automated Testing
Automated Testing
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
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
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
D E V L O O P
Working with JavaScript Modules
• Require JS• Almond• Node.js• NPM• Karma• Soy and LESS• Maven
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
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
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
<!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
<!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
<!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
<!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
<!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
TODO: Embedded Screenshot
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
Thank you!
CHRIS MOUNTFORD • SENIOR DEVELOPER • ATLASSIAN • @CHROMOSUNDRIFT