Magento – When to use mixins and when to use map

extendknockoutjsmagento2mixinsrequirejs

I'm following magento 2 official documentation to create my checkout step. I'm very new to knockoutjs, requirejs, js components which are massively used in magento 2, specially in checkout.

I'm struggling to understand the concept of mixins, extending and overriding js in magento.

I have seen somewhere earlier map was used to override js file. Now here mixins is used and seem to me to serve similar purpose.

In that documentation in this code section of viewModel:

define(
    [
        'ko'
    ], function (ko) {
        'use strict';

        var mixin = {

            initialize: function () {
                this.visible = ko.observable(false); // set visible to be initially false to have your step show first
                this._super();

                return this;
            }
        };

        return function (target) {
            return target.extend(mixin);
        };
    }
);

target is passed to a function, which is returned from the viewModel,
at last, it further extends itself with mixin model.
I'm confused here as well, where does target come from and what is being returned actually.

In short, my question is what is the difference between mixin and map, and explanation to the viewModel.

Best Answer

The choice of which of those techniques to use is often relative and can be decided by general principles. There are a few exceptions when a mixin would not accomplish the goal and therefore, map must be used.

TL;DR

  • Use a mixin if you only need to modify some of an object's methods.
  • Use map if a mixin won't work or if the file is being changed extensively.
  • If in doubt, use a mixin.

Definitions:

Generally speaking, a mixin overrides individual methods inside of a Javascript object (or "class").

A map is a key used in requirejs-config.js that can replace one file with another. This overrides an entire file. Themes have the capability of doing this without requirejs-config.js.

General Principles / Best Practice

Now, what general principles should we use when making the decision of which approach to use? Relative to this question, I suggest the following:

The goal in making modifications is to affect as little code as possible.

This isn't really the only one, though. Other considerations include overall development time, simplicity of the code in question, and probably more.

The benefit of affecting as little code as possible is upgradability and maintainability. If the core file changes, there is a smaller chance of it breaking your update. In addition, since there is less code there altogether, bug fixes or changes to it should be easier.

Specific to your question:

A mixin is a great choice because it affects very little code and is easy to implement. If you were to use map, you would have to copy and override the entire file. You can't extend the original file like you would with PHP because referencing the original file would load your own file.

With regards to your mixin question: target is the original Javascript object. Magento's mixin handler provides that to you. Further, your mixin must match the structure of the original Javascript object: whether an object or jQuery UI widget or other. This necessitates some slightly awkward code at times.

The code in your example is correct: Magento merges your object over the top of the original one. This replaces the original initialize method with your method but keeps the rest of the object intact.