ByAngelica Jade Bastién,
a New York and Vulture critic covering film and pop culture
The show is at once frustrating and fascinating in how it fails to disrupt the conventions of a potent pop culture archetype.
Photo: Warrick Page/Prime Video
The story of Andrea “Dre” Greene — the deeply lonely whirlwind of a lead played by Dominique Fishback in Swarm — ends in the way of many onscreen madwomen before her: consumed by delusion. She’s Amy Dunne in Gone Girl, shaking her platinum-blonde bob from her line of vision after slitting the throat of a former paramour. She’s Isabelle Adjani in 1981’s Possession, contorting and flinging groceries into a glorious mess that feels like divine ritual. She’s Norma Desmond in Sunset Boulevard, slinking down the grand staircase of her home, beckoning the camera before devolving into a fantasy of a future that won’t arrive. She’s as unruly with desire as Isabelle Huppert in The Piano Teacher, a film name-checked by the creators of Swarm as a direct inspiration. The madwoman is an archetype that crosses time and national origins, conventions of class and flavors of womanhood. The madwoman is revelatory and reflective, untamed and yearning, and Dre is, too. But she is something else that madwomen have rarely been in cinema or the American imagination: Black.
Created by showrunner Janine Nabers with an assist from her Atlanta boss Donald Glover, Swarm presents a thinly veiled rendition of madness in the age of standom. “We can be crazy; we can be serial killers, too,” Nabers professed in interviews ahead of her show’s release, the “we” referring to Black women who tend to be more often depicted as the “therapist, or a funny best friend, or someone looking for love, or a teacher” on screen. And so she co-created Dre as an obsessive fan of Ni’Jah (an obvious avatar for Beyoncé played by Nirine S. Brown), whose sanity is held together by bubblegum and a prayer before being entirely obliterated when her former foster sister/object of psychosexual obsession, Marissa (Chloe Bailey), commits suicide. Dre had purchased tickets for the two of them to see Ni’Jah’s Festival tour, an event that cuts closer to Marissa’s life than she imagined: Festival is the Lemonade of Swarm’s universe, and Marissa too was feeling the pain of being cheated on. (The plot is pulled from a real-life rumor, now debunked, that a woman named Marissa killed herself after the release of Lemonade.) But Dre arrives too late, the suicide of her best friend fracturing her mind and leading to a vengeful, violent road trip in the name of Marissa, or Ni’Jah, or most likely both.
Swarm aims to be a psychological character study, a treatise on the nature of parasocial relationships that remixes horror and satire. Fishback consistently outplays the scripts from Nabers and her collaborators, as Dre murders not only Marissa’s unfaithful boyfriend but a collection of people whom Dre deems toxic toward Ni’Jah online and off, some premeditated and others utterly random. Consumption drives her madness and renders her incapable of connecting to the actual world around her. Swarm’s camera undergirds this point, rendering Dre’s vicious outbursts with cool curiosity, asking us to gawk at her rather than empathize. Fishback, meanwhile, never condescends or looks down upon Dre. Through a wavering voice, hard-won tears, and jittering physical force, she lets us into her character’s private self — the hurt girl hidden within the rampaging serial killer. She attempts to bend and break the rules governing the madwomen who came before her, but can never fully and consistently shake the stereotypes upon which her story is built.
In her monumental book Black Madness::Mad Blackness, Theri Alyce Pickens poses and answers a series of questions that tie together racial interrogations, disability theory, and literary criticism. What should a Black madwoman reveal? How should she speak to the intersecting concerns of race and mental illness, femininity and power? “Reading and theorizing mad Blackness and Black madness demands an elliptical openness that refuses linearity and progression toward traditional conclusions,” Pickens writes. “To my mind, the mad Black/Black mad subject is not simply standing at an intersection but also actively changing it.” Pickens realizes that Black madness and the mad Black are radically disruptive. Or at least can be, should be. The presence of Blackness isn’t inherently revolutionary though. The problem with Swarm is that it slots a Black woman into well-tread cinematic space and ticks the narrative boxes, traipsing her across America to uncover nothing but its very id.
Dre plunges into madness almost immediately, when in the inaugural episode, she smashes Marissa’s boyfriend’s body repeatedly with a himalayan salt lamp until blood streaks her visage. She immediately fumbles into a refrigerator, heaving to the point of hyperventilating. With her hand she spoons pie into her mouth, bits of food tumbling from her lips. Dre doesn’t just eat, she gorges. Two episodes later, she’s still voracious. Dre connives her way into a ritzy afterparty with Ni’Jah in attendance, where a tray of ripe plums rolls in front of her. She devours them, her eyes never leaving Ni’Jah. A brief sliver of reality cuts into the delusion — Dre’s mouth agape, teeth poised near Ni’Jah’s cheek, before the bite that becomes internet fodder. Intimacy becomes a spectacle.
Womanhood isn’t a project afforded to Black women, which makes the exaltation of Ni’Jah that much more complicated, that much more of a necessary balm for Dre. Is it any wonder she turns to the intimate, feminine excess of Ni’Jah for connection in a culture as lonely and broken as this? By episode four, Dre has met cult leader Eva (Billie Eilish, bringing a barbed warmth to the role) and been welcomed into her private sanctum — used for blackmail masked as emotionally exhaustive therapy. There, Dre reveals a crucial memory from before all of this: her biological grandmother upset by her unruliness over a glass of spilled milk. As Dre mines the murky depths of this memory, she remembers it wasn’t milk at all but blood. Whose did she spill? The scenes between Dre and Eva electrify, the two performances perfectly calibrated to tease out the contours of each character. By episode five, Dre has returned to Houston with a density to her delusions that leads her to the attic that was once her bedroom, a memorial for Marissa aglow with lights and mementos, her former foster father pounding on the door before blowing it apart with a shotgun. She becomes a familiar vision, played out by Rochester’s wife in Charlotte Bronte’s Jane Eyre and powerfully explored as a trope in Sandra Gilbert and Susan Gubar’s iconic 1979 literary study, The Madwoman in the Attic.
It takes until Swarm’s penultimate episode, which exists in the form of a true-crime documentary, to find any semblance of disruption. We’re introduced to the maternally warm but cunning Major Det. Loretta Greene (Heather Simms, acting with blistering charisma), who is piecing together Dre’s past and her violent actions in pursuit of an arrest. In a scene with Dre’s former caseworker, Roberta Kirby (a forthright Bonita Elery), the series finally drops a crucial key to the experiences of madness for Black women: that to be deemed mad or display madness as a Black woman immediately brings carceral forces down upon you. When Loretta throws out the fact that Roberta’s a mandated reporter and the white cameraman pushes back, asking what she’s hiding, Roberta chooses to tell them about themselves. “Oh, I see. You want me to tell you her sob story. That she was touched or something? That she saw her mother murdered and from then on a screw was loose? … The only reason you want Andrea’s sob story is so you can absolve yourselves. You need there to be a reason that she’s messed up. That girl was lonely and she was looking for acceptance … I’m not gonna help you judge her for something you couldn’t begin to understand.” This spotlights a dynamic that defines the experience of mental illness for Black women: wishing for an intervention that will never arrive.
And for Dre, it doesn’t.The finale, “Only God Makes Happy Endings”, written by Nabers with direction by Adamma Ebo, takes place in June 2018. Dre is living in Atlanta. As a Syd song hums, we see that Dre has gone full stud, with a closely cropped afro, baggy clothes, and a new walk laced with confidence. She comes across Rashida (Kiersey Clemons), a privileged and beautiful student who is helping her exceedingly drunk white roommate, Becca (Meg Barlowe). Dre offers Rashida a ride she harshly rebuffs before realizing she doesn’t have the option of a rideshare, given Becca’s state. Rashida accepts the offer and a flirtation sparks. But when they arrive at her apartment, Rashida switches off a Ni’Jah song and utters four words that stamp an expiration date on the romance beginning to bloom: “I fucking hate Ni’Jah.”
What follows is a relationship pockmarked by Dre’s elisions — Rashida works two jobs to support them both, never questioning why Dre doesn’t have money or why she has to habitually switch the car she drives. Dre gets to meet Rashida’s exceedingly well-off, wonderful, caring parents, played by Cree Summer and Norm Lewis. When Dre reveals her parents are dead, her hands are held by Rashida on one side and Rashida’s mother on the other. Fishback’s downcast eyes communicate a friction; she’s never been in a family that genuinely cares for her. The series is at its best when granting Fishback extreme close-ups that allow us to chart the minute shifts across her face. The softness of her features adds a wonderful contradiction to the sharpness and harshness of everything else.
Soon after, Dre decides to spend beaucoup bucks on Ni’Jah tickets to “surprise” Rashida for her birthday. Rashida doesn’t hold back in her response, “Are you dumb? Let’s make this clear, I don’t like Ni’Jah and you know that … You’re a selfish asshole.” Our lead snaps, and for a moment, the snap is fascinating. Her madness marks a loss of self and identity, a total disconnection from her present circumstances. Hands around Rashida’s throat, Dre straddles her on the couch and strangles with fierce conviction. Dre’s murders up until this point have all been blunt force trauma or a bullet to the head. In this scene, there’s an unspoken intimacy. Dre can’t look at Rashida as she kills her. Her gaze drifts closer to the camera’s eyeline, tears stream down her face. “I love you. I love you. I wanted to share Ni’Jah with you because I love you,” Dre softly whispers. Cut to Dre burning Rashida’s body in the wilderness and panicking when she realizes the Ni’Jah tickets were in Rashida’s pocket. Pure delusional fantasy takes over: Dre goes to the concert desperate to find tickets. (Wouldn’t she have a digital copy?) Dre kills a scalper in his car for a ticket. We see Dre in the cool blue light of the stadium, front row, her mouth agape and eyes glittering as she witnesses the glory of her object of obsession.
Swarm never fully connects the dots between Dre’s sexuality and the forces that put her in Ni’Jah’s thrall. A crucial failure of the series is its inability to fully consider why Black women like Dre turn to paragons of femininity and find a sense of home therein. Because the writers lean so heavily on Beyoncé iconography to fill in the gaps of their story, we don’t get a full understanding of Ni’Jah, either. She’s a question mark, not an answer. A backdrop to Dre bypassing security and stumbling onstage as if in a trance, disrupting the sequined gyrations of dancers and hair-flinging elegance of the icon herself. Security captures her before she can even touch her queen: “Please, Ni’Jah. Please!” “Let her go,” Ni’Jah responds. When Ni’Jah steps into the light, Marissa’s face has been sloppily superimposed. Dre holds Ni’Jah tight as they walk to the car afterward. Dre is lost in her delusion, with no recourse. Resting her head upon Marissa-as-Ni’Jah’s bosom, Dre welcomes a happy ending that will in fact never come.
It isn’t that I want to witness Dre facing carceral repercussions. It isn’t that I want to see the reality that Dre has broken from. What I want — and what the narrative needs — is a reformation of expectation: a way to clearly foreground Dre’s emotional life instead of making the stakes so opaque. The madwoman has the opportunity to be a disruptive force in how we understand femininity, disability, and power, but more often than not she is the opposite, a cautionary tale of what happens when women overstep the bounds of socially acceptable presentation. Dre is consumed by her very unruliness, unable to escape or reckon with the strictures on her life. She’s not a disruption of the status quo but its reaffirmation.
By submitting your email, you agree to our
Terms and Privacy Notice
and to receive email correspondence from us. This site is protected by reCAPTCHA and the Google
Privacy Policy and
Terms of Service apply.
or
Already a subscriber?
What is your email?
This email will be used to sign into all New York sites. By submitting your email, you agree to our Terms and Privacy Policy and to receive email correspondence from us.
Password must be at least 8 characters and contain:
Lower case letters (a-z)
Upper case letters (A-Z)
Numbers (0-9)
Special Characters (!@#$%^&*)
This password will be used to sign into all New York sites. By submitting your email, you agree to our Terms and Privacy Policy and to receive email correspondence from us.
You’re in!
As part of your account, you’ll receive occasional updates and offers from New York, which you can opt out of anytime.
or
Already a subscriber?
What is your email?
This email will be used to sign into all New York sites. By submitting your email, you agree to our Terms and Privacy Policy and to receive email correspondence from us.
Password must be at least 8 characters and contain:
Lower case letters (a-z)
Upper case letters (A-Z)
Numbers (0-9)
Special Characters (!@#$%^&*)
This password will be used to sign into all New York sites. By submitting your email, you agree to our Terms and Privacy Policy and to receive email correspondence from us.
You’re in!
As part of your account, you’ll receive occasional updates and offers from New York, which you can opt out of anytime.
Already a subscriber?
Already a subscriber?
`;
// integrate Sub(x) scripts and elements
if (hostname !== 'subs.nymag.com') { // do not integrate on this subdomain
document.head.appendChild(trackingScript);
document.body.insertAdjacentHTML('beforeend', subXAnimationElements);
}
There was an error processing the request. Please try again later."}).catch(e=>console.error("Error verifying email: ",e)))(r.querySelector(".content"),o.bannerCTAVerification)})):(l.remove(),s.remove()),o.dismissable||n.remove(),o.useAlertIcon||a.remove(),r.classList.add("show"),n.addEventListener("click",()=>{u(),r.classList.remove("show")})}else r.remove()}});
}, {"1":1,"6":6,"12":12,"35":35,"40":40}];
window.modules["global-nav.client"] = [function(require,module,exports){"use strict";const dom=require(3),auth=require(12),signInButton=dom.find(".user-signin"),signOutButton=dom.find(".user-signout"),globalNav=dom.find('[class^="global-nav"]'),body=dom.find("body"),dropdownItems=dom.findAll(".dropdown-wrap"),gtm=require(1),appendLandingPageParams=require(136),pageUri=require(124).getPageUri(),subscriptionPromoLinks=dom.findAll(".persist-params"),searchString=window.location.search||"";function closeDropdowns(e){let n=globalNav.querySelectorAll(".dropdown.open");dropdownItems.forEach(function(t){let o=t.querySelector(".dropdown");!n||t.contains(e.target)&&27!==e.keyCode||o.classList.remove("open")})}function gtmSendReport(e,n,t){let o={eventCategory:"ecommerce",eventAction:"componentClick",brand:e,dimension23:"global-nav",list:pageUri,pageZone:"header",variant:"nav-link"};"global-nav-link"===t&&(o.eventLabel=n.href),gtm.reportNow(o)}function updateElementTargetUrlsIfQueryStrings(e){if(searchString){const n=new URLSearchParams(searchString);let t=e.href;if(t.includes("?")){const o=t.split("?"),i=new URLSearchParams(o[1]);for(let e of n.entries())i.set(e[0],e[1]);t=`${o[0]}?${i.toString()}`,e.href=t}else e.href=`${t}?${n.toString()}`}}function init(e){const n=e.querySelectorAll(".to-landing-page");window.addEventListener("auth:init",()=>{signInButton.addEventListener("click",function(e){e.preventDefault(),auth.showEmbeddedLoginFlow("top navigation")}),signOutButton.addEventListener("click",function(e){e.preventDefault(),gtmSendReport("Sign Out",e.target,"user-info-link"),auth.logout()}),auth.isAuthenticated()&&e.classList.add("signed-in"),auth.isSubscriber()&&e.classList.add("subscribed"),e.querySelectorAll(".user-link").forEach(e=>{e.classList.add("active")}),subscriptionPromoLinks.forEach(e=>{updateElementTargetUrlsIfQueryStrings(e)}),appendLandingPageParams(n)})}dropdownItems.forEach(function(e){e.addEventListener("click",function(){e.querySelector(".dropdown").classList.toggle("open")})}),body.addEventListener("click",closeDropdowns),document.addEventListener("keydown",closeDropdowns),globalNav.addEventListener("click",function(e){let n=e.target;n.classList.contains("global-nav-track")&>mSendReport(n.text,n,"global-nav-link")}),module.exports=init;
}, {"1":1,"3":3,"12":12,"124":124,"136":136}];
window.modules["aaa-module-mounting.legacy"] = [function(require,module,exports){"use strict";const _pickBy=require(221),_each=require(408),Fingerprint2=require(407),DS=require(406),Eventify=require(246);function registerGlobals(){window.DS=DS,window.Eventify=Eventify,window.Fingerprint2=Fingerprint2,DS.value("Eventify",Eventify),DS.value("Fingerprint2",Fingerprint2),DS.value("$document",window.document),DS.value("$window",window)}function mountDollarSliceComponents(){DS.service("components",["$document","$module",function(e,n){var o=_pickBy(n.definitions,e=>e.providerStrategy===n.providers.controller),r=Object.keys(o);function t(e){return o=>{try{n.get(e,o)}catch(e){logMountError(o,e)}}}_each(r,n=>{var o=e.querySelectorAll('[data-uri*="/_components/'+n+'/"]'),r=e.querySelectorAll('[data-uri$="/_components/'+n+'"]');_each(o,t(n)),_each(r,t(n))}),this.components=r}]),DS.get("components")}function logMountError(e,n){const o=e.outerHTML.slice(0,e.outerHTML.indexOf(e.innerHTML));console.error("Error attaching controller to "+o,n)}registerGlobals(),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>{mountDollarSliceComponents()}):mountDollarSliceComponents();
}, {"221":221,"246":246,"406":406,"407":407,"408":408}];
window.modules["ads.legacy"] = [function(require,module,exports){"use strict";const _map=require(118),_forEach=require(107),_isString=require(268),_intersectionWith=require(409),_isEqual=require(274),_each=require(408),_debounce=require(182),_sortBy=require(205),page=require(124),visit=require(114);DS.service("adService",["Eventify","$cid","$document","$window",function(e,t,a,i){var o,n,s,r,d,c,u,l,g={},p=this,h=[],f=visit.getQueryParamsObject(["utm_campaign"]),m=document.querySelector('script[data-type="ad-a9"]'),b=[],w=!1,v=[],y=document.querySelector('script[data-name="ad-doubleverify"]');document.querySelector('script[data-name="concert-ads"]')||(i.NYM={},i.NYM.analytics={},i.NYM.analytics.adStartTime=i.performance.now(),i.googletag=i.googletag||{},i.googletag.cmd=i.googletag.cmd||[],u=i.googletag,(m||y)&&(i.googletag.cmd=i.googletag.cmd||[],i.googletag.cmd.push(function(){i.googletag.pubads().disableInitialLoad()})),m&&(l=i.setInterval(function(){void 0!==window.apstag&&void 0!==window.apstag.timeout&&(i.clearInterval(l),window.apstag.cleared=!0,l=null)},10),setTimeout(function(){l&&(i.clearInterval(l),i.googletag.pubads().refresh(),window.apstag||console.log("MESSAGE: Timeout for A9 load exceeded, aborting"))},500)),y&&(b.push(new Promise(function(e){w?e():v.push(e)})),c=i.setTimeout(T,2500)),o=function(e){var t,a,o=e.data,n=[];return o.loaded?e:(o.loaded=!0,t=null,(t=o.sizes?u.defineSlot(o.name,o.sizes,o.id).addService(u.pubads()):u.defineOutOfPageSlot(o.name,o.id).addService(u.pubads())).setTargeting("adid",o.id),f.hasOwnProperty("utm_campaign")&&t.setTargeting("utmcamp",f.utm_campaign),a=p.getAdCount(o.label),t.setTargeting("label",o.label+"_"+o.site+"-"+a),u.display(o.id),u.pubads().addEventListener("slotOnload",function(){i.NYM.analytics.firstAdLoadTime||(i.NYM.analytics.firstAdLoadTime=i.performance.now(),i.NYM.analytics.firstAdLoadLabel=e.data.label)}),n=_(o),Promise.all(b).then(function(){n?window.apstag&&window.apstag.cleared?window.apstag.fetchBids({slots:[n],timeout:window.apstag.timeout},function(){u.cmd.push(function(){window.apstag.setDisplayBids(),u.pubads().refresh([t],{changeCorrelator:!1})})}):y&&u.pubads().refresh([t],{changeCorrelator:!1}):u.pubads().refresh([t],{changeCorrelator:!1})}),e.slot=t,e)},n=function(e){var a,i,o,n=t(),s=e.getAttribute("data-name"),r=e.getAttribute("data-sizes"),d=e.getAttribute("data-label"),c=e.getAttribute("data-site");n=e.id,r&&r.length?(r=r.split(","),a=[],_map(r,function(e){e=e.split("x"),i=parseInt(e[0]),o=parseInt(e[1]),a.push([i,o])})):(e.classList.add("oop"),a=!1),this.data={id:n,name:s,sizes:a,loaded:!1,label:d,site:c},g[n]=this},r=function(e){u.cmd.push(function(){var t=o(e);g[e.data.id]=t})},s=function(e){var t=[];e.slot?(t=_(e))&&window.apstag&&window.apstag.cleared&&window.apstag.fetchBids({slots:[t],timeout:window.apstag.timeout},function(){u.cmd.push(function(){window.apstag.setDisplayBids(),u.pubads().refresh([e.slot],{changeCorrelator:!1})})}):e&&r(e)},u.cmd.push(function(){var e,t,o,n=page.getMeta("article:tag"),s=page.getMeta("author"),r=i.location.href,d=(e=a.head.querySelector(".head-gtm"),t=a.body.querySelector(".gtm"),e&&"top"===e.getAttribute("data-gtm")?"gtmtop":t&&"bottom"===t.getAttribute("data-gtm")?"gtmbottom":"");o=[],_forEach([n,s,d],function(e){_forEach(e.split(","),function(e){(e=e.trim().toLowerCase().replace(/\s/g,"-").replace(/\'|\’/g,"")).length&&o.push(e)})}),u.pubads().setTargeting("kw",o),u.pubads().setTargeting("entry_group",o),r=r.slice(r.lastIndexOf("/")+1),u.pubads().setTargeting("pn",r),u.companionAds().setRefreshUnfilledSlots(!0),u.pubads().enableAsyncRendering(),u.enableServices()}),this.load=r,this.create=function(e){return new n(e)},this.refresh=function(e){var t;_isString(e)?(t=this.getById(e),s(t)):s(e)},this.remove=function(e){var t=e.data.id;a.getElementById(t).innerHTML=""},this.getAdCount=function(e){var t,a=0,i=Object.keys(g);return _each(i,function(i){(t=g[i]).data.loaded&&t.data.label===e&&a++}),a},this.getById=function(e){return g[e]},d=_debounce(function(){var e={TopLeaderboard:1,RightColTopMPU:2,outOfPage:99,"homepageTakeover/TopLeaderboard":1},t=_sortBy(h,function(t){return e[t.data.label]||10});_forEach(t,function(e){return e.data.sizes?r(e):i.setTimeout(function(){r(e)},2e3)}),y&&window.PQ.cmd.push(()=>{try{window.PQ.loadSignals(["ids","bsc","vlp"],T)}catch(e){T(),console.error(`There has been an error loading Double Verify signals: ${e}`)}}),h=[]},10),this.addToPageLoadQueue=function(e){h.push(e),d()});function _(e){var t,a=e.sizes;return a=_intersectionWith(a,[[970,250],[970,90],[728,90],[300,600],[300,250],[320,100],[320,50]],_isEqual),e.sizes&&e.sizes.length&&(t={slotID:e.id,sizes:a,slotName:e.label}),t}function T(){i.clearTimeout(c),w=!0,_forEach(v,function(e){e()})}}]);
}, {"107":107,"114":114,"118":118,"124":124,"182":182,"205":205,"268":268,"274":274,"408":408,"409":409}];
window.modules["cid.legacy"] = [function(require,module,exports){"use strict";DS.service("$cid",function(){var r=Math.floor(100*Math.random());return function(){return"cid-"+ ++r}});
}, {}];
window.modules["client.legacy"] = [function(require,module,exports){"use strict";require("cid.legacy"),require("ads.legacy"),require("facebook.legacy"),require("aaa-module-mounting.legacy");
}, {"cid.legacy":"cid.legacy","aaa-module-mounting.legacy":"aaa-module-mounting.legacy","ads.legacy":"ads.legacy","facebook.legacy":"facebook.legacy"}];
window.modules["facebook.legacy"] = [function(require,module,exports){"use strict";DS.service("facebook",[function(){this.fb=function(i){window.FB&&window.FB[i].apply(this,Array.prototype.slice.call(arguments,1))}}]);
}, {}];
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o typeof key === 'string' && key.match(/\.legacy$/)).forEach(key => window.require(key));
}
function tryToMount(fn, el, name) {
try {
fn(el); // init the controller
} catch (e) {
const elementTag = el.outerHTML.slice(0, el.outerHTML.indexOf(el.innerHTML));
console.error(`Error initializing controller for "${name}" on "${elementTag}"`, e);
}
}
/**
* mount client.js component controllers
*/
function mountComponentModules() {
Object.keys(window.modules).filter(key => typeof key === 'string' && key.match(/\.client$/)).forEach(key => {
let controllerFn = window.require(key);
if (typeof controllerFn === 'function') {
const name = key.replace('.client', ''),
instancesSelector = `[data-uri*="_components/${name}/"]`,
defaultSelector = `[data-uri$="_components${name}"]`,
instances = document.querySelectorAll(instancesSelector),
defaults = document.querySelectorAll(defaultSelector);
for (let el of instances) {
tryToMount(controllerFn, el, name);
}
for (let el of defaults) {
tryToMount(controllerFn, el, name);
}
}
});
}
// Make sure that a `window.process.env.NODE_ENV` is available in the client for any dependencies,
// services, or components that could require it
// note: the `` value is swapped for the actual environment variable in /lib/cmd/compile/scripts.js
window.process = window.process || {};
window.process.env = window.process.env || {};
if (!window.process.env.NODE_ENV) {
window.process.env.NODE_ENV = '';
}
// note: legacy controllers that require legacy services (e.g. dollar-slice) must
// wait for DOMContentLoaded to initialize themselves, as the files themselves must be mounted first
mountLegacyServices();
mountComponentModules();
// ]]