Skip to content

Instantly share code, notes, and snippets.

@ianvonholt
Created March 6, 2017 20:21
Show Gist options
  • Save ianvonholt/9f700ec9a6def8655179b46f9f294e61 to your computer and use it in GitHub Desktop.
Save ianvonholt/9f700ec9a6def8655179b46f9f294e61 to your computer and use it in GitHub Desktop.
Marko Version 3 to Version 4 Migration Guide

Marko Migration Guide

Version 3 to Version 4

Below is an assortments of steps that were taken to take a live production site running with Marko v3 and Marko Widgets to the new Marko v4. This is by no means a complete migration guide, but more of what steps were taken to get everything up and running.

Component Filename Structure

Marko v3 Widgets were traditionally structured as follows:

  components/
    my-cool-component/
      index.js       --> Widget Definition
      template.marko --> Widget Marko Template
      browser.json   --> Lasso Requirements
      style.css      --> Widget CSS Definition

Marko v4 changes the filename structure a bit, and introduces single page components within index.marko.

index.js has now become component.js and component-browser.js.

template.marko has now become index.marko.

Thus a full split file based component in Marko v4 would be structured as follows:

  components/
    my-cool-component/
      component.js --> Component Definition
      index.marko  --> Component Marko Template
      browser.json --> Lasso Requirements
      style.css    --> Component CSS Definition

Ref: marko-js/marko#416 and marko-js/marko#591

Component Definition

Marko and Marko Widgets had to define a component within each individual index.js as follows:

module.exports = require('marko-widgets').defineComponent({
  template: require('./template.marko'),
  ...
});

With Marko v4, this is no longer allowed. Marko Widgets has been merged into the Marko codebase.

We can define a component within a component.js (more about filenames later) as follows:

module.exports = {
    ...
};

Ref: marko-js/marko#416

Component Lifecycle Methods

There have been huge improvements to Marko's Component Lifecycle methods and how a widget / component is defined and exported.

Ref: marko-js/marko#396

  • getInitialProps(input, out), getWidgetConfig(input, out), and getInitialState(input, out) becomes onCreate(input, out) or onInput(input)

    In Marko v3 getInitialPros was the place to normalize the input properties during the rendering of a UI component. This was usually done before setting template data and state variables. Additionally, getWidgetConfig was used to determine what was passed to the widget constructor init(widgetConfig) when the widget is initialized in the browser.

    Now we use onCreate(input, out) as the entry point to normalize both the input, state, and component configuration variables for a component.

    Example:

    module.exports = {
      onCreate: function (input, out) {
        this.componentConfigVariable = true; // Widget config uses `this` scope
        this.state = {
          ... // State variables can be set here as well
        },
        this.input = {
          ... // Input, once data, variables can be set here as well
        }
      },
    
      onInput: function (input) {
        this.state = {
          ... // State variables can be set here as well
        }
        return {
          ... // Input variables are returned.
        }
      }
    

    Take care when setting, and using input variables in both onCreate and onInput. Since onInput is called after component creation, your input variables in onInput can be modified in the onCreate method.

  • getTemplateData(state, input) becomes onInput(input)

    Marko v3 getTemplateData allowed you to set template data object variables to be passed and then used in Marko templates. These are no longer necessary. data variables have been renamed to input with Marko v4.

    Example:

     module.exports = {
       onInput: function (input) {
         return {
           ... // Anything set here becomes `input.` in a template
         }
       }
     }
    
  • init(widgetConfig) becomes onMount()

Marko v3 init and Marko v4 onMount are nearly identical. The only difference being that widgetConfig is no longer passed, but rather persisted within the this scope.

The mount event is emitted when the component is first mounted to the DOM. For a server-rendered component, this is the first event that is emitted in the browser.

Note: With some jQuery plugins, onMount is called before the initialization of those plugins. To get around this, if it is needed, you can wrap your jQuery specific plugin calls as follows:

module.exports = {
  onMount: function () {
    $(function () {
      ... // Plugin specific calls here.
    })
  }
}
  • onBeforeUpdate() has become deprecated

    Marko v3 onBeforeUpdate is no longer present. You can use onRender to satisfy the same requirements. The one caveat is that onRender will be called before onMount on the server. This can lead to some confusion in code portability, so it's best to just not use any onBeforeUpdate code within onRender unless it's modifying the component internals.

  • onBeforeDestroy() has become deprecated

    Marko v3 onBeforeDestroy is no longer present. You can use onDestroy to satisfy the same requirements.

Component Marko Syntax Changes

Marko v3 had a quite a few language keyword changes with the v4 update. These changes should mostly be used within a components index.marko after it has been renamed (as explained above)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment