Slide 1

Slide 1 text

Max Bucknell & Marcin Szterling Taming the JavaScript Beast in Magento 2 Ujarzmić JavaScript w Magento 2

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

Take a Deep Breath • What's Changed for M2? • RequireJS • JavaScript Components • jQuery UI Widgets • UI Apps

Slide 4

Slide 4 text

What's Changed? • No more Prototype • No more inline scripts • No more adding JS to the • No more global variables • And a bunch of new stuff

Slide 5

Slide 5 text

RequireJS

Slide 6

Slide 6 text

RequireJS • A JavaScript module loader • 1.0 in 2011 • Loads JavaScript on a page. • Loads a "module", and its dependencies, and its dependencies, and so on.

Slide 7

Slide 7 text

AMD • Not a chip manufacturer • Stands for "Asynchronous Module Definition" • The format of RequireJS "modules" • Used in all Magento 2 JavaScript files

Slide 8

Slide 8 text

AMD – Dissection define([ 'jquery', ...otherDependencies, ], function moduleDefinition ( $, ...otherDependencies ) { ... });

Slide 9

Slide 9 text

define Function define([ 'jquery', ...otherDependencies, ], function moduleDefinition ( $, ...otherDependencies ) { ... });

Slide 10

Slide 10 text

Dependency Definition define([ 'jquery', ...otherDependencies, ], function moduleDefinition ( $, ...otherDependencies ) { ... });

Slide 11

Slide 11 text

Module Definition define([ 'jquery', ...otherDependencies, ], function moduleDefinition ( $, ...otherDependencies ) { ... });

Slide 12

Slide 12 text

Module Definition • To define an AMD module, you write a function • This function will be called once when your module is loaded • Whatever you return is what dependents get, your public API

Slide 13

Slide 13 text

RequireJS – Impacts • All JavaScript is loaded after your content • Separation of concerns • No global scope pollution

Slide 14

Slide 14 text

AMD Dependencies • How does RequireJS know what jquery means? • ...or collapsible? • ...or mage/translate? • ...or Magento_Checkout/js/view/sidebar?

Slide 15

Slide 15 text

AMD Dependencies • Modules are referred to by their name, which comes from the URL: store.biz/static/frontend/Magento/luma/pl_PL/Magent

Slide 16

Slide 16 text

AMD Dependencies PL/Magento_Checkout/js/view/sidebar.js • Modules are referred to by their name, which comes from the URL:

Slide 17

Slide 17 text

AMD Dependencies • Modules are referred to by their name, which comes from the URL: PL/Magento_Checkout/js/view/sidebar

Slide 18

Slide 18 text

AMD Dependencies • Can also be configured via a mapping • requirejs-config.js • As a sibling to the web directory • Standard RequireJS Config • Merged by Magento\Framework\Requirejs

Slide 19

Slide 19 text

requirejs-config.js var config = { map: { '*': { 'collapsible': 'mage/collapsible', }, } };

Slide 20

Slide 20 text

JavaScript Components

Slide 21

Slide 21 text

JavaScript Component • Basic unit of functionality in Magento 2 • Built on top of AMD, loaded by RequireJS • Gives us The Way to get JavaScript into a page • Comes in two parts: Definition, and Declaration

Slide 22

Slide 22 text

JS Component Definition • A normal AMD module that returns a function. • Function takes parameters of a configuration object, and an HTML element.

Slide 23

Slide 23 text

JS Component Definition define([], function addClass() { function main (config, el) { el.classList.add( config.className); } return main; });

Slide 24

Slide 24 text

JS Component Declaration • JavaScript is included in the template, not the layout XML • Upshot: JavaScript is only included when it needs to be • Specially formatted JSON, that is picked up by Magento

Slide 25

Slide 25 text

JS Component Declaration { "#my-element": { "My_Module/js/add-class": { "className": "class__new" } } }

Slide 26

Slide 26 text

JS Component Declaration { "#my-element": { "My_Module/js/add-class": { "className": "class__new" } } }

Slide 27

Slide 27 text

JS Component Declaration { "#my-element": { "My_Module/js/add-class": { "className": "class__new" } } }

Slide 28

Slide 28 text

JS Component Declaration { "#my-element": { "My_Module/js/add-class": { "className": "class__new" } } }

Slide 29

Slide 29 text

