Business wants to fully rebuild the webapps
AngularJs is becoming more and more popular, we try it, it looks awesome!
...exactly
betclic sport .fr
betclic casino .com
betclic turf .fr
expekt casino .com
expekt sport .com
betclic sport .com
betclic sport .it
montecarlo casino .com
...more than 15 webapps
4 universes
3 brands
Ios & Droid apps using webviews
100 000 single users per month, 3 000 000 bets per month
... must confess not so good with Javascript
Multi-tenant: same package per universe for all brands
No Duplicated code
Unit tests & Integration tests
The business wants webapps with same functionnalies and look and feel as the native apps
One Team, one screen, one keyboard
Fix a goal: a real user story
Prepare a detailed dojo and play it in front of the team
The team replays it and switches keyboard every 10min
Write our own coding conventions
full C#
not a lot of code to write: just an optimized presentation layer
shared core used on web front
It's just one HomeController with one action
not only serve our angular app but also injects dynamic javascript
analyzes the incoming request:
https://m.betclic.com/sport/
injects token & context in a constant service
window.contextToken = "eyJ0eXA..";
angular.module('global').constant('appContext', {
"channelId":"BetclicMobile",
"applicationId":"BetclicCom",
"legislation":"Com",
"universe":"Sports",
...});
})();
bootstraps constants from config file and database
angular.module("sport.core").constant("sportInitialData", {
sportWebApiUrl:"https://webapi/url",
iconsSportUrl:"https://cdn/url",
...
});
chooses the corresponding bundle
https://m.betclic.com/sport/script src="/sport/build/mon_bundle_betclic_com.js?v=15.010"
Orhttps://m.betclic.fr/sport/script src="/sport/build/mon_bundle_betclic_fr.js?v=15.010"
Thanks to our gulp build chain
In gulp config file, we describe our different applications:
applications: [
{
name: 'BetclicCom',
code: 'com'
},
{
name: 'BetclicFr',
code: 'fr'
},
{
name: 'ExpektCom',
code: 'expektCom'
}]
so for each applications:
config.applications.forEach(function (application) {
var taskName = application.code + '_scripts';
gulp.task(taskName, function () {
return gulp.src(tools.GetFilesFilteredByApplicationCode(..))
.pipe($.if(configBuild.minify, $.uglify()))
.pipe($.concat('app_' + application.code + '.js'))
.pipe(gulp.dest(config.paths.build));
});
scriptsTasks.push(taskName);
});
method "GetFilesFilteredByApplicationCode" will do the magic
so in the build folder, we have:
app_com.js
app_fr.js
app_expektCom.js
same for templates!
Common infrastructure:
Transversal features
Universe apps are loosely coupled to common feature,
but still tightly coupled to the Infrastructure changes!
Our approach is very pragmatic
As many entreprise-grade applications, we made some trade-off regarding the purity of our application
For instance, the payment domain is really complex and business-critical
The decision was to integrate our existing web-cashier directly int the web-app, through an iframe integration
To do so, we simply added some mobile-designed razor views,
update the view-engine,
DisplayModeProvider.Instance.Modes.Insert(0, new DefaultDisplayMode("mobile")
{
ContextCondition = IsFromMobileWebApp())
});
cutsomize a bit our SSO and...
Betclic is present in 21 languages. We obvioulsy rely on a CMS, built a long-time ago...
Our webapps have to support different languages, and for performance purpose, we couldn't afford to preload all the needed ressources
We built our client side language management over the awesome angular-translate module, wich handles batching ressources fecthing, local-storage persistance
Each universe is responsible for registering its own languageProvider:
angular.module('sport.helpers')
.factory('translationProvider', translationProvider);
translationProvider.$inject = ['translationSvc']; // Restangular ressource
function translationProvider(translationSvc) {
return {
universe: 'sport',
load: function () { return translationSvc.getTranslations(); }
}
}
Then the global module loads and puts everything in cache:
function checkGlobal(languageCode) {
return $http.get(envContext.globalApi + 'translation'); // global resource
}
function checkUniverse(languageCode) {
var provider = $injector.get('translationProvider');
return provider.load();
}
Templates for Visual Studio by John Papa
NPM and Bower package Intellisense directly Visual Studio JSON editor
A task runner for Grunt and Gulp directly within Visual Studio
Intellisense in JavaScript files for injected AngularJS components in Visual Studio.
Custom nuget package with node,npm and git standalone version
https://www.nuget.org/packages/Betclic.BuildTools.Node/1.0.0Post build Event: npm install, bower install, gulp tasks
First weeks: all good :)
we have the look and feel of native app
But too much limitations
« It’s for app, not webapp »: Ionic team
Browser compatibility (IE …)
Integration team unhappy
don't be afraid to use AngularJs !