Date post: | 15-Aug-2015 |
Category: |
Technology |
Upload: | ben-limmer |
View: | 2,432 times |
Download: | 0 times |
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-variablesconfig/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 initializationapp/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 });
languageForCountryCodeapp/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 };
templateapp/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 StackHosting
• 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 routingindex.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 variableslib/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 addresslib/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 configconfig/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 $ [email protected]! 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