Marko

website·Indexed 36 days ago

https://v5.markojs.com

A language for building dynamic and reactive user interfaces by extending standard HTML. Marko v5 features progressive rendering, code elimination, and a compiler API with functions like `compile()` and `compileSync()`. It provides integrations for Vite, Webpack, Rollup, Express, Fastify, Koa, and Cloudflare Workers, and supports TypeScript in versions v5.22.7+ and v4.24.6+.

Tokens
26.9K
Snippets
194
Records
224
Agent score
56%

What's inside Marko

  1. Introduction to Marko syntax and basic usage

    Marko is a language for building dynamic and reactive user interfaces that extends standard HTML. It allows for declarative application building using HTML templates, custom tags, and JavaScript expressions. It supports looping through data using the <for> tag and dynamic attribute binding using backticks.
    <!doctype html>
    <html>
    <head>
        <title>Hello Marko</title>
    </head>
    <body>
        <h1>My favorite colors</h1>
        <ul>
            <for|color| of=["red", "green", "blue"]>
                <li style=`color:${color}`>
                    ${color.toUpperCase()}
                </li>
            </for>
        </ul>
        <shared-footer/>
    </body>
    </html>
  2. Clean up resources in Marko class components using onDestroy

    The onDestroy() method is called when the component is about to unmount from the DOM and be cleaned up. Use this method to perform manual cleanup, such as destroying third-party library instances.
    import scrollmonitor from 'scrollmonitor';
    
    class {
        onMount() {
            this.watcher = scrollmonitor.create(this.el);
        }
        onDestroy() {
            this.watcher.destroy();
        }
    }
  3. Work with tags and discovery in Marko

    Marko supports native HTML/SVG tags, core tags, custom tags, and third-party tags from npm. Tags do not need to be imported; Marko discovers them based on the folder structure, looking in the components/ directory by default (configurable via marko.json).
    <my-tag-name/>
  4. Execute logic before rendering with onRender

    The onRender(out) method is called when the component is about to render or rerender. It provides access to the async out object for the current render cycle.
  5. Understand Marko's dual compilation strategy

    Marko is an isomorphic library that uses different compilation outputs depending on the target environment to maximize performance. Instead of using a single representation, it compiles views into programs optimized for the specific platform:

    1. Server-side: Compiles directly to a string representation (HTML) for streaming. This avoids the overhead of creating an intermediate virtual DOM tree and then serializing it, allowing for a single-pass render.
    2. Browser-side: Compiles to a program that renders to a virtual document (VDOM) tree, enabling efficient updates to the real DOM.
  6. Compare Marko and React component architecture

    Marko and React both use a UI component-based architecture with virtual DOM rendering in the browser, internal state, and input properties. However, Marko differs in several key ways to reduce boilerplate and improve performance:

    • State Management: Marko allows direct modification of state (e.g., this.state.count++) and updates are synchronous, whereas React requires setState and updates may be asynchronous.
    • Class Definition: Marko does not require explicit extension of a base component class (unlike extends React.Component).
    • Purity: Marko components are pure by default and skip re-rendering if state/inputs are unchanged, whereas React requires extending React.PureComponent for this behavior.
    • File Structure: Marko supports single-file components that combine JavaScript, HTML, and CSS (including preprocessors) natively.
  7. Import external files into Marko templates

    Use the standard JavaScript import statement to access data and functions from external files within a Marko template.
    import sum from './utils/sum';
    <div >The sum of 2 + 3 is ${sum(2, 3)}</div>
  8. Create a new Marko application using the CLI

    The recommended way to start a new Marko project is using the npm init marko command. This launches an interactive CLI that allows you to choose a starter template. The basic template is the most minimal option and uses the Marko Run framework, which provides built-in file-based routing, automatic code reloading, and handles building, bundling, and serving without requiring manual configuration.
    npm init marko
  9. Use shorthand for classes and IDs

    Marko provides a concise shorthand for adding CSS classes (.className) and IDs (#idName) to elements, which also supports interpolation.
    <div.my-class/> <!-- <div class="my-class"></div> -->
    <span#my-id/> <!-- <span id="my-id"></span> -->
    <button#submitprimary.large/> <!-- <button id="submit" class="primary large"></span> -->
    <button.button--${size}></button> <!-- <button class="button--small"></span> (if size='small') -->
  10. Handle user events in Marko components

    You can define a JavaScript class directly within a .marko file to handle logic. Methods defined in this class can be called from the view using on- attributes (e.g., on-click).
    class {
        sayHi() {
            alert("Hi!");
        }
    }
    
    <button on-click("sayHi")>Click me!</button>
  11. Implement custom Marko compiler hooks

    Marko compiler hooks allow extending the compilation process. Hooks must export a Babel-style visitor function (or an enter/exit pair) that receives a NodePath with a MarkoTag node and a types object (a superset of @babel/types).

    Available stages:

    • Parse: Converts raw text to AST. Must return a replacement AST node; does not support enter/exit API.
    • Migrate: Translates outdated APIs to modern ones. Set output: "migrate" to stop here.
    • Transform: Userland transformations of Marko code into other Marko code.
    • Analyze: Non-mutative analysis. Metadata should be stored in the .extra property of nodes.
    • Translate: Converts the Marko AST into optimized JavaScript.
    // Example hook: removes tags with a specific string literal name
    export default (tag, types) => {
      if (types.isStringLiteral(tag.node.name)) {
        console.log(`Found a tag called ${tag.node.name.value}`);
        tag.remove();
      }
    };
  12. Quick start with Marko and Express

    The fastest way to start a Marko project with Express is to use the official Vite-Express template via the CLI.
    npm init marko -- --template vite-express
    # Or
    npx create-marko --template vite-express