Chat on WhatsApp
Magento glossary

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.

How it works

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.

  1. 01

    Each 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.

  2. 02

    Magento 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]]).

  3. 03

    Templates 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.

  4. 04

    RequireJS 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.

  5. 05

    The 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.

When to use

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.

Common mistakes

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.

FAQ

Magento RequireJS — frequently asked questions

  • RequireJS vs ES modules — why does Magento still use AMD in 2026?
    Backward compatibility plus inertia. Magento 2.0 shipped in 2015 and committed to AMD via RequireJS as the storefront JS module format. By the time native browser ES modules landed (2017-ish), the Magento ecosystem had thousands of third-party extensions all written as AMD <code>define()</code> 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?
    The merged config file is cached on disk at <code>pub/static/frontend/<theme>/<locale>/requirejs-config.js</code>. 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: <code>rm -rf pub/static/frontend/* pub/static/_cache/merged var/view_preprocessed</code>, then <code>bin/magento setup:static-content:deploy -f en_US</code>, then hard-refresh the browser to clear the local cache, then purge the CDN (Cloudflare, Fastly, whatever) because the old <code>requirejs-config.js</code> 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?
    Yes, with caveats. Inside your AMD module you can use modern ES syntax (arrow functions, destructuring, async/await) because the file is parsed by the browser’s JS engine, not RequireJS itself. What you cannot do is use <code>import</code> / <code>export</code> — the entry point that Magento loads via x-magento-init <em>must</em> be a wrapping <code>define([...], function(){...})</code> AMD block. If you want to internally import from a sibling ES module, declare each one as its own AMD <code>define</code>, declare it as a dep in the outer module, and let RequireJS resolve the graph. Don’t try to mix native <code><script type="module"></code> into a Luma storefront — that bypasses Magento’s bootstrap and breaks under FPC.
  • What is <code>mage/translate</code>?
    A RequireJS module that provides Magento’s frontend translation helper. Declared in <code>Magento_Translation/view/frontend/requirejs-config.js</code>, it exposes <code>$.mage.__(&apos;Some text&apos;)</code> — the JS equivalent of PHP’s <code>__(&apos;Some text&apos;)</code>. Inside your AMD module: <code>define([&apos;jquery&apos;, &apos;mage/translate&apos;], function($, $t){ var label = $t(&apos;Add to cart&apos;); });</code>. 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, <code>mage/translate</code> 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?
    Three admin config flags under <code>Stores → Configuration → Advanced → Developer → JavaScript Settings</code>: set <code>Enable JavaScript Bundling = No</code> (<code>dev/js/enable_js_bundling=0</code>), <code>Minify JavaScript Files = Yes</code> (<code>dev/js/minify_files=1</code>), and <code>Merge JavaScript Files = No</code> (<code>dev/js/merge_files=0</code>). 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 <code>bin/magento setup:static-content:deploy -f en_US</code>. For real bundle performance, use Baler or Hyvä instead of the built-in bundler.
  • Does Hyvä really not load RequireJS at all?
    Correct — check the network panel on a Hyvä storefront and you will not find <code>require.js</code> or <code>requirejs-config.js</code> anywhere. Hyvä uses native ES modules loaded via <code><script type="module"></code> 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.
Magento JS audit

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.