Music API
Over 20 territories
Markup with arbitrary code, e.g. RenderAction:
<div class="first column width3">
# Html.RenderAction("Index", "Tracks", new { artistId = Model.ReleaseTile.ArtistId, releaseId = Model.ReleaseTile.ProductId, salePrice = Model.ReleaseTile.PriceValue, productUrl = Model.ReleaseTile.ProductUrl, artistUrl = Model.ReleaseTile.DisplayedArtistUrl, displayedArtistName = Model.ReleaseTile.DisplayedArtistName, IsPreOrder = Model.IsPreOrder, CheckPurchaseDetails = Model.IncludesPurchaseDetails });
# Html.RenderAction("Index", "AlsoByRelease", new { id = Model.ReleaseTile.ArtistId, BasedOnReleaseId = Model.ReleaseTile.ProductId });
</div>
Nice and modular, right? Hard to reason about whole pages
Never actually rendered a lot of sub-Actions on their own
Poor performance - spins up a whole MVC context each time
Pretty happy with the backend, keen to ditch views
Markup needed reworking anyway for the re-design!
No arbitrary code was appealing after Spark
More testable - everything in view models
Prototype designs with node mustache (we used Grunt for FE build anyway)
Use dummy data to mock up views
Fetching dummy data is a pain, just hook in this handy node 7d api client!
Run on linux, no spinning up Windows VM...
FE guy often WFH on a Mac - Windows environment a bit unfriendly
Looked out for X-7D-Responsive-Views header being sent (using browser plugin)
Switch out view engine based on that
(Also checked your IP was based in the 7d office)
[HasResponsiveView("sign-in")]
public ActionResult Index(string returnUrl)
{
if (_httpContext.IsResponsive())
{
var signInViewModel = BuildResponsiveViewModel(returnUrl);
}
else
{
var signInViewModel = BuildViewModel(returnUrl);
}
return View("SignIn", signInViewModel);
}
(Branching pretty hard)
Decided to push ahead and just use node
Validate node
On windows servers...
(Used by Azure for hosting node apps)
Also handles multiple node processes per server/LBing them
<handlers>
<add name="iisnode" path="redesign/server.js"
verb="*" modules="iisnode" />
</handlers>
<rule name="node-for-basket" stopProcessing="true">
<match url="^basket/items"/>
<action type="Rewrite" url="redesign/server.js" />
</rule>
(Apart from the occasional node stack trace showing up in the site header...)
<rule name="set-responsive-views-if-beta-cookie-sent">
<conditions>
<add input="{HTTP_COOKIE}" pattern="7digital_beta=" />
</conditions>
<serverVariables>
<set name="HTTP_X_7D_RESPONSIVE_VIEWS" value="true" />
</serverVariables>
</rule>
<rule name="node-app-if-header" stopProcessing="true">
<conditions>
<add input="{HTTP_X_7D_RESPONSIVE_VIEWS}" pattern="^true$" />
</conditions>
<action type="Rewrite" url="reboot/server.js" />
</rule>
Is there anything in particular you'd like to see on the new store?
BRING BACK THE FUNK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
router.get('/artist/:artistSlug/release/:releaseSlug',
handleReleasePage);
function handleReleasePage(req, res, next) {
api.Catalogue().getReleaseIdByUrl({
artistSlug: req.params.artistSlug,
releaseSlug: req.params.releaseSlug
}, function (err, idLookupRes) {
if (err) { return next(err); }
api.Releases().getDetails({
releaseId: idLookupRes.release.id
}, function (err, release) {
if (err) { return next(err); }
var forView = map.fromRelease(res);
return res.render('release', forView);
});
}
function userDetails(req, res, next) {...}
expressApp.use(shopConfig);
expressApp.use(userDetails);
...
Responsive design (lots of iterations)
Revamped editorial system
Displaying Hi-Res content
No more legacy DB access \o/
Way better logging/monitoring
A nightmare to debug deep inside IIS, on production under load only
Upgraded iisnode
<action type="Rewrite" url="server.js?rewrittenFrom={REQUEST_URI}" />
<iisnode nodeProcessCountPerApplication="4" ../>
function myCallback(err, res) { ... }
throw new Error('lol');
Loss of context if error is not thrown by your own code
function uncaughtErrorMiddleware(req, res, next) {
var reqDomain = domain.create();
reqDomain.name = 'request';
reqDomain.traceId = req.traceId;
reqDomain.on('error',
createUncaughtErrorHandler(serverDomain, req, res));
reqDomain.run(next);
}
Deprecated :(
Zones? Async Listener?
Simplicity / Malleability
Productive if you know what architecture you're aiming for
Great tooling
npm package for everything
One language everywhere - no context switch
Cross-platform (linux dev environment)
redis:
image: redis
ports:
- "6379:6379"
sentinel:
image: joshula/redis-sentinel
links:
- redis
ports:
- "26379:26379"
command: sentinel monitor session redis 6379 1 --sentinel monitor objectcache redis 6379 1 -- sentinel down-after-milliseconds session 5000 -- sentinel down-after-milliseconds objectcache 5000
(Yeah, yeah, it is coming to windows..)
Should have taken more screenshots...
Old project <3 ?
Many more tooling / deployment choices now