Deploying a Location-Aware Ember Application

Deploying a
location-aware EmberJS app
Ben Limmer
EmberJS Denver Meetup
5/27/2015
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
deployment can be
scary
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
!==
Dev/Staging Production
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
data/servers can differ
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
data/servers can differ
db sharding
mini/uglification
caching
latency
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
us testing
>
users testing
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
dev/qa/stakeholder testing in prod
>
users testing in prod
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
enter ember-cli-deploy
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
– Michael Klein
“Lightning Fast Deployments of Ember-CLI
Apps”
LevelbossMike
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
– Ben Limmer
“Easy, Lightning Fast, Sleep-Better-at-Night,
Deployments of Ember-CLI Apps”
blimmer
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
how does it work?
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
“abc123”: “<html>...</html>”
what’s current?
contents of abc123
example.org
“current”: “abc123”
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
“def456”: “<html>...</html>”
app-hash.css, app-hash.js, ...
what’s current?
contents of abc123
“abc123”: “<html>...</html>”
example.org
“current”: “abc123”
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
“def456”: “<html>...</html>”
what’s def456?
contents of def456
“abc123”: “<html>...</html>”
example.org/?
secret=def456
“current”: “abc123”
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
“def456”: “<html>...</html>”
what’s current?
contents of def456
“abc123”: “<html>...</html>”
example.org
“current”: “def456”
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
💩!
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
“def456”: “<html>...</html>”
what’s current?
contents of abc123
“abc123”: “<html>...</html>”
example.org
“current”: “abc123”
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
demo project
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
Español English
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
ip address mexican user
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
ember-cli-server-variables
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
Client Stack
• EmberJS 1.12
• ember-i18n
• ember-cli-deploy (redis + s3 adapters)
• ember-cli-server-variables
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
client code
ember-cli-server-variables
config/environment.js
1 module.exports = function(environment) {
2 var ENV = {
3 modulePrefix: 'location-aware-ember',
4
5 serverVariables: {
6 tagPrefix: 'var',
7 vars: ['country']
8 }
9 };
10
11 if (environment === 'development') {
12 ENV.serverVariables.defaults = {
13 'country': 'US'
14 };
15 }
16 }
session initialization
1 export default Ember.Service.extend({
2 serverVariables: Ember.inject.service(),
3
4 countryCode: 'US',
5
6 forceInitialization: function () {
7 const country = this.get('serverVariables.country');
8 if (country) {
9 this.set('countryCode', country);
10 }
11 }
12 });
app/services/session.js
app initialization
app/routes/application.js
1 export default Ember.Route.extend({
2 i18n: Ember.inject.service(),
3 session: Ember.inject.service(),
4
5 beforeModel: function () {
6 this.set(
7 'i18n.locale',
8 languageForCountryCode(this.get('session.countryCode'))
9 );
10 }
11 });
languageForCountryCode
app/utils/language-for-country-code.js
1 export default function languageForCountryCode(countryCode) {
2 switch(countryCode.toLowerCase()) {
3 case 'es':
4 case 'mx':
5 return 'es';
6 case 'gb':
7 case 'us':
8 return 'en';
9 default:
10 return 'en';
11 }
12 }
translations (en)
app/locales/en/translations.js
1 export default {
2 'home': {
3 'greeting': 'Hello!',
4 'secondaryGreeting': 'Thank you for visiting from
{{countryName}}.'
5 }
6 };
translations (es)
app/locales/es/translations.js
1 export default {
2 'home': {
3 'greeting': ‘¡Hola!',
4 'secondaryGreeting': 'Gracias por visitar desde
{{countryName}}.'
5 }
6 };
template
app/templates/index.hbs
1 <div class='row'>
2 <h2 class='text-center' id="greeting">
3 {{t 'home.greeting'}}
4 </h2>
5 </div>
6 <div class='row'>
7 <h4 class='text-center' id="secondary-greeting">
8 {{t 'home.secondaryGreeting' countryName=countryName}}
9 </h4>
10 </div>
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
demo
Server Stack
Hosting
• heroku
• heroku-redis
Server Tech
• express 4
• geoip-lite
• redis
• cheerio
• node-ember-cli-
deploy-redis
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
server code
server routing
index.js
1 app.get('/', function(req, res) {
2 nodeEmberCliDeployRedis.
3 fetchIndex(‘location-aware-ember’, req, client).
4 then(function (indexHtml) {
5 indexHtml = serverVarInjectHelper.
6 injectServerVariables(indexHtml, req);
7 res.status(200).send(indexHtml);
8 }).catch(function(err) {
9 res.status(500).send('Oh noes!n' + err.message);
10 });
11 });
inject server variables
lib/server-var-inject-helper.js
1 var injectServerVariables = function (htmlString, req) {
2 var $ = cheerio.load(htmlString);
3 $('meta[name=var-country]').
4 attr('content', locationHelper.getCountry(req));
5
6 return $.html();
7 };
geocode ip address
lib/location-helper.js
1 var getCountry = function (req) {
2 var ipAddr = req.headers["x-forwarded-for"];
3 if (ipAddr){
4 var list = ipAddr.split(",");
5 ipAddr = list[list.length-1];
6 } else {
7 ipAddr = req.connection.remoteAddress;
8 }
9
10 var geo = geoip.lookup(ipAddr);
11
12 if (geo && geo.country) {
13 return geo.country;
14 } else {
15 return 'US';
16 }
17 };
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
running in prod
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
feature request:
change locale in realtime
git diff
++app/templates/index.hbs
1 <div class='row language-chooser'>
2 <h6>{{t 'home.chooseLang'}}</h6>
3 <a id='set-en' {{action 'setLanguage' 'en'}}>EN</a>
4 <a id='set-es' {{action 'setLanguage' 'es'}}>ES</a>
5 </div>
git diff
++app/routes/application.js
1 export default Ember.Route.extend({
2 i18n: Ember.inject.service(),
3 ...
4 actions: {
5 setLanguage: function (locale) {
6 this.set('i18n.locale', locale);
7 }
8 }
9 });
deloyment config
config/deploy.js
1 module.exports = {
2 "production": {
3 buildEnv: "production",
4 store: {
5 host: 'ec2-107-22-167-67.compute-1.amazonaws.com',
6 port: 6929,
7 password: process.env.REDIS_PW,
8 },
9 assets: {
10 "type": "s3",
11 "accessKeyId": "AKIAIFM7MT2JTIHV6HBA",
12 "secretAccessKey": process.env.S3_SECRET_ACCESS_KEY,
13 "bucket": "location-aware-ember"
14 }
15 }
16 };
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
demo
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
thank you!
blimmer
l1m5
hello@benlimmer.com
ember.party
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
demo project code
• location-aware-ember
• location-aware-ember-server
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
demo project libs (client)
• ember-cli-deploy
• s3 adapter
• redis adapter
• ember-cli-server-variables
• ember-i18n
Ben LimmerEmberJS Meetup - 5/27/2015 ember.party
demo project libs (server)
• express js
• geoip-lite
• redis
• cheerio
• node-ember-cli-deploy-redis
1 of 51

