What is Magento RequireJS?
Magento RequireJS is the AMD (Asynchronous Module Definition) JavaScript loader Magento 2 ships since 2.0 as its storefront and admin JS dependency manager. Every module declares its module map in view/frontend/requirejs-config.js; Magento merges all enabled-module configs into a single file at runtime, and code calls require([…]) which resolves through that merged map. Required in Luma and the admin; removed entirely in Hyvä, which uses native ES modules plus Alpine.js.
- Version RequireJS 2.3.x, bundled in Magento 2.0+
- Config view/frontend/requirejs-config.js per module, merged at runtime
- Status Required in Luma + admin; removed entirely in Hyvä (native ES modules)
Five steps from module config to executing AMD callback
RequireJS is not magic, Magento walks every module, merges configs, and hands control to RequireJS via a documented bootstrap. Here is the wiring, end to end.
01Each module ships a requirejs-config.js with its JS module map
A Magento module declaring custom storefront JS drops a config file at Vendor/Module/view/frontend/requirejs-config.js (or view/adminhtml/requirejs-config.js for the admin). That file exports a single var config = { map: {...}, paths: {...}, deps: [...], shim: {...} } block. map aliases module names (Vendor_Module/js/widget → physical path); paths rewrites paths; deps declares modules to auto-load on page boot; shim wraps legacy non-AMD libraries so RequireJS can still pull them in.
02Magento walks every enabled module and merges configs into one file
At storefront boot Magento’s Magento\RequireJs\Model\FileManager iterates the ComponentRegistrar list, reads every enabled module’s requirejs-config.js, and concatenates them into a single requirejs-config.js served at pub/static/frontend/<theme>/<locale>/requirejs-config.js. The merged file is cached on disk, any change to a per-module config needs a static-content rebuild before the storefront sees it (see [[feedback_static_content_force_rebuild]]).
03Templates hand control to RequireJS via x-magento-init
A .phtml template that wants to load custom JS emits <script type="text/x-magento-init">{"*": {"Vendor_Module/js/component": {"config":"value"}}}</script>. Magento_Ui’s mage/apply/main.js bootstrap scans the DOM for these script tags after RequireJS loads, then calls require(["Vendor_Module/js/component"], function(c){ c(config, selector); }). The selector "*" means “page-wide”; you can also target a specific element via "#my-element": {...} or use data-mage-init on a DOM node directly.
04RequireJS resolves the module name to a static file URL and fetches it
The merged config tells RequireJS that Vendor_Module/js/component resolves to pub/static/frontend/<theme>/<locale>/Vendor_Module/js/component.js. The file is requested with an async <script> tag, parsed as an AMD module, it must be wrapped in define(['jquery', 'ko', 'mage/translate'], function($, ko, $t){ ... }). RequireJS recurses into each declared dependency, caching every resolved module, and once all dependencies are loaded the factory function runs.
05The AMD factory’s return value is wired to the calling block
Whatever the AMD factory returns, typically a Component constructor, a jQuery widget factory, or a KnockoutJS ViewModel class, is what x-magento-init hands back. For UI Components, Magento instantiates the class with the JSON config; for jQuery widgets, Magento calls $(selector).widgetName(config); for ViewModels, Magento binds the instance via ko.applyBindings. The component then takes over: it can call require() recursively for lazy dependencies, fire AJAX, render templates, and bind UI events.
Four scenarios where you cannot avoid RequireJS
On a Luma storefront, these four scenarios all route through RequireJS. Skip the wiring and you get loose script tags that break under bundling, FPC, or CDN edge caches.
Adding any custom JS to a Luma storefront page
On a Luma storefront, custom JS goes through RequireJS, that’s not optional, it’s how Magento expects to wire frontend behaviour. Declare your module’s entry point in view/frontend/requirejs-config.js under map['*'] if it’s a global alias, or just leave it discoverable via the standard Vendor_Module/js/file naming convention. Load it from a .phtml template with <script type="text/x-magento-init">. Skipping RequireJS and dropping a raw <script> tag will work locally but breaks once you turn on JS bundling, full-page cache, or move to a CDN.
Customizing a KnockoutJS UI Component
Every Magento UI Component, checkout, mini-cart, product gallery, admin grids, is a RequireJS module under the hood. The component XML (view/frontend/web/template/...) points at a JS class loaded via RequireJS as Vendor_Module/js/view/checkout/foo. Customizing means either overriding the class path via map['*'] in your requirejs-config.js, mixing in behaviour via a config['mixins'] entry, or replacing the entire component definition. All three routes go through RequireJS, understand its merge rules before you start.
Adding an admin JS widget
The Magento admin runs on the same RequireJS pipeline as the storefront, just with its own merged config at pub/static/adminhtml/<theme>/en_US/requirejs-config.js. Add a view/adminhtml/requirejs-config.js in your module to register admin JS modules; load them from admin .phtml templates via the same x-magento-init pattern. The admin theme is Magento/backend; the locale is the admin user’s locale. Everything else matches storefront RequireJS, same merge, same cache, same static-content rebuild rules.
Overriding or extending a core module’s JS
The cleanest way to override a core JS file (say Magento_Checkout/js/view/payment) is a map['*'] alias in your requirejs-config.js: map: { '*': { 'Magento_Checkout/js/view/payment': 'Vendor_Module/js/view/payment' } }. RequireJS will resolve every require(['Magento_Checkout/js/view/payment']) in any module to your file instead of the core one. For additive behaviour (don’t replace, just extend) use the mixins mechanism in requirejs-config.js, cleaner because you don’t inherit the burden of merging upstream changes.
Three RequireJS pitfalls that break Magento JS in production
Every “why is my Magento JS broken in production” engagement I’ve been called in to fix tracks back to one of these. Audit your custom JS against the list before going live.
Dropping a raw <script> tag instead of declaring an AMD module
The single most common Magento JS mistake: a developer needs “just a small inline script” and emits a literal <script>require(['jquery'], function($){...});</script> in a .phtml. It works in dev, then breaks in production because the script tag runs before RequireJS is loaded, you get Uncaught ReferenceError: require is not defined. The fix: always go through <script type="text/x-magento-init"> or data-mage-init on a DOM node, and put the actual code in a proper define() AMD module under your module’s view/frontend/web/js/.
Forgetting to rebuild static content after editing requirejs-config.js
The merged requirejs-config.js sits at pub/static/frontend/<theme>/<locale>/requirejs-config.js on disk. When you edit your module’s per-module config, nothing on the storefront changes until the merged file is regenerated. Symptoms: “my new RequireJS alias isn’t picked up”, “my mixin doesn’t fire”. Fix: rm -rf pub/static/frontend/* pub/static/_cache var/view_preprocessed, then bin/magento setup:static-content:deploy -f en_US, then a browser hard-refresh to bust the CDN. See [[feedback_static_content_force_rebuild]] for the full ritual.
Flipping dev/js/enable_js_bundling=1 without testing
Magento’s built-in JS bundler concatenates AMD modules into bundle files served by require.js. On paper this kills round-trips; in practice the default bundler is brittle on Luma, it routinely breaks lazy-loaded modules, mini-cart hydration, and address validation, and the bundle file is megabytes (~10MB+) on a stock Luma store. Test on staging before flipping it on. For real performance gains, use a custom bundler like Baler (github.com/magento/baler) or upgrade to Hyvä, the latter removes RequireJS entirely. Default-stack: keep bundling off, keep dev/js/minify_files=1, keep dev/js/merge_files=0.
Where RequireJS sits in the Magento frontend stack
Five neighbour concepts most readers want to look at next. Click through for the full deep-dive.
- What is Magento KnockoutJSKnockoutJS is Magento’s MVVM library, loaded as a RequireJS module (Magento_Ui/js/lib/ko/...). Every UI Component is a Knockout ViewModel that RequireJS wires up via x-magento-init.
- What is Magento UI ComponentUI Components are Magento’s declarative widget framework, backed by KnockoutJS, loaded by RequireJS. The XML config points at a JS class resolved through the merged requirejs-config.js.
- What is Magento layout XMLLayout XML declares <script src="..."> and <css src="..."> tags, those are static assets that RequireJS does NOT touch. They sit alongside the RequireJS pipeline.
- What is Hyvä ThemesHyvä rips out RequireJS entirely, the storefront uses native ES modules and Alpine.js instead. No merged config, no AMD wrappers, no bundle problems. The migration path away from RequireJS.
- Hire a Magento developerAdobe Certified Magento & Hyvä developer, ten years on platform. RequireJS-config debugging, UI Component overrides, JS-bundling audits, Luma-to-Hyvä migration, fixed-price or hourly.
Magento RequireJS, frequently asked questions
RequireJS vs ES modules, why does Magento still use AMD in 2026?
define() blocks. Migrating to ES modules would break every single one of them. Adobe’s answer is Hyvä, a clean-room storefront theme that drops RequireJS entirely in favour of native ES modules plus Alpine.js. If you’re starting fresh, build on Hyvä. If you’re on Luma, you’re on RequireJS for the lifetime of the storefront unless you do a full theme rewrite.Why does my <code>requirejs-config.js</code> change not load?
pub/static/frontend///requirejs-config.js . Editing your module’s per-module config does not regenerate that file, you have to wipe the static-content cache and redeploy. The full ritual: rm -rf pub/static/frontend/* pub/static/_cache/merged var/view_preprocessed, then bin/magento setup:static-content:deploy -f en_US, then hard-refresh the browser to clear the local cache, then purge the CDN (Cloudflare, Fastly, whatever) because the old requirejs-config.js URL was probably edge-cached too. See [[feedback_static_content_force_rebuild]] for the recipe I run on this site.Can I use ES modules inside a Luma Magento module?
import / export, the entry point that Magento loads via x-magento-init must be a wrapping define([...], function(){...}) AMD block. If you want to internally import from a sibling ES module, declare each one as its own AMD define, declare it as a dep in the outer module, and let RequireJS resolve the graph. Don’t try to mix native into a Luma storefront, that bypasses Magento’s bootstrap and breaks under FPC.What is <code>mage/translate</code>?
Magento_Translation/view/frontend/requirejs-config.js, it exposes $.mage.__('Some text'), the JS equivalent of PHP’s __('Some text'). Inside your AMD module: define(['jquery', 'mage/translate'], function($, $t){ var label = $t('Add to cart'); });. Translation strings are pulled from the same i18n CSV / dictionary files the PHP side reads, you don’t duplicate them. If a string isn’t translated, mage/translate returns the original English. It is the only correct way to translate JS strings; never hardcode language strings inside AMD modules.How do I disable RequireJS bundling without losing minification?
Stores → Configuration → Advanced → Developer → JavaScript Settings: set Enable JavaScript Bundling = No (dev/js/enable_js_bundling=0), Minify JavaScript Files = Yes (dev/js/minify_files=1), and Merge JavaScript Files = No (dev/js/merge_files=0). Merge is an old HTTP/1 optimisation that hurts more than it helps on HTTP/2. Minify-on, merge-off, bundle-off is the safest production default for Luma. Then run bin/magento setup:static-content:deploy -f en_US. For real bundle performance, use Baler or Hyvä instead of the built-in bundler.Does Hyvä really not load RequireJS at all?
require.js or requirejs-config.js anywhere. Hyvä uses native ES modules loaded via for declarative behaviour and Alpine.js for inline reactivity. The bundle size drops from ~2.5MB of compressed JS on Luma to ~150KB on Hyvä for the same storefront, and the JS execution time on first paint drops from 600-800ms to under 100ms. RequireJS in 2026 is the single biggest reason Luma is hard to performance-tune, if PageSpeed Insights and Core Web Vitals matter to you, the migration to Hyvä is the answer.Stuck on a RequireJS error on a Magento storefront?
Send your storefront URL and the error message, I will inspect your requirejs-config.js merge, x-magento-init usage, mixin wiring, and JS bundling settings, then reply with a written fix plan, fixed-price quote, and earliest start date. 24-business-hour turnaround.