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
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 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
onCreate
andonInput
. SinceonInput
is called after component creation, your input variables inonInput
can be modified in theonCreate
method. -
getTemplateData(state, input) becomes onInput(input)
Marko v3
getTemplateData
allowed you to set templatedata
object variables to be passed and then used in Marko templates. These are no longer necessary.data
variables have been renamed toinput
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 useonRender
to satisfy the same requirements. The one caveat is that onRender will be called beforeonMount
on the server. This can lead to some confusion in code portability, so it's best to just not use anyonBeforeUpdate
code withinonRender
unless it's modifying the component internals. -
onBeforeDestroy() has become deprecated
Marko v3
onBeforeDestroy
is no longer present. You can useonDestroy
to 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-bind
is 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 key
Ref: marko-js/marko#394 and marko-js/marko#570
-
w-id-for becomes key-for
Ref: 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 input
Ref: marko-js/marko#549
-
state introduces as a local variable
Ref: marko-js/marko#400