Up and Running with Marko and Vite!
Tags: javascript, webdev, marko, tutorial
Published: 2021-05-21 00:02:57

In this tutorial I will show you some of the basics of Marko.js and getting it set up with Vite.js!

## Why Marko

Marko.js is a JS framework that is SSR (server-side rendered) by default with an MPA (multi-page app) architecture. [eBay](ebay.com) runs on it. It has been around for a few years but has gotten a lot of updates lately, like the new Vite plugin. Additionally new features that are coming soon like a concise syntax and improved performance will make Marko.js a great choice for many JS devs. 

Did I mention even Dan Abramov (of the React core team) said we're on track to go where no JS framework has gone before? 

 {% twitter  1377343141485764610 %}

## MPA + SSR -- By Default! 

Marko's MPA architecture allows it to run without needing a router like React Router or Vue Router, making things that much simpler for devs. And because it is SSR by default, there is no need to worry about anything like Next.js or Gatsby. 

In this tutorial I will show how this all works. 

## Why Vite.js

Vite, like Webpack, takes care of your bundling needs, putting all of your HTML, CSS, JS and in our case `.marko` files together to serve to the browser.

Unlike Webpack, Vite is WAY faster and has an extremely minimal configuration. In this case we'll just use the command line and we won't have to worry about any configuration! 

Vite also gives us hot module reloading, so when you save, the page automatically reloads. This is a very nice feature  because you don't have to restart your dev server when you make changes to your code, it just reloads itself for you. 

## Let's Go!

First, you need NPX installed. If you haven't done that yet, go [here](https://github.com/nvm-sh/nvm) and follow the instructions to install NVM, which will then allow you to get Node.js and NPX on your device.

[Here](https://github.com/austingardner/marko-vite-blog) is the repo for the finished code if you don't want to go through the tutorial step-by-step.

We'll call our app's directory marko-vite. Let's run `npx @marko/create marko-vite` in the command line. Then arrow down to `Example from marko-js/examples`, hit enter, then arrow to `vite-express` and hit enter again. 

A directory named marko-vite will be generated for us. 

Open it up in your code editor, and let's nuke some things. 
Delete the components, pages, and services directories.

Next, make a new pages directory and put a file called index.js into it, with the following code: 

```js
import template from "./template.marko";

export default (req, res) => {
  res.marko(template, {});
};

```

This just tells our server when it comes to this page, to load in our Marko template.

Next, let's make a basic Marko page! 

Make a new file in the src/pages/ directory and call it `template.marko`, and add the following code: 

```html
<!DOCTYPE html>
<html>
<head>
  <title>Marko + Vite</title>
</head>
<body>
<h1>Hello World!</h1>
<div>
    <a href="/goodbye">Goodbye!</a>
</div>
<div>
    <a href="/counters">Count!</a>
</div>
</body>
</html>
```

WAIT! Doesn't that look just like HTML? Marko is a superset of HTML, so anything that is HTML can be taken care of by Marko. 

Next, let's make a file named goodbye.js in the src/pages directory and put the following code in: 

```js 
import goodbye from "./goodbye.marko";

export default (req, res) => {
  res.marko(goodbye, {});
};
```

and another file called goodbye.marko: 

```html
<!DOCTYPE html>
<html>
<head>
  <title>Marko + Vite</title>
</head>
<body>
<h1>See you later world!</h1>
<div>
    <div>
        Bye Bye!
    </div>
    👋
</div>
<div>
    <a href="/">Hello Again!</a>
</div>
</body>
</html>
```

Then let's update the src/index.js file to make sure we have the right routes. We'll worry about the `/counters` in a little bit: 

```js
import { Router } from "express";
import indexPage from "./pages/index";
import goodbyePage from "./pages/goodbye";

export default Router()
  .get("/", indexPage)
  .get("/goodbye", goodbyePage)
```

## Running the project

Now let's run the project! run `npm run dev` and navigate to `localhost:3000`. You should see something like this: 

![Screen Shot 2021-05-20 at 4.03.13 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ofe9qujunkrjwf408rwe.png)

and then if you navigate to the goodbye link, you should see something like this: 

![Screen Shot 2021-05-20 at 4.03.23 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t48rkpaysr96sssm0eiz.png)

But wait! We haven't added JS to the browser yet! Let's keep rolling!

## Adding Components!

let's make a file in `src/pages/` called `counters.js` and add the code:

```js
import counters from "./counters.marko";

export default (req, res) => {
  res.marko(counters, {});
};
```

then another file in `src/pages/` called `counters.marko` and add the code: 

```html
<!DOCTYPE html>
<html>
<head>
  <title>Marko + Vite</title>
</head>
<body>
<h1>Count 'em up!</h1>
<div>
    <counter/>
    <counter/>
    <counter/>
    <counter/>
    <counter/>
</div>
<div>
    <a href="/">Back to home</a>
</div>
</body>
</html>
```

Woah! This looks different... where are those counter tags coming from? That's no longer valid HTML! You see, Marko automatically detects Marko components in our `src/` directory, and then adds them into their respective places. Pretty nifty!

## Adding Counters

Let's make a new directory under `src` called `components` and then make the file `src/components/counter.marko`. Then let's add the code: 

```html
class {
    onCreate() {
        this.state = {
            count: 0
        };
    }
    increment() {
        this.state.count++;
    }
}

<div>
    Count is: <output>${state.count}</output>
</div>
<div>
    <button on-click('increment')>
        Click Here!   
    </button>
</div>
```

Here we have a basic counter, which increments based on the on-click handler we added to the button. Marko allows us to combine the JS and the HTML in one page in this way! 

(There are cases where you can or should separate out the JS from the .marko file -> see [Marko docs](https://markojs.com/docs/class-components/) for more info).

Now we're almost ready to show off our counters! We just need to add the new `<a/>` tag into our `template.marko` file and add the routes into our `src/index.js` file. 

Now our `src/index.js` file will look like this: 

```js
import { Router } from "express";
import indexPage from "./pages/index";
import goodbyePage from "./pages/goodbye";
import countersPage from "./pages/counters";

export default Router()
  .get("/", indexPage)
  .get("/goodbye", goodbyePage)
  .get("/counters", countersPage);
```

and our `src/pages/template.marko` like this: 

```html
<!DOCTYPE html>
<html>
<head>
  <title>Marko + Vite</title>
</head>
<body>
<h1>Hello World!</h1>
<div>
    <a href="/goodbye">Goodbye!</a>
</div>
<div>
    <a href="/counters">Count!</a>
</div>
</body>
</html>
```

Notice how on saving the files, Vite re-runs things for us - that is hot module reloading at work. Then from our base page, clicking on the `count!` link gives us a lot of buttons to click on! Alright!! 

![Screen Shot 2021-05-20 at 4.15.31 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9qtlovipix0yal3gqq56.png)
 
## Conclusion

Here we can see that using Marko with Vite allows us to use some shortcuts compared to React. SSR by default, no router needed. 




## Read more about the future of Marko!

See Ryan Carniato's posts [FLUURT overview](https://dev.to/ryansolid/fluurt-re-inventing-marko-3o1o) for an overview of the future changes to Marko; [UI language](https://dev.to/ryansolid/marko-designing-a-ui-language-2hni) for more specifics on the conciseness of Marko's future syntax; and Michael Rawling's [Maybe you don't need that SPA](https://medium.com/@mlrawlings/maybe-you-dont-need-that-spa-f2c659bc7fec) about how Marko's server-native architecture puts Marko on the path to sub-component level hydration, enabling high levels of SSR performance.