UNPKG

25.2 kBMarkdownView Raw
1# Marko vs React: An In-depth Look
2
3<a href="https://hackernoon.com/marko-vs-react-an-in-depth-look-767de0a5f9a6">
4 <img src="https://cdn-images-1.medium.com/max/2000/1*4BP6tPQtwImj6_QseeybwQ.png" alt="Marko logo" width="100%" />
5</a><br />
6
7You can find the original ["Marko vs React: An In-depth Look" article here](https://hackernoon.com/marko-vs-react-an-in-depth-look-767de0a5f9a6)!
8
9In this article we will take an in-depth look at the differences and
10similarities between [Marko](http://markojs.com/) and React from the perspective
11of the maintainers of Marko.
12
13On the surface, Marko and React have a lot in common and both are trying to
14solve very similar problems. Specifically, both Marko and React allow developers
15to build web applications based on UI components and both free developers from
16having to write code to manually update the DOM. While many of the features in
17Marko were inspired by React, Marko and React offer very different usability and
18performance characteristics. Marko was designed to avoid almost all boilerplate
19and is more closely aligned with HTML. In almost all cases, a Marko UI component
20will require less lines of code than its React JSX equivalent while maintaining
21readability and allowing the same expressiveness as JSX. In addition, Marko is
22highly optimized for use on the server and in the browser and has a much smaller
23weight:
24
25<img src="https://cdn-images-1.medium.com/max/1600/1*a9hL_pfNrRq1UU3Mxkf3Jg.png" alt="Marko logo" width="100%" /><br />
26
27Because the Marko JavaScript library is much smaller than React, it will require
28less time to load and parse and this will drastically improve page load times on
29slow connections or on older devices. Based on [our
30benchmarks](http://markojs.com/#benchmarks), Marko consistently outperforms
31React by a significant margin on both the server and in the browser.
32
33### Example
34
35The following code highlights some of the differences between Marko and React
36JSX using a somewhat contrived UI component as an example:
37
38#### React JSX
39
40```jsx
41class Counter extends React.Component {
42 constructor(props) {
43 super(props);
44
45 this.state = { count: 0 };
46 }
47
48 increment(delta) {
49 this.setState({ count: this.state.count + delta });
50 }
51
52 render() {
53 const count = this.state.count;
54 let countClassName = "count";
55
56 if (count > 0) {
57 countClassName += " positive";
58 } else if (count < 0) {
59 countClassName += " negative";
60 }
61
62 return (
63 <div className="click-count">
64 <div className={countClassName}>{count}</div>
65 <button
66 onClick={() => {
67 this.increment(-1);
68 }}
69 >
70 -1
71 </button>
72 <button
73 onClick={() => {
74 this.increment(1);
75 }}
76 >
77 +1
78 </button>
79 </div>
80 );
81 }
82}
83```
84
85<span class="figcaption_hack">[▶ Try Online](http://codepen.io/mlrawlings/pen/wJXOWR?editors=0010)</span>
86
87#### Marko
88
89```marko
90class {
91 onCreate() {
92 this.state = { count: 0 };
93 }
94 increment(delta) {
95 this.state.count += delta;
96 }
97}
98
99$ var count = state.count;
100
101<div.click-count>
102 <div.count class={
103 positive: count > 0,
104 negative: count < 0
105 }>
106 ${count}
107 </div>
108 <button on-click('increment', -1)>
109 -1
110 </button>
111 <button on-click('increment', 1)>
112 +1
113 </button>
114</div>
115```
116
117<span class="figcaption_hack">[▶ Try
118Online](http://markojs.com/try-online/?gist=8fe46bc5866605aca0dfeec202604011)</span>
119
120### Similarities
121
122Marko and React have the following in common:
123
124- UI component-based
125- JavaScript and HTML markup can be intertwined
126- No restrictions on JavaScript (use ES5 or ES2015+, your choice)
127- Virtual DOM rendering in the browser
128- DOM diffing/patching is used to reconcile views
129- Both support keyed element matching
130- UI components can have input properties
131- UI components can have internal state
132- Changes to state trigger an asynchronous update to the DOM
133- Updates to the DOM are batched
134- Compatible with central application state stores such as Redux and MobX
135- UI components can be embedded using custom tags
136- Declarative event binding (no `domEl.addEventListener()` needed)
137- Support for all DOM events
138- Event delegation utilized internally for DOM events that bubble
139- IE9+ support
140- Similar lifecycle events for UI components
141- JSX and Marko both compile to JavaScript
142
143### Differences
144
145At a high level here are some differences:
146
147#### Differences in rendering
148
149- **Improved performance:** Marko renders to a virtual DOM in the browser and
150 directly to an HTML stream on the server (Marko supports multiple compilation
151 targets).
152- **Improved performance:** Marko supports asynchronous rendering with [early
153 flushing of
154 HTML](http://www.ebaytechblog.com/2014/12/08/async-fragments-rediscovering-progressive-html-rendering-with-marko/)
155 for improvements in actual and perceived page load times.
156- **Improved performance:** React requires an additional client-side re-render if
157 a page is initially rendered on the server while Marko does not.
158- **Improved ease of use:** Marko automatically serializes UI component state and
159 input down to the browser so that the browser can pick up right where the server
160 left off.
161- **Improved ease of use:** Marko is suitable for rendering an entire HTML page on
162 the server with support for tags such as `<doctype>` and `<html>`
163
164#### Differences in syntax
165
166- **Improved ease of use:** Marko uses the
167 [HTML-JS](http://markojs.com/docs/syntax/) syntax and the
168 [JSX](https://facebook.github.io/react/docs/jsx-in-depth.html) syntax is offered
169 for React.
170- **Improved ease of use:** Marko supports both a concise syntax and a familiar
171 HTML syntax.
172- **Improved ease of use:** JSX requires strict XML while Marko aligns with less
173 strict HTML that web developers are used to.
174- **Improved ease of use:** With Marko, _all_ HTML attribute values are parsed as
175 JavaScript expressions.
176- **Improved ease of use:** Marko supports simple directives for conditionals,
177 looping, etc.
178- **JSX limitation:** JSX is “just JavaScript” but requires expressions that
179 preclude the usage of JavaScript statements such as in certain places.
180
181#### Differences in compilation
182
183- **Improved performance:** Marko supports multiple compilation outputs (Marko
184 VDOM and HTML streaming are currently supported).
185- **Improved ease of use:** Marko compiles UI components to JavaScript modules
186 that export a rendering API.
187- **Expanded capabilities:** Marko supports a robust API for controlling how
188 custom tags and custom attributes get compiled and it supports compile-time
189 transforms based on a friendly Abstract Syntax Tree (AST).
190- **Improved performance:** JSX is just syntactic sugar that translates elements
191 to `createElement()` function calls while the Marko compiler has full control over how things are
192 compiled and optimized.
193- **Improved ease of use:** React requires all UI components to be explicitly
194 imported before they can be used as custom tags while Marko supports both
195 explicit importing and implicit importing.
196- **Improved performance:** Marko has a modular runtime and the compiler generates
197 code that only imports the parts of the Marko runtime that are needed for much
198 smaller builds.
199- **Improved ease of use:** Marko supports optional compile-time checks to ensure
200 that only allowed attributes are passed to custom tags. (React `PropTypes` only provide
201 validation at render-time)
202- **Improved ease of use:** Marko validates _all_ tag names at compile-time.
203- **Improved ease of use:** Marko provides its own compiler that integrates with
204 Node.js and JavaScript module bundlers while React JSX requires babel and custom
205 babel transforms.
206
207#### Differences in UI components
208
209- **Reduced boilerplate:** No explicit extending of JavaScript classes in Marko
210 (in contrast to `class Counter extends React.Component` in React).
211- **Improved ease of use:** Modifications to UI component state are synchronous
212 with Marko while [the rules for React are more
213 complicated](https://facebook.github.io/react/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous).
214- **Improved ease of use:** Marko watches UI component state objects to allow
215 state to be modified directly (e.g., `this.state.count++`).
216- **Improved ease of use:** Marko supports single-file UI components combining
217 JavaScript behavior, CSS styling (with support for CSS preprocessors) and HTML
218 markup. (React requires using one of the many [CSS in JS
219 solutions](https://github.com/MicheleBertoli/css-in-js) if you want styles in
220 the same file as your component and there is no standard in the community)
221- **Improved maintainability:** Marko supports a seamless transition from a
222 single-file UI component to a multi-file UI component.
223- **Improved performance:** Marko assumes UI components are pure by default and
224 skips re-rendering when input properties and state are unchanged (React requires
225 extending
226 [React.PureComponent](https://facebook.github.io/react/docs/react-api.html#react.purecomponent)).
227
228#### Differences in event systems
229
230- **Reduced complexity:** React utilizes [synthetic
231 events](https://facebook.github.io/react/docs/events.html) while Marko utilizes
232 real DOM events.
233- **Improved ease of use:** Custom events are emitted using the [EventEmitter
234 API](https://nodejs.org/api/events.html) in Marko (e.g., `this.emit('myCustomEvent', arg1, arg2)`).
235- **Improved ease of use:** Marko has a consistent approach for listening to both
236 native DOM events and custom events.
237- **Improved ease of use:** React requires passing around `Function` references for custom
238 events while Marko automatically delegates emitted custom events to event
239 handler methods on components.
240- **Improved ease of use:** Marko provides a simple mechanism for binding
241 additional arguments to event handler methods and `this` will be the component
242 instance.
243
244#### Differences in compatibility
245
246- **Marko limitation:** Marko has no support for native mobile similar to React
247 Native (although with Marko VDOM rendering, this is possible).
248- **Marko limitation:** Marko requires a JavaScript module bundler (such as
249 [Lasso](http://markojs.com/docs/lasso/),
250 [Webpack](http://markojs.com/docs/webpack/),
251 [Rollup](http://markojs.com/docs/rollup/) or
252 [Browserify](http://markojs.com/docs/browserify/)) to be used in the browser
253 since Marko UI components compile down to JavaScript modules. (we consider using
254 a JavaScript module bundler a best practice)
255
256---
257
258In the sections below we will take a closer look at some of the differences
259between Marko and React.
260
261### Syntax
262
263Both Marko and React JSX allow HTML markup and JavaScript to be combined into a
264single file and both support building web applications based on UI components.
265Marko utilizes an [HTML-JS syntax](http://markojs.com/docs/syntax/) while most
266React apps use the JSX syntax.
267
268> React JSX makes JavaScript more like HTML and Marko makes HTML more like
269> JavaScript.
270
271In the end, both Marko and React allow JavaScript and HTML to be intertwined.
272
273### Syntax: attributes
274
275#### React JSX
276
277In React JSX, all attribute values are parsed as string values unless `{}` is used.
278
279```jsx
280<MyComponent
281 name="Frank"
282 messageCount={30}
283 visible={true}
284 person={{ firstName: 'John', lastName: 'Doe' }}
285 colors={['red', 'green', 'blue']} />
286
287<div id="content" className="foo">Hello</div>
288```
289
290#### Marko
291
292With Marko, _all_ attribute values are parsed as JavaScript expressions. The
293following Marko code is equivalent to the React JSX code above:
294
295```marko
296<my-component
297 name="Frank"
298 message-count=30
299 visible=true
300 person={ firstName: 'John', lastName: 'Doe' }
301 colors=['red', 'green', 'blue'] />
302
303<div id="content" class="foo">Hello</div>
304```
305
306### Syntax: inline JavaScript
307
308#### React JSX
309
310React JSX starts with JavaScript and allows XML elements to be inlined as shown
311below:
312
313```jsx
314import { formatDate } from "./util";
315
316function formatName(person) {
317 return person.firstName + " " + person.lastName.charAt(0) + ".";
318}
319
320export default function HelloMessage(props) {
321 var person = props.person;
322
323 return (
324 <div>
325 Hello {formatName(person)}!
326 <span>You were born on {formatDate(person.birthday)}.</span>
327 </div>
328 );
329}
330```
331
332#### Marko
333
334Marko starts out in HTML, but it allows JavaScript to be inlined in a clean and
335maintainable way. Unlike other template languages, Marko aims to allow the full
336power of JavaScript. The following Marko code is equivalent to the React JSX
337code above:
338
339```marko
340import { formatDate } from './util';
341
342static function formatName(person) {
343 return person.firstName + ' ' + person.lastName.charAt(0) + '.';
344}
345
346$ var person = input.person;
347
348<div>
349 Hello ${formatName(person)}!
350 <span>
351 You were born on ${formatDate(person.birthday)}.
352 </span>
353</div>
354```
355
356Lines prefixed with `$` are directly added to the compiled JavaScript output inside
357the compiled `render()` function (for JavaScript code that should run for every render).
358Lines prefixed with `static` are directly added to the compiled JavaScript output
359outside the `render()` function (for code that should only run _once_ when the template is
360loaded).
361
362### Syntax: HTML support
363
364With Marko any valid HTML markup can be used inside a Marko template. This is
365not the case with React. The following quote is from the [React
366documentation](https://facebook.github.io/react/docs/introducing-jsx.html#specifying-children-with-jsx):
367
368> **Caveat:**
369
370> Since JSX is closer to JavaScript than HTML, React DOM uses `camelCase` property naming
371> convention instead of HTML attribute names.
372
373> For example, `class` becomes `className` in JSX, and `tabindex` becomes `tabIndex`.
374
375As a result of this caveat for React, [tools for converting HTML to JSX
376exist](http://magic.reactjs.net/htmltojsx.htm).
377
378#### React JSX
379
380```jsx
381<div id="content" className="my-component">Hello</div>
382
383<input type="text" name="firstName" value="John" />
384```
385
386#### Marko
387
388```marko
389<div id="content" class="my-component">Hello</div>
390
391<input type="text" name="firstName" value="John">
392```
393
394### Syntax: conditionals
395
396JSX is syntactic sugar on top of JavaScript, but it requires expressions, so
397simple things like an `if/else/for` statement don’t work on their own within a JSX element. As
398a result, you must either use a ternary expression, an immediately invoked
399function expression, function call expression, or the experimental `do {}` expression
400(stage 0 at the time of writing). This is not an issue for Marko, and tags
401such as `if()` and `for` can be used anywhere as shown below:
402
403#### React JSX
404
405```jsx
406function counterMessage(count) {
407 return (
408 <div className="counter-message">
409 (function() {
410 if (count < 0) {
411 return <div>Count is negative</div>
412 } else if (count === 0) {
413 return <div>Count is zero</div>
414 } else {
415 return <div>Count is positive</div>
416 }
417 }())
418 </div>
419 )
420}
421```
422
423#### Marko
424
425```marko
426<div.counter-message>
427 <if(count < 0)>
428 <div>Count is negative</div>
429 </if>
430 <else if(count === 0)>
431 <div>Count is zero</div>
432 </else>
433 <else>
434 <div>Count is positive</div>
435 </else>
436</div>
437```
438
439Marko also allows directives to be used as attributes for a more condensed
440template:
441
442```marko
443<div.counter-message>
444 <div if(count < 0)>Count is negative</div>
445 <div if(count === 0)>Count is zero</div>
446 <div else>Count is positive</div>
447</div>
448```
449
450### Syntax: looping
451
452#### React JSX
453
454```jsx
455function renderColors(colors) {
456 return (
457 <ul>
458 {colors.map(color => (
459 <li
460 className="color"
461 style={{
462 backgroundColor: color
463 }}
464 >
465 {color}
466 </li>
467 ))}
468 </ul>
469 );
470}
471```
472
473#### Marko
474
475```marko
476<ul>
477 <for|color| of=colors>
478 <li.color style={ backgroundColor: color }>
479 ${color}
480 </li>
481 </for>
482</ul>
483```
484
485### Syntax: HTML shorthand
486
487```marko
488<div id="content"/>
489<h1 class="subheader"/>
490<h1 id="pageTitle" class="foo bar"/>
491
492<!-- Shorthand equivalent: -->
493<div#content/>
494<h1.subheader/>
495<h1#pageTitle.foo.bar/>
496```
497
498Marko supports a shorthand based on CSS selectors for less code.
499
500React does not support these helpful shorthands.
501
502### Syntax: concise
503
504Marko supports a concise syntax that drops angled brackets and ending tags in
505favor of indentation. Here’s how the Marko syntax options compare:
506
507#### Marko HTML syntax
508
509```marko
510<ul>
511 <for|color| of=colors>
512 <li>${color}</li>
513 </for>
514</ul>
515```
516
517#### Marko concise syntax
518
519```marko
520ul
521 for|color| of=colors
522 li -- ${color}
523```
524
525#### Marko mixed syntax
526
527```marko
528ul
529 for|color| of=colors
530 <li>${color}</li>
531```
532
533The HTML syntax and the concise syntax can be used together:
534
535#### React JSX
536
537React does not offer a concise syntax.
538
539### Components
540
541Marko starts with simple HTML and allows UI component logic to easily be layered
542on top.
543
544#### React JSX
545
546A React UI component is typically implemented as a class that extends `ReactComponent`:
547
548```jsx
549class HelloMessage extends React.Component {
550 render() {
551 return <div>Hello {this.props.name.toUpperCase()}</div>;
552 }
553}
554```
555
556React also supports a more concise functional component:
557
558```jsx
559function HelloMessage(props) {
560 return <div>Hello {props.name.toUpperCase()}</div>;
561}
562```
563
564However, if state or lifecycle events are needed then a functional UI component
565must be converted to a class component:
566
567```jsx
568class HelloMessage extends React.Component {
569 componentDidMount() {
570 // ...
571 }
572 render() {
573 return <div>Hello {this.props.name.toUpperCase()}</div>;
574 }
575}
576```
577
578#### Marko
579
580Here is the same component in Marko:
581
582```marko
583<div>Hello ${input.name.toUpperCase()}</div>
584```
585
586Behavior can easily be added to any Marko UI component:
587
588```marko
589class {
590 onMount() {
591 // ...
592 }
593}
594
595<div>Hello ${input.name.toUpperCase()}</div>
596```
597
598Marko also allows JavaScript behavior, CSS styling and HTML markup to be
599embedded in the Marko template as a single file UI component:
600
601```marko
602class {
603 onMount() {
604 // ...
605 }
606}
607
608style.less {
609 .hello {
610 color: red;
611 }
612}
613
614<div.hello>
615 Hello ${input.name.toUpperCase()}
616</div>
617```
618
619### API
620
621Marko compiles component to JavaScript modules that export an API for rendering
622the component as shown below:
623
624```js
625require("./components/greeting")
626 .renderSync({ name: "Frank" })
627 .appendTo(document.body);
628```
629
630The same UI component can be rendered to a stream such as a writable HTTP
631response stream:
632
633```js
634require("./components/hello").render({ name: "John" }, res);
635```
636
637> The user’s of a Marko UI component do not need to know that the component was
638> implemented using Marko.
639
640Contrast this with React as an example:
641
642```jsx
643import ReactDOM from "react-dom";
644
645ReactDOM.render(
646 <HelloMessage name="John" />,
647 document.getElementById("container")
648);
649```
650
651On top of that, React requires that a different module be imported to render the
652exact same UI component on the server:
653
654```jsx
655import ReactDOMServer from "react-dom/server";
656
657var html = ReactDOMServer.renderToString(<HelloMessage name="John" />);
658```
659
660### Custom tags
661
662#### React JSX
663
664With React, all custom tags for UI components must be explicitly imported:
665
666```jsx
667import Hello from "./components/Hello";
668import GoodBye from "./components/GoodBye";
669
670export default function HelloGoodBye(props) {
671 return (
672 <div>
673 <Hello name={props.name} />
674 <GoodBye name={props.name} />
675 </div>
676 );
677}
678```
679
680#### Marko
681
682Marko supports a mechanism for [automatically discovering custom
683tags](http://markojs.com/docs/custom-tags/#discovering-tags) for UI components
684based on the project directory structure. Marko walks up the directory tree to
685discover all directories and it will also automatically discover custom tags
686exported by installed packages. This approach negates the need for explicitly
687importing a custom tag to reduce the amount of code needed in a Marko template.
688For example given the following directory structure:
689
690```
691 .
692 ├── components/
693 │ ├── hello.marko
694 │ └── good-bye.marko
695 └── index.marko
696```
697
698The `<hello>` tag and the `<good-bye>` tag nested below the `components/`
699directory will automatically be made available to the `index.marko` at the root:
700
701```marko
702<div>
703 <hello name=input.name />
704 <good-bye name=input.name />
705</div>
706```
707
708This approach also allows editors and IDEs to offer autocompletion for custom
709tags.
710
711### Async
712
713Even after rendering has started, Marko allows parts of the view to be rendered
714asynchronously using the [`<await>`](http://markojs.com/docs/core-tags#await)
715tag as shown in the following Marko template:
716
717```marko
718import fsp from 'fs-promise';
719
720$ var filePath = __dirname + '/hello.txt';
721$ var readPromise = fsp.readFile(filePath, {encoding: 'utf8'});
722
723<await(readPromise)>
724 <@then|helloText|>
725 <p>${helloText}</p>
726 </@then>
727</await>
728```
729
730### Compiler
731
732Marko compiles a template differently based on whether or not it will be used on
733the server or in the browser. For example, given the following template:
734
735```marko
736<div>Hello ${input.name}!</div>
737```
738
739#### Compiled for the server:
740
741```marko
742var marko_template = require("marko/html").t(__filename),
743 marko_helpers = require("marko/runtime/html/helpers"),
744 marko_escapeXml = marko_helpers.x;
745
746function render(input, out) {
747 out.w("<div>Hello " +
748 marko_escapeXml(input.name) +
749 "!</div>");
750}
751```
752
753#### Compiled for the browser:
754
755```marko
756var marko_template = require("marko/vdom").t(__filename);
757
758function render(input, out) {
759 out.e("DIV", null, 3)
760 .t("Hello ")
761 .t(input.name)
762 .t("!");
763}
764```
765
766### Compile-time code transforms
767
768The Marko compiler was built to support compile-time code generators for custom
769tags and it also provides support for compile-time transforms. While Babel
770allows code transformations of JavaScript, the Marko compiler provides support
771for resolving custom tags declaratively and the Marko AST provides for very
772powerful and simple transformations as shown in the following code for rendering
773Markdown to HTML at _compile-time_:
774
775**components/markdown/code-generator.js:**
776
777```js
778import marked from "marked";
779import { removeIndentation } from "./util";
780
781export default function generateCode(el, codegen) {
782 var bodyText = removeIndentation(el.bodyText);
783 var html = marked(bodyText);
784 var builder = codegen.builder;
785 return builder.html(builder.literal(html));
786}
787```
788
789The `<markdown>` tag can then be used as shown below:
790
791```marko
792<markdown>
793
794> This section demonstrates Markdown in Marko
795
796# Marko is awesome!
797
798- High performance
799- Small
800- Intuitive
801
802</markdown>
803```
804
805In this example, after the template is compiled, the
806[marked](https://github.com/chjj/marked) library is no longer needed at
807render-time.
808
809### Tools
810
811Marko and React offer a variety of developer tools. The [Marko developer
812tools](https://github.com/marko-js/marko-devtools) are constantly evolving, but
813Marko currently provides tools for unit testing UI components, precompiling `.marko`
814files and generating configuration-less apps (similar to
815[create-react-app](https://github.com/facebookincubator/create-react-app)).
816Currently, there are no Marko developer tools that integrate with the browser,
817but this is something we would like to see in the future. We will go into more
818detail on the Marko developer tools in a future post.
819
820#### IDE and editor support
821
822Marko offers syntax highlighting across all major IDEs and editors, as well as
823on GitHub. Marko provides first-class support for the Atom editor with syntax
824highlighting,
825[Autocomplete](https://github.com/marko-js/atom-language-marko#autocomplete) for
826both HTML and custom tags,
827[Hyperclick](https://github.com/marko-js/atom-language-marko#hyperclick) to
828quickly jump to referenced files and methods, and [Pretty
829printing](https://github.com/marko-js/atom-language-marko#prettyprint) to keep
830your code readable.
831
832---
833
834### Why Marko?
835
836Here are just a few reasons you should consider using
837[Marko](http://markojs.com/) over React:
838
839- Marko requires much less boilerplate.
840- Marko has much better performance based on our benchmarks.
841- Marko offers a clean and powerful syntax that aligns with HTML while also
842 allowing the full power of JavaScript.
843- Marko has much less complexity and a very small runtime.
844- Marko has a much lower page weight for faster page loads.
845- Marko has strong integrations with Node.js.
846- Marko allows for extremely powerful IDE and editor plugins (see the [Marko
847 plugin for Atom](https://github.com/marko-js/atom-language-marko) as an
848 example).
849- Marko has a powerful compiler that allows new features to be added without
850 introducing bloat.
851- eBay relies heavily on Marko and it is being used to build ebay.com (including
852 the mobile web).
853- Marko has a strong and growing community on
854 [GitHub](https://github.com/marko-js/marko) and in
855 [Gitter](https://gitter.im/marko-js/marko).
856
857Interested in learning more about Marko? If so, you can get additional
858information on the [Marko website](http://markojs.com/). Join the conversation
859and contribute on [GitHub](https://github.com/marko-js/marko) and follow us on
860[Twitter](https://twitter.com/MarkoDevTeam).