More Related Content

What's hot(20)

Introduction to es6Introduction to es6
Introduction to es6
NexThoughts Technologies774 views
AngularJS Unit TestingAngularJS Unit Testing
AngularJS Unit Testing
Prince Norin466 views
PWA 與 Service WorkerPWA 與 Service Worker
PWA 與 Service Worker
Anna Su4.8K views
Djangocon 2014 angular + djangoDjangocon 2014 angular + django
Djangocon 2014 angular + django
Nina Zakharenko8.3K views
Service Worker PresentationService Worker Presentation
Service Worker Presentation
Kyle Dorman1.5K views
Mini Rails FrameworkMini Rails Framework
Mini Rails Framework
Aviandri Rivai1.3K views
Automated Testing with RubyAutomated Testing with Ruby
Automated Testing with Ruby
Keith Pitty16.7K views
Cucumber Ru09 WebCucumber Ru09 Web
Cucumber Ru09 Web
Joseph Wilk5.5K views
Cooking Up DramaCooking Up Drama
Cooking Up Drama
bridgetkromhout1.8K views
Service workersService workers
Service workers
jungkees3.9K views
Zenly - Reverse geocodingZenly - Reverse geocoding
Zenly - Reverse geocoding
CocoaHeads France5.3K views
Server Side SwiftServer Side Swift
Server Side Swift
Jens Ravens1.3K views
RSpec 2 Best practicesRSpec 2 Best practices
RSpec 2 Best practices
Andrea Reginato1.5M views
PowerShell: Automation for everyonePowerShell: Automation for everyone
PowerShell: Automation for everyone
Gavin Barron471 views
Psgi Plack SfpmPsgi Plack Sfpm
Psgi Plack Sfpm
som_nangia1.8K views

Similar to Deploying a Location-Aware Ember Application(20)

Recently uploaded(20)

[2023] Putting the R! in R&D.pdf[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdf
Eleanor McHugh36 views
Java Platform Approach 1.0 - Picnic MeetupJava Platform Approach 1.0 - Picnic Meetup
Java Platform Approach 1.0 - Picnic Meetup
Rick Ossendrijver24 views
The Research Portal of Catalonia: Growing more (information) & more (services)The Research Portal of Catalonia: Growing more (information) & more (services)
The Research Portal of Catalonia: Growing more (information) & more (services)
CSUC - Consorci de Serveis Universitaris de Catalunya59 views
CXL at OCPCXL at OCP
CXL at OCP
CXL Forum203 views
METHOD AND SYSTEM FOR PREDICTING OPTIMAL LOAD FOR WHICH THE YIELD IS MAXIMUM ...METHOD AND SYSTEM FOR PREDICTING OPTIMAL LOAD FOR WHICH THE YIELD IS MAXIMUM ...
METHOD AND SYSTEM FOR PREDICTING OPTIMAL LOAD FOR WHICH THE YIELD IS MAXIMUM ...
Prity Khastgir IPR Strategic India Patent Attorney Amplify Innovation24 views
Tunable Laser (1).pptxTunable Laser (1).pptx
Tunable Laser (1).pptx
Hajira Mahmood21 views
Liqid: Composable CXL PreviewLiqid: Composable CXL Preview
Liqid: Composable CXL Preview
CXL Forum120 views

Deploying a Location-Aware Ember Application