Magento 2 – Why Use RequireJS `map` Instead of `path`

javascriptmagento2requirejs

In Magento 2's RequireJS implementation, many core modules use a configuration something like this

map: {
    '*': {
        editTrigger:   'mage/edit-trigger',
        addClass:      'Magento_Translation/add-class'
    }
}

In RequireJS, the map configuration directive allows developers to tell RequireJS

When you load module X, and it uses module Y, replace module Y with module Z — but only for Module X

Or, in code

map: {
    'modulex':{
        'moduley':'modulez'
    }
}

The map feature basically allows you to swap out module definitions via configuration — in Magento speak, it's a module rewrite feature for javascript.

What's not clear to me though is Magento's heavy use of the * as the key for the map property.

map: {
    '*': {
        editTrigger:   'mage/edit-trigger',
        addClass:      'Magento_Translation/add-class'
    }
}

The * basically says *do this mapping for all modules, and its intended use case is is provide a base module aliasing that can be changed for more specific modules.

However, Magento appears to use it as a replacement for RequireJS's paths property. i.e. it seems Magento could have achieved the same thing with the following

paths: {
    'editTrigger': 'mage/edit-trigger',
    'addClass':    'Magento_Translation/add-class',
}

and then selectively does specific mapping when needed.

Does anyone know why Magento chose map:* as its method for path aliasing? i.e — is my understanding of the difference between map and path incomplete — or is this one of those "Six of one, half dozen the other" things. Or is there some additional behavior Magento gets by doing it this way.

Not asking to solve a specific problem, asking to clarify any misunderstandings of RequireJS and Magento's implementation before I start writing heavily about it 🙂

Best Answer

After researching this a bit more, I have found one major difference between map and path. I'm not sure if the Magento core team makes deliberate use of this, but per this Stack Overflow answer when you're define a map configuration, you're actually defining a prefix for mappings. i.e. Not only will this

map: {
    '*': {
        editTrigger:   'mage/edit-trigger',
    }
}

ensure the loading the editTrigger module actually loads the mage/edit-trigger module, but also that editTrigger/foo would load the mage/edit-trigger/foo module.

The paths directive is not a prefix mapping. It's a simple one-to-one mapping.

Related Topic