Skip to content
CMO & CTO
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

  • Digital Experience
    • Experience Strategy
    • Experience-Driven Commerce
    • Multi-Channel Experience
    • Personalization & Targeting
    • SEO & Performance
    • User Journey & Behavior
  • Marketing Technologies
    • Analytics & Measurement
    • Content Management Systems
    • Customer Data Platforms
    • Digital Asset Management
    • Marketing Automation
    • MarTech Stack & Strategy
    • Technology Buying & ROI
  • Software Engineering
    • Software Engineering
    • Software Architecture
    • General Software
    • Development Practices
    • Productivity & Workflow
    • Code
    • Engineering Management
    • Business of Software
    • Code
    • Digital Transformation
    • Systems Thinking
    • Technical Implementation
  • About
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

and the Shape of the Frontend

Posted on June 16, 2014 By Luis Fernandez

We did not wake up one morning and find the web changed. We just shipped one more script tag, then another, and one day the browser was our app runtime.

notes from my repo

2012 and the Shape of the Frontend: a ground level story of the rise of JavaScript, why teams leaned into it, and the lessons that still hold up when the build breaks at 1 am.

From sprinkles to full apps

Two years ago most of us still called JavaScript a sprinkle. A light layer on top of server templates. A dropdown here, a modal there. Then the feature list kept growing. Product wanted offline feel. Design wanted native like transitions. Marketing wanted richer tracking. Suddenly we were writing state machines in the browser and pushing templates to users over the wire.

That season put names in our daily standup: Backbone for structure, AngularJS for templates and data binding, Ember for ambitious apps, and a new idea called React that treats the UI like a function of state. We paired that with Node.js on the server so the same language could live end to end. It felt scrappy and it worked. The browser turned into a serious app host, and our teams followed.

At the same time the mobile web forced our hand. Touch targets, slow radios, and small CPUs punished sloppy code. We learned to ship less, cache more, and respect the critical path. Responsive design went from novelty to table stakes. The message was clear. JavaScript gives power, performance sets the budget.

The tooling moment

Our repos picked up new neighbors. package.json. Gruntfile.js or a shiny gulpfile.js. bower.json for the front end bits. Tests under Karma. Lint rules that protect our future selves. Build steps that bundle, minify and fingerprint. It felt like overhead at first. Then a teammate joined and ran npm install and shipped on day one. That is when it clicked.

We also ran into the sharp edges. Circular deps at 5 pm. A Require config that swallowed the afternoon. A broken shrinkwrap in the middle of a deploy. The lesson is steady: keep modules tiny, keep your dependency graph simple, write down the rules in the repo, and automate everything twice. Humans forget, scripts do not.

Search and sharing forced more learning. Crawlers do not wait for your app to boot. We used server rendered shell pages, pre render services, or simple snapshots to give bots real HTML. Push state is great. Empty divs are not. Progressive enhancement still pays rent.

Deep dive one: modules and loading

Most teams I know landed in one of two camps. AMD with RequireJS or CommonJS with Browserify. AMD loads in the browser with async definitions. CommonJS feels like Node and gets bundled for the browser. Pick the one your team reads without frowning and stick to it.

// AMD with RequireJS
define(['jquery', 'views/todo'], function($, TodoView) {
  return function boot() {
    var view = new TodoView($('#app'));
    view.render();
  };
});
// CommonJS with Browserify
var $ = require('jquery');
var TodoView = require('./views/todo');

module.exports = function boot() {
  var view = new TodoView($('#app'));
  view.render();
};

For apps with many routes, AMD can split code per route out of the box. If you want bundles with CommonJS, add Browserify plugins or split points and build multiple bundles. Either way, aim for fast first paint, then load the rest when needed.

// RequireJS: load route bundle on demand
require(['routers/dashboard'], function(startDashboard) {
  startDashboard();
});

// Browserify: simple multi bundle via factor-bundle
// cli example
// browserify entry-a.js entry-b.js -p [ factor-bundle -o bundle-a.js -o bundle-b.js ] -o common.js

Bonus trick. Keep a small core bundle for boot and shared deps, then lazy load heavy features. Your users get pixels fast and your graphs get greener.

Deep dive two: frames, paint, and jank

The browser wants to hit 60 frames per second. That gives you about 16 milliseconds per frame for everything. JavaScript, style, layout, paint. Blow that budget and you feel it. The fix is to separate read and write, batch work, and give animations to CSS when you can.

