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.
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
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
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
getInitialProswas 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,getWidgetConfigwas used to determine what was passed to the widget constructorinit(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
onCreateandonInput. SinceonInputis called after component creation, your input variables inonInputcan be modified in theonCreatemethod. -
getTemplateData(state, input) becomes onInput(input)Marko v3
getTemplateDataallowed you to set templatedataobject variables to be passed and then used in Marko templates. These are no longer necessary.datavariables have been renamed toinputwith 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 deprecatedMarko v3
onBeforeUpdateis no longer present. You can useonRenderto satisfy the same requirements. The one caveat is that onRender will be called beforeonMounton the server. This can lead to some confusion in code portability, so it's best to just not use anyonBeforeUpdatecode withinonRenderunless it's modifying the component internals. -
onBeforeDestroy() has become deprecatedMarko v3
onBeforeDestroyis no longer present. You can useonDestroyto satisfy the same requirements.
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)
-
w-bindis deprecatedComponents in v4 will no longer need to define w-bind within the template markup.
v3
template.marko:<div w-bind> ... </div>v4
index.marko:<div> ... </div>Ref: marko-js/marko#393 and marko-js/marko#395
-
w-id becomes keyRef: marko-js/marko#394 and marko-js/marko#570
-
w-id-for becomes key-forRef: marko-js/marko#394 and marko-js/marko#570
-
w-preserve* becomes no-update*()Ref: marko-js/marko#419
-
w-on* event handlers become on*() or on-*()Ref: marko-js/marko#420
-
w-body becomes include()Ref: marko-js/marko#418
-
data becomes inputRef: marko-js/marko#549
-
state introduces as a local variableRef: marko-js/marko#400