Skip to content

Module tailwind.config.js merging

Often compatibility modules need to add their templates and layout XML files to a themes tailwind.config.js content purge configuration.
Other tailwind.config.js configuration could need to be added to support a module, too. This feature is provided by a npm module @hyva-themes/hyva-modules.

This npm module is included with the Hyvä default theme since release 1.1.14, but it can also be added to themes based on older releases.

Module tailwind.config.js merging for 1.1.13 and older themes
  1. First, run the following command to install the npm module to the theme within the theme web/tailwind directory.

    npm install @hyva-themes/hyva-modules
    

  2. Import the module in the themes tailwind.config.js file.

    const hyvaModules = require('@hyva-themes/hyva-modules');
    

  3. Wrap the value assigned to module.exports in a function call to hyvaModules.mergeTailwindConfig.

    module.exports = hyvaModules.mergeTailwindConfig({
        // theme tailwind config here ...
    })
    

Updating @hyva-themes/hyva-modules

In case an update of @hyva-themes/hyva-modules is released, and you want to pull that into your theme, run the following command to fetch the new version, replacing the 1.0.4 in the example with the desired version:

npm install @hyva-themes/hyva-modules@1.0.4

The npm module also contains functionality to merge postcss configuration from modules.

Adding a module to the tailwind purge config

1. Create the tailwind.config.js file

For modules the tailwind configuration is located at view/frontend/tailwind/tailwind.config.js.

Any paths are specified relative to this file. For example, to include the modules *.phtml templates into the tailwind config, use:

module.exports = {
  purge: {
    content: [
      '../templates/**/*.phtml',
    ]
  }
}

Skeleton compat modules contain this configuration out of the box since the release of 1.1.14

Other configuration can be added to the file, too, and will be merged into a themes tailwind configuration when the styles.css file is built.

TailwindCSS v2 or v3?

Do I use the TailwindCSS v2 or v3 purge content structure?

The script is smart enough to map a modules' purge config structure to the same one that is used in the theme.
If you don't have any preference, then we suggest you use the v3 structure.

Using require() inside a module

When using require with a node library inside a modules' view/frontend/tailwind/tailwind.config.js file, prefix the node module name the global variable themeDirRequire:

const colors = require(`${themeDirRequire}/tailwindcss/colors`);

The global variable themeDirRequire maps to the node_modules/ folder in the theme that is currently being built.

If you need to require node modules bundled with the module inside the frontend/tailwind directory, use the usual import syntax.

2. Add the module to the app/etc/hyva-themes.json file

A modules tailwind.config.js file will not be included in the build process immediately.
First, the module needs to be added to the Magento app/etc/hyva-themes.json file. This file contains a list of all installed modules that should be scanned for tailwind configuration or tailwind CSS.

Since Hyvä 1.1.15, the hyva-themes.json file is generated implicitly whenever a new module is status is changed by

  • bin/magento setup:upgrade
  • bin/magento module:enable
  • bin/magento module:disable

The file can also be explicitly generated by the command

bin/magento hyva:config:generate

With Hyvä version 1.14 this command needed to be be run always after a compat module was installed

Since Hyvä 1.1.15 this usually happens automatically through one of the commands listed above.

Before automatic tailwind.config.js merging was introduced, the purge content configuration in a theme would need to be adjusted to include the new theme.

Now no manual configuration changes are required.

The app/etc/hyva-themes.json file

When one of the following commands is run, Hyvä modules register themselves to be added to the file

  • bin/magento hyva:config:generate
  • bin/magento setup:upgrade
  • bin/magento module:enable
  • bin/magento module:disable

Any compatibility module that is registered with the Hyva\CompatModuleFallback\Model\CompatModuleRegistry (using etc/frontend/di.xml) is added to the file automatically.

Other modules besides compat modules can also register themselves to be included in the hyva-themes.json file using an event observer, as described below.

Registering a module for inclusion in hyva-themes.json

The app/etc/hyva-themes.json file contains a list of all installed modules that should be scanned for tailwind configuration or tailwind CSS.

This is not required for compat modules

Compatibility modules that use automatic template overrides (via the CompatModuleRegistry) are registered automatically.
This documentation might be useful for other modules.

Example for a generated hyva-themes.json file:

{
    "extensions": [
        {
            "src": "app\/code\/My\/Module"
        },
        {
            "src": "vendor\/hyva-themes\/magento2-magenerds-baseprice\/src"
        }
    ]
}

A module that needs to be included in the hyva-themes.json file, can do so by declaring an event observer in etc/frontend/events.xml for the event hyva_config_generate_before.

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"
>
    <event name="hyva_config_generate_before">
        <observer name="MyModule" instance="Hyva\ExampleModule\Observer\RegisterModuleForHyvaConfig"/>
    </event>
</config>

The observer method will receive a configuration object which represents the data structure written to the JSON file.

To register itself for the tailwind theme configuration merge process, it needs to add the module path relative to the Magento root directory to the extensions[].src path in the file.

<?php

declare(strict_types=1);

namespace Hyva\ExampleModule\Observer;

use Magento\Framework\Component\ComponentRegistrar;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

class RegisterModuleForHyvaConfig implements ObserverInterface
{
    private $componentRegistrar;

    public function __construct(ComponentRegistrar $componentRegistrar)
    {
        $this->componentRegistrar = $componentRegistrar;
    }

    public function execute(Observer $event)
    {
        $config = $event->getData('config');
        $extensions = $config->hasData('extensions') ? $config->getData('extensions') : [];

        $moduleName = implode('_', array_slice(explode('\\', __CLASS__), 0, 2));

        $path = $this->componentRegistrar->getPath(ComponentRegistrar::MODULE, $moduleName);

        // Only use the path relative to the Magento base dir
        $extensions[] = ['src' => substr($path, strlen(BP) + 1)];

        $config->setData('extensions', $extensions);
    }
}