// Measure then mutate to avoid layout thrash
function moveBox(el, x, y) {
  // measure once
  var rect = el.getBoundingClientRect();

  window.requestAnimationFrame(function() {
    el.style.transform = 'translate(' + x + 'px,' + y + 'px)';
  });
}

// Event delegation to keep listeners light
document.body.addEventListener('click', function(e) {
  if (e.target.matches('.todo-item')) {
    // work here
  }
});

Watch your CSS too. Expensive selectors and layout triggers sneak in. Stick to class selectors. Promote moving elements to their own layer with transform and will-change when supported. Measure with DevTools, do not guess. The timeline and paint stats do not lie.

Deep dive three: tests and delivery without drama

Teams ship calm when tests run fast and close to the browser. My current stack pairs Karma with Jasmine or Mocha. Run it in Chrome for speed and on Phantom for headless checks. Wire it to Travis CI and fail builds early. Then minify, add source maps, and fingerprint assets so caches work for you.

// package.json scripts
{
  "scripts": {
    "start": "grunt serve",
    "test": "karma start --single-run",
    "build": "grunt build",
    "ci": "npm run test && npm run build"
  }
}
// tiny karma.conf.js sketch
module.exports = function(config) {
  config.set({
    frameworks: ['jasmine', 'requirejs'],
    files: [
      { pattern: 'app/**/*.js', included: false },
      { pattern: 'test/**/*.spec.js', included: false },
      'test/test-main.js'
    ],
    browsers: ['Chrome'],
    reporters: ['dots'],
    singleRun: true
  });
};

For builds, Grunt and Gulp both deliver. The exact runner matters less than repeatable tasks. Uglify for scripts, clean CSS with Sass plus autoprefixer, and a rev step for cache busting. Keep an eye on the total weight. Every kilobyte on 3G feels like a tax.

What the shift taught me

JavaScript earned its seat not because it is pretty, but because it is close to the user. That is the lesson. Build where the user feels it. Use the framework your team can debug at 2 am. Favor small modules, clear contracts, and tests that catch you when you fall. Keep your first paint lean. Respect the back button. Render something useful even if scripts fail.

There is a lot of noise out there. New libs every week. Exciting talks. It is fun. Ship anyway. Pick a stack, write it down, and keep it boring for a while. Learn one thing deeply. Maybe it is Angular with UI Router. Maybe Backbone with Marionette. Maybe you try React and see if its mental model fits your team. The details change. The habits do not.

Looking back, that push in 2012 was not about fashion. It was about owning the experience from tap to pixel. Today we are still tuning that idea. The web remains open, quirky, and fast enough if we respect the budget. Keep the focus on the people using your work and the rest shakes out.

General Software Software Engineering

Post navigation

Previous post
Next post
  • Digital Experience (94)
    • Experience Strategy (19)
    • Experience-Driven Commerce (5)
    • Multi-Channel Experience (9)
    • Personalization & Targeting (21)
    • SEO & Performance (10)
  • Marketing Technologies (92)
    • Analytics & Measurement (14)
    • Content Management Systems (45)
    • Customer Data Platforms (4)
    • Digital Asset Management (8)
    • Marketing Automation (6)
    • MarTech Stack & Strategy (10)
    • Technology Buying & ROI (3)
  • Software Engineering (310)
    • Business of Software (20)
    • Code (30)
    • Development Practices (52)
    • Digital Transformation (21)
    • Engineering Management (25)
    • General Software (82)
    • Productivity & Workflow (30)
    • Software Architecture (85)
    • Technical Implementation (23)
  • 2025 (12)
  • 2024 (8)
  • 2023 (18)
  • 2022 (13)
  • 2021 (3)
  • 2020 (8)
  • 2019 (8)
  • 2018 (23)
  • 2017 (17)
  • 2016 (40)
  • 2015 (37)
  • 2014 (25)
  • 2013 (28)
  • 2012 (24)
  • 2011 (30)
  • 2010 (42)
  • 2009 (25)
  • 2008 (13)
  • 2007 (33)
  • 2006 (26)

Ab Testing Adobe Adobe Analytics Adobe Target AEM agile-methodologies Analytics architecture-patterns CDP CMS coding-practices content-marketing Content Supply Chain Conversion Optimization Core Web Vitals customer-education Customer Data Platform Customer Experience Customer Journey DAM Data Layer Data Unification documentation DXP Individualization java Martech metrics mobile-development Mobile First Multichannel Omnichannel Personalization product-strategy project-management Responsive Design Search Engine Optimization Segmentation seo spring Targeting Tracking user-experience User Journey web-development

©2025 CMO & CTO | WordPress Theme by SuperbThemes