Migrating Luma JavaScript and Templates
This guide helps you convert Luma JavaScript and templates to modern, Alpine.js-based Hyvä components.
From data-mage-init and require() to Inline Scripts
Hyvä inlines most JavaScript directly within `.phtml` templates, unlike Luma's external `data-mage-init` or `require()` scripts. This approach creates self-contained, reusable UI components and boosts page speed.
Process for Inlining Scripts
-
Declare a new function within a
<script>tag in your.phtmltemplate. Give it a unique name to prevent global scope conflicts. -
Copy the contents of the original RequireJS module into this new function.
-
Replace dependencies. Often, jQuery dependencies can be replaced with native JavaScript. Sometimes, this may involve inlining other external scripts.
-
Call the new function based on its dependencies:
- For code depending on customer section data, subscribe to the
private-content-loadedevent. - For code in the page header depending on the global
window.hyvaobject, subscribe toDOMContentLoadedto ensurehyvais defined. - Otherwise, call the function inline after its definition.
- For code depending on customer section data, subscribe to the
From x-magento-template to Alpine.js x-for
Luma uses <script type="text/x-magento-template"> with mage/template and underscore.js to render data arrays. Hyvä replaces this with Alpine.js x-for directives, as it doesn't use those libraries.
Rendering Array Items with Alpine.js
Alpine.js x-for is the main directive for iterating arrays and rendering DOM elements.
<ul class="bundle items">
<template x-for="option in selectedOptions">
<li class="mb-2" x-show="option.products.length">
<span class="text-base font-semibold" x-html="option.label"></span>
<template x-for="product in option.products">
<div><span x-html="product.qty"></span> x <span x-html="product.name"></span></div>
</template>
</li>
</template>
</ul>
To access the index of the current iteration, use the (item, index) syntax:
For more details, see the Alpine.js x-for documentation.
From jQuery data() to Native dataset
jQuery's $(selector).data() reads data-* attributes, caching values and auto-parsing JSON. When migrating to vanilla JavaScript, you must manually replicate these behaviors if needed.
The native equivalent, element.dataset, offers a live view of attributes. If an attribute is removed from the DOM, its value is no longer accessible via dataset.
Reading Data Attributes
Consider this element: <div id="my-id" data-example='{"name": "Alice"}'></div>
jQuery Way:
Native JavaScript / Alpine.js Way: To cache a value (e.g., before removing the attribute), store it manually on a custom element property.
const element = document.getElementById('my-id');
// Manually parse JSON and store it on a custom property
element.__example = JSON.parse(element.dataset.example);
// The value is now cached even if the attribute is removed
element.removeAttribute('data-example');
console.log(element.__example); // => {name: "Alice"}
Native Equivalents for Underscore Functions
Here are native JavaScript equivalents for common Underscore.js utility functions.
| Underscore | Native JavaScript Equivalent |
|---|---|
_.isObject(x) |
const isObject = x => x === Object(x); |
_.isArray(x) |
Array.isArray(x) |
_.has(x, p) |
const has = (x, p) => x === Object(x) && x.hasOwnProperty(p); |
_.isEqual(x, y) |
JSON.stringify(x) === JSON.stringify(y) (for simple objects/arrays) |
Native Equivalents for jQuery Functions
Most jQuery functions have native JavaScript equivalents. For a comprehensive guide, see: