Introducing AdonisJS - Setup up Laravel mix
Tags: adonisjs, tailwindcss, node
Published: 2020-11-17 07:36:13

In this post, we will learn how to use the AdonisJS template engine (Edge) and set up Webpack/Laravel mix to process TailwindCSS and Alpine.js.

## Views & Templates

The official and the recommended template engine of AdonisJS is Edge. It is a logical template engine and comes with some neat features like:

- An easy to write syntax
- Support for conditionals, loops, layouts, and partials
- Support for components **(a personal favorite)**
- Allows runtime debugging using Chrome DevTools
- Accurate stack traces

We won't be covering every feature of the edge in this series and just focus on the pieces we need for our todo app.

### Rendering views

Open the `start/routes.ts` file and replace all of its contents with the following code snippet.

```ts
import Route from '@ioc:Adonis/Core/Route'

Route.get('/', 'TodosController.index')
```

Assuming you already have the `TodosController` from the previous post. Replace its contents with the following code snippet.

```ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

export default class TodosController {
  public async index({ view }: HttpContextContract) {
    return view.render('todos/index')
  }
}
```

- The `view.render` methods takes the path to the template file stored inside the `resources/views` directory.
- Adding a file extension is optional.
- The return value is a string. In our case, it will be a string containing the final HTML.

You can also render views using the `Adonis/Core/View` module directly. For example:

```ts
import View from '@ioc:Adonis/Core/View'
View.render('todos/index')
```

However, there is a difference between using the module directly and using the `ctx.view` object.

The `ctx.view` object also contains the information about the current HTTP request like **the request details**, **authenticated user**, **session flash messages** and so on. Therefore it is recommended to always use `ctx.view` during an HTTP request.

### Creating the view file

Let's create the `todos/index.edge` file using the following ace command.

```sh
node ace make:view todos/index

# CREATE: resources/views/todos/index.edge
```

Open the newly created file and paste the following contents inside it.

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  </head>

  <body>
    <h2>Todos app</h2>
    <p>We will being rendering todos here</p>
  </body>
</html>
```

Finally, visit the http://localhost:3333 URL to view the rendered HTML.

![](https://res.cloudinary.com/adonis-js/image/upload/v1605591018/devto/render-views_cpxna2.gif)

## Serving static assets

Everything we have done so far is on the server-side. However, we do need some way to style our webpages using CSS and also write front-end JavaScript to make the pages interactive.

Let's **start with the basics** and slowly move towards using a build tool like [Webpack](https://webpack.js.org) to bundle the front-end assets.

To begin with, we need some way to serve CSS and JavaScript files to the browser. In AdonisJS, you need to keep these files inside the `public` folder and then access them using the relative path. Let's give it a try.

Create a new file named `styles.css` inside the `public` directory and paste the following contents to it.

```css
body {
  background: #d7dceb;
  background: -webkit-linear-gradient(to right, #d7dceb, #e2e2e2);
  background: linear-gradient(to right, #d7dceb, #e2e2e2);
}
```

Now, visit http://localhost:3333/styles.css to access the file inside the browser.

![](https://res.cloudinary.com/adonis-js/image/upload/v1605592988/devto/serve-css-file.png)

Great! Lets open `resources/views/todos/index.edge` and load this css file.

```html
<head>
  <!-- Other tags -->
  <link rel="stylesheet" href="/styles.css" />
</head>
```

The same process can be repeated for JavaScript files, images, fonts, and so on.

## Using assets bundler

In the previous section, we accomplished the task of serving static files by adding them to the `public` folder. Of course, these files have to be written in a way that browsers can understand, parse, and execute.

However, we live in a complicated world. We are so much used to using pre/post processors. Writing code that browsers cannot fully understand. Therefore we need tools like Webpack to compile our version of code into something different browsers can understand.

### Using Laravel Mix

The Laravel community (Jeffrey Way to be specific) created [Laravel mix](https://laravel-mix.com) which wraps webpack into a high level, less verbose API. Even though the package uses the keyword `Laravel`, it can be used independently as well.

Luckily, there is also [a package](https://github.com/wahyubucil/adonis-mix-asset) for AdonisJS that eases the setup process of using Laravel mix in AdonisJS apps.

So let's start by installing it.

```sh
npm i --save-dev adonis-mix-asset laravel-mix@next
```

Run the following command to configure the package.

```sh
node ace invoke adonis-mix-asset

# CREATE: webpack.mix.js
# UPDATE: .adonisrc.json { commands += "adonis-mix-asset/build/commands" }
# UPDATE: .adonisrc.json { providers += "adonis-mix-asset" }
# CREATE: ace-manifest.json file
```

And start the compilation process by running the following ace command. Also, feel free to reference the [README file](https://github.com/wahyubucil/adonis-mix-asset/blob/master/README.md) of the adonis-mix-asset package.

```sh
node ace mix:watch
```

### Setup TailwindCSS

We are all set now! Before giving this set up a test run let's also install and configure [Tailwind CSS](https://tailwindcss.com).

```sh
npm i -D tailwindcss

# Create a Tailwind config file
npx tailwindcss init
```

Open the `webpack.mix.js` file and add the following line of code inside it.

```js
mix.postCss('resources/css/styles.css', 'public/css', [require('tailwindcss')])
```

- Here we tell mix to process the `resources/css/styles.css` file using PostCSS.
- The output should be written to the `public/css` folder.
- Also, we are using tailwind as a plugin of PostCSS.

---

**Why resources folder and not public?**
If you noticed we are telling PostCSS to read the file from the `resources/css` folder and not the public folder.

The PostCSS syntax is not something the browsers can understand and hence there is no point in keeping this file inside the `public` folder. Instead, we want the processed output to be in the `public` folder.

This is true for every other file including the frontend JavaScript, images, and so on. Any asset that needs pre-processing should not be in the `public` folder.

---

Let's remove everything we added to the `public` folder earlier.

```sh
rm -r public/*
```

Create a new file named `css/styles.css` inside the `resources` directory and paste the following contents inside it.

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

Finally, we need to update our template to load the CSS file created by Laravel mix inside the `public` folder.

```html
<link rel="stylesheet" href="/css/styles.css" />
```

Let's give it a try now. Run the following commands to start the HTTP server and the mix process.

```sh
# Starts AdonisJS server
node ace serve --watch

# Inside another terminal session
node ace mix:watch
```

Now open the webpage inside the browser and for sure you will see TailwindCSS getting loaded on the page.

![](https://res.cloudinary.com/adonis-js/image/upload/v1605596414/devto/loading-tailwind_rs3pxe.gif)

### Setup Alpine.Js

Let's quickly follow the same process for setting up Alpine.js. Begin by installing the package.

```sh
npm install alpinejs
```

Create a JavaScript file named `app.js` inside the `resources/js` directory and paste the following contents inside it.

```js
import 'alpinejs'
```

Next, tell mix to pre-process this file by adding the following line of code to the `webpack.mix.js` file.

```js
mix.js('resources/js/app.js', 'public/js')
```

Also, make sure to restart the `node ace mix:watch` command for the mix to pick up the config file changes.

Finally, we can load the processed JavaScript file inside the head tag.

```html
<script src="/js/app.js" defer></script>
```

To give it a test run, modify the `body` tag as follows.

```html
<body x-data="{}" x-init="() => alert('Alpine is ready')">
  <h2>Todos app</h2>
  <p>We will being rendering todos here</p>
</body>
```

## Closing notes

Initially, I decided to even design the webpage in the post. However, we already covered a lot of ground, so let's move the design phase to the next post.

Today we learned about

- Rendering views using the `ctx.view.render` method.
- Server front-end assets by keeping them inside the `public` folder.
- Setup `adonis-mix-asset` to process the front-end assets and write them to the `public` folder.