On Github actionshrimp / net-to-node-presentation
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