JS Component Definition define([], function addClass() { function main (config, el) { el.classList.add( config.className); } return main; });

Slide 30

Slide 30 text

JS Components • JS Components will only load once, but may be run many times. • Convention comes from jQuery UI: All jQuery UI Widgets are valid JS Components. • To run some general JavaScript, use * as the element selector.

Slide 31

Slide 31 text

UI Apps

Slide 32

Slide 32 text

UI App • A UI App (defined in Magento_Ui) is a JavaScript Component. • Renders a tree of uiComponents into a dynamic web app. • uiComponents ≠ UI Components

Slide 33

Slide 33 text

UI Components? • UI Components are UI Apps under the hood. • The checkout is not a UI Component, it is a UI App. • Configured by the layout, not a ui_component file. • UI Components are out of scope.

Slide 34

Slide 34 text

uiComponent • AMD Module. • A view model, or "block" in Magento language. • Extend from this root component to create your own. • Define the public API for a template.

Slide 35

Slide 35 text

When to Use • For rendering private data. • Serves whole page from Varnish. • Only loads private data through API.

Slide 36

Slide 36 text

UI App Creation { "#checkout": { "Magento_Ui/js/core/app": <?= $block->getJsLayout() ?> } }

Slide 37

Slide 37 text

uiComponent define([ 'uiComponent', ], function myComponent ( Component ) { return Component.extend({ // Public API }); });

Slide 38

Slide 38 text

initialize Component.extend({ initialize: function () { this._super(); // Set up, API requests, etc }, //... });

Slide 39

Slide 39 text

defaults Component.extend({ defaults: { template: 'My_Module/template/component', }, getTemplate: function () { return this.template }, });

Slide 40

Slide 40 text

Templating • Your view-model is linked to a template. • Templates are parsed by Knockout • Knockout uses a special binding syntax to make views dynamic.

Slide 41

Slide 41 text

Binding Click Me!
We are visible!

Slide 42

Slide 42 text

Observables • Your view model will receive notifications about state changes. • Your view needs to respond to these. • Knockout Observables are data objects you can "subscribe" to, and be notified of changes.

Slide 43

Slide 43 text

Observables Component.extend({ isVisible: ko.observable(false), show: function () { this.isVisible(true); }, });

Slide 44

Slide 44 text

Observables Component.extend({ isVisible: ko.observable(false), show: function () { this.isVisible(true); }, });

Slide 45

Slide 45 text

Binding Click Me!
We are visible!

Slide 46

Slide 46 text

Component Configuration • uiComponents are configured in the layout XML as a constructor argument. • Syntax is like DI XML, with deeply nested arrays. • Magento\Checkout\Block\Onepage resolves this array into JSON.

Slide 47

Slide 47 text

XML Configuration ...

Slide 48

Slide 48 text

XML Configuration My_Module/js/view/component

Slide 49

Slide 49 text

XML Configuration My_Module/js/view/component

Slide 50

Slide 50 text

XML Configuration My_Module/js/view/component

Slide 51

Slide 51 text

XML Configuration My_Module/js/view/component

Slide 52

Slide 52 text

XML Configuration ... myComponent // It begins all over again.

Slide 53

Slide 53 text

XML Configuration ... myComponent // It begins all over again.

Slide 54

Slide 54 text

Rendering Children • An app is a tree of UI Components. • Get a child by calling getRegion(name). • getRegion always returns an array. • Get all children with this.regions.

Slide 55

Slide 55 text

Rendering a child

Slide 56

Slide 56 text

Component Registry • A component "class" is a function that returns a constructor, not the component itself. • You cannot load a component as a dependency • Use the registry to get a component. • Registry key is the component's name with all parent component's names. Not displayArea

Slide 57

Slide 57 text

Component Registry let shippingStep = registry.get( 'checkout.steps.shipping-step' ); // may be undefined

Slide 58

Slide 58 text

Component Registry • All JavaScript is loaded and executed asynchronously. • You cannot depend on components being loaded. • Magento has an answer here...

Slide 59

Slide 59 text

Component Registry registry.get( 'checkout.steps.shipping-step', function (component) { component.isVisible.subscribe( onComponentVisibleChange ); } );

Slide 60

Slide 60 text

Conclusion • This is quite a comprehensive framework for web apps. • It's new. Expect issues. Some common things are hard or ugly.

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

Join a Growing Team

Slide 63

Slide 63 text

?