Akeneo ikona technologiiCo powinieneś wiedzieć o strukturze modułów w Akeneo PIM opartych o RequireJS?

Co powinieneś wiedzieć o strukturze modułów w Akeneo PIM opartych o RequireJS?

Pierwszy post blogowy stanowił wprowadzenie do obszaru UI w Akeneo PIM. Przedstawiliśmy sam produkt oraz stack technologiczny. Kolejny rozdział poświęcimy zagadnieniu modułu i omówimy je w oparciu o moduł RequireJS używany w starej części frontendu. Dlaczego RequireJS? Jak już wiesz, nowy stack technologiczny Akeneo obejmuje webpack, React oraz TypeScript, jednak nie wszystkie elementy zostały zrefaktoryzowane, co oznacza, że sięgając po komponenty w Akeneo PIM, trafiamy na stary zestaw technologii. Zatem w tym artykule zgłębimy, jak wyglada plik konfiguracyjny .yml, jaką strukturę mają moduły i jak dodawane są do nich dependencje.

Gotowy? Zaczynamy!


Przeczytaj również inne artykuły z cyklu:


Do czego jest używany RequireJS w Akeneo PIM?

Sygnalizowaliśmy już, że aplikacja w dużej mierze opiera się na RequireJS. Mimo że jego zadanie z czasem zaczął przejmować webpack, nadal znajduje zastosowanie w nowszych wersjach oprogramowania.

1. Korzystając z RequireJS, kod JavaScript w Akeneo zostaje podzielony na mniejsze, funkcjonalne i niezależne fragmenty zwane modułami. Mogą być one również rozszerzane i importowane za pomocą RequireJS.

2. RequireJS pozwala w efektywny sposób zarządzać zależnościami pomiędzy klasami, plikami czy komponentami z uwagi na łatwy sposób ich ładowania.

3. Dzięki RequireJS możliwe jest tworzenie kodu, który jest szybszy i lepszy jakościowo.

Jak wygląda przykładowy moduł RequireJS i z czego się składa?

RequireJS wymaga pliku konfiguracyjnego .yml, który umożliwia przypisanie nazwy komponentu do ścieżki do danego pliku. To jeden z podstawowych plików RequireJS ładujący większość modułów.

Przykładowy, domyślny plik konfiguracyjny Akeneo w RequireJS importujący szablony html związane z przyciskami i modalami:

config:
   pim/template/form/index/create-button: pimui/templates/form/index/create-button.html
   pim/template/form/index/confirm-button: pimui/templates/form/index/confirm-button.html
   pim/template/form/creation/modal: pimui/templates/form/creation/modal.html

Z lewej strony widoczny jest klucz, pod którym dostępny będzie moduł i będzie go można dodać jako dependencję do innego komponentu. Po prawej stronie znajdziemy ścieżkę do tego pliku. Warto zwrócić uwagę na "pim/template/form/index/create-button", który będzie użyty w omawianym poniżej komponencie.

Jeśli jesteś ciekawy, jak wygląda cały plik konfiguracyjny RequireJS, kliknij tutaj.

A teraz przyjrzyjmy się, jak zbudowany jest plik pojedynczego modułu. Niech to będzie komponent odpowiadający za renderowanie "create button", który jest używany tam, gdzie coś się tworzy, np. produkt czy paczkę:

"use strict";

/**
 * Create button
 *
 * @author    Alban Alnot 
 * @copyright 2017 Akeneo SAS (http://www.akeneo.com)
 * @license   http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */
define([
  "jquery",
  "underscore",
  "oro/translator",
  "pim/form",
  "pim/template/form/index/create-button",
  "routing",
  "pim/dialogform",
  "pim/form-builder",
], function ($, _, __, BaseForm, template, Routing, DialogForm, FormBuilder) {
  return BaseForm.extend({
    template: _.template(template),
    dialog: null,

    /**
     * {@inheritdoc}
     */
    initialize: function (config) {
      this.config = config.config;

      BaseForm.prototype.initialize.apply(this, arguments);
    },

    /**
     * {@inheritdoc}
     */
    render: function () {
      this.$el.html(
        this.template({
          title: __(this.config.title),
          iconName: this.config.iconName,
          url: this.config.url ? Routing.generate(this.config.url) : "",
        })
      );

      if (this.config.modalForm) {
        this.$el.on(
          "click",
          function () {
            FormBuilder.build(this.config.modalForm).then(function (modal) {
              modal.open();
            });
          }.bind(this)
        );

        return this;
      }

      this.dialog = new DialogForm("#create-button-extension");

      return this;
    },
  });
});

Na samej górze zadeklarowana została funkcja define(). Można posłużyć się nią, aby załadować moduły.

Jej pierwszym argumentem jest tablica dependencji, czyli zależności (innych modułów), jakie chcemy zaimportować do pliku. Drugi argument stanowi funkcja, która jako argumenty przyjmuje wartości podane w tablicy dependencji i będą one dostępne wewnątrz jej ciała.

Za przykładowy import może posłużyć "jquery", który jest pierwszym elementem tablicy. "jquery" będzie potem dostępny w funkcji jako pierwszy, czyli “$”.

Możemy również znaleźć moduł "pim/template/form/index/create-button", który został zdefiniowany w pliku RequireJS powyżej.

Wskazówka! Nazwa argumentów w funkcji może być dowolna, jednak ważne jest, żeby mówiła coś programiście, który w późniejszym etapie będzie miał do czynienia z napisanym przez Ciebie kodem. Przykładowo czwartą dependencją w tablicy jest "pim/form", zgodnie z konwencją Akeneo nazywana jako "BaseForm" – zatem argument numer 4 nazwij dokładnie tak samo. "BaseForm" uznaje się za podstawową klasę używaną w Akeneo, co szerzej omówiliśmy w pierwszym rozdziale.

Funkcja zwraca "BaseForm.extend" – pełni więc rolę modułu rozszerzającego plik "BaseForm", który został zaimportowany i jest dostępny dzięki RequireJS.

W kodzie można zobaczyć też inne funkcje, jak np. "initialize", stosowaną w celu wywołania komponentu "BaseForm":

initialize: function (config) {
   this.config = config.config;
   BaseForm.prototype.initialize.apply(this, arguments);
},

Ponadto znajdziemy drugą funkcję: render(), która odpowiada za wyrenderowanie przycisku. Jak łatwo zauważyć, wewnątrz tej metody mamy dostęp do wszystkich dependencji dodanych w tablicy "define", np. "FormBuilder".

Przed Tobą coraz bardziej zaawansowane treści na temat projektowania interfejsów użytkownika. Kolejne rozdziały są dedykowane m.in. tworzeniu nowych bundli, podstawowym komendom do przebudowy frontendu oraz modyfikacjom, jakim mogą być poddawane moduły w Akeneo. Jeśli chciałbyś dowiedzieć się, jak dopasować gotowy komponent do Twoich potrzeb, śledź naszego bloga!