Skip to content

Instantly share code, notes, and snippets.

@avermeulen
Forked from Pholisa-Fatyela/AlpineJSwithViteJS.md
Last active May 2, 2024 08:34
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save avermeulen/6790ffc7c86c464143ff79a3b57068ed to your computer and use it in GitHub Desktop.
Save avermeulen/6790ffc7c86c464143ff79a3b57068ed to your computer and use it in GitHub Desktop.

AlpineJS with ViteJS

ViteJS is a modern JavaScript build tool that can be used to build modern JavaScript frameworks including ReactJS and VueJS to name only two. In this tutorial you will explore how to use ViteJS with AlpineJS. This will prepare you for using ViteJS with ReactJS or other modern web framework.

Modern JavaScript built tools like ViteJS, ParcelJS & react-create-app (built with webpack) embrace ES Modules. Meaning that external dependencies are installed via npm and imported. So no more script, style or link tags. HTML, CSS & JavaScript are bundled into compact bundle.

Create app using Vite

Let's start exploring ViteJS by creating a new application. Using this command:

npm create vite@latest

Follow the prompts:

  • Enter an app name of quotes-app

  • Pick vanilla twice.

Change into the app folder and do npm install.

Then run npm run dev - this will start an development ViteJS instance that will compile your code in the fly.

It will open up automatically in the browser. If you change some things in main.js and other files the screen will automatically reload in the browser.

Let's test that by quickly

Show the text below in the page by replacing the text that is setting #app element with the text below in main.js.

document.querySelector('#app').innerHTML = "I πŸ’š Alpine JS!"

The browser will refresh automatically, after you save the file if all went well.

Alpine setup

To use AlpineJS in a ViteJS app you install it using npm.

Run the following command to install it:

npm install alpinejs

And then import Alpine in the main.js file

Now import Alpine into your bundle and initialize it like so:

import Alpine from 'alpinejs'
 
window.Alpine = Alpine

Alpine.start()

Create your own module

Next you will create application files in modules and then import them into your application.

We will start it of by creating a LoveCounter counter module.

The module will return hearts based on how much love it has been shown.

  • 1 πŸ’š heart for 5 or less loves,
  • 2 πŸ’šπŸ’š hearts for 10 or less loves,
  • and 3 πŸ’šπŸ’šπŸ’š hearts for 15 or more loves.

You will also note that love wears of.

Create a file called love-counter.js and copy the code into it:

function LoveCounter() {
    return {
      loveCounter : 0,
      init() {
        setInterval( () => {
          if (this.loveCounter > 0) {
            this.loveCounter--;
          }
         console.log(this.loveCounter)
        }, 3000)
      },
      love() {
       this.loveCounter++
      },
      hearts() {
         
         if (this.loveCounter <= 0) {
          return "πŸ’”"
         }
      
         if (this.loveCounter > 0 && this.loveCounter <= 5) {
           return "πŸ’š"
         } else if (this.loveCounter <= 10) {
           return "πŸ’šπŸ’š";
         } else {
           return "πŸ’šπŸ’šπŸ’š";
         }
      }
    }
}

Export the module by adding an export this code:

export function LoveCounter () {

}

In main.js import the LoveCounter factory function and bind it to an AlpineJS data context.

import {LoveCounter} from './love-counter';

In main.js just above Alpine.start() do this:

Alpine.data('loveCounter', LoveCounter);

In the index.html file add the HTML & Alpine directives for the widget.

<div x-data="loveCounter" >
  <h1>Show some heart</h1>
  <div x-text="hearts()" >
  </div>
  <div>
      <button @click="love" >Show πŸ’Ÿ</button>
  </div>
</div>

At this point the Love Counter App should be working.

More on modules

You can change the export for LoveCounter to an default export like this:

export default function LoveCounter () {

}

Then the import in main.js needs to change to this:

import LoveCounter from './love-counter';

You can learn more about es-modules by read this article or by watching this video.

Persist the counter

Make the loveCounter reload after refresh by using the persist plugin.

Using external modules

When using ViteJS you can install npm modules using npm install and then using it with import & require.

We will practice that by installing the everyday-fun module and use it to create a little Quotes Widget. The Widget will show a quote and can press a button to see another quote.

Install the module using: npm install everyday-fun

Import the module in the main.js file

import * as fun from 'everyday-fun';

Use the module in the main.js module like this:

Alpine.data('quoteApp', function(){
	return {
		init(){
			this.quote = fun.getRandomQuote()
		},
		quote : {}
	}
})

Add this to index.html:

<div x-data="quoteApp">
   <div x-text="quote.quote"></div>
</div>

If you see a quote on the screen - it means the everyday-fun module is working. Next we will create a new module file for the logic of the quote app.

Create a module that's using an npm module

Create a quotes.js file. Create a Factory function and add a default export.

export default function Quotes() {

}

In the quotes app we would like to get an initial quote and then have the ability to ask for another quote.

import * as fun from 'everyday-fun';

export default function Quotes() {
    return {
      init() {
       this.getQuote();
      },
      quote : {},
      getQuote(){
        this.quote = fun.getRandomQuote()
      },
    }
}

Remember to import the everyday-fun module. You can remove this module import from main.js.

Next import the Quote function and register it as data directive in main.js


import Quotes from './quote';

Alpine.data('quoteApp', Quotes)

Remove the local instance of the QuoteApp that you created earlier.

Now setup the Quote widget section in the index.html file.

<hr>
<div x-data="quoteApp" class="quoteApp" >
    <h1>Quote App</h1>
    <button @click="getQuote()">Next quote πŸ“’</button>
    <div class="quote">
      <div x-text="quote.quote" class="content" ></div>
      <div>
        <strong>by </strong><span x-text="quote.author"></span>
      </div>
    </div>
  </div>

If all goes well you should see some quotes on the screen with an horizontal line below the earlier LoveCounter widget. Feel free to remove this widget or move it to it own setup.

Style your app

Next lets style our Quote app using a new css file called quote.css and import this file in main.js using and import statement.

import 'quote.css'

Add some classes to it:

.quote {
    background-color: limegreen;
    border-radius : 0.5em;
    padding: 1em;
	margin-top:1em;
	width: 25em;
}

.content {
	margin: 1em 0 1em 0;
}

.quoteApp {
	margin: auto;
	width: 50%;
}

Add a class to the HTML of the quote widget:

<div x-data="quoteApp" class="quote" >
   
</div>

At this stage you should have quote app that shows a new quote when you are pressing the button.

You can add other functionality such as showing a new quote every 5 seconds. Or adding support ot show the previous quote. Or to store quotes you like.

But next up is how to deploy your app.

Deploy your app

To deploy your app you need to add 2 new files - vite.config.js & deploy.sh

Add this into you vite.config.js file:

import { defineConfig } from 'vite'

export default defineConfig({
    base: 'repo-name',
})

Add name of your repo next to the base

Add this to the deploy.sh file - add your own GitHub repo details in this file.

#!/usr/bin/env sh

rm -rf dist
# abort on errors
set -e

# build
npm run build

# navigate into the build output directory
cd dist

# if you are deploying to a custom domain
# echo 'www.example.com' > CNAME

git init
git checkout -b main
git add -A
git commit -m 'deploy'

# Add your GitHub repo details here
git push -f https://github.com/<USERNAME>/<REPO>.git main:gh-pages

# if you are deploying to https://<USERNAME>.github.io
# git push -f git@github.com:<USERNAME>/<USERNAME>.github.io.git main

# if you are deploying to https://<USERNAME>.github.io/<REPO>
# git push -f git@github.com:<USERNAME>/<REPO>.git main:gh-pages

cd -

You might need to make this file executable by running this command:

chmod +x deploy.sh
@Gideon877
Copy link

Ensure that you don't use:

Alpine.date('loveCounter', LoveCounter);

// but use 

Alpine.data('loveCounter', LoveCounter);

@Gideon877
Copy link

Yes, Alpine.date()

@sonyarianto
Copy link

add a router please

@avermeulen
Copy link
Author

@sonyarianto what you have in mind for the router?

@dvd101x
Copy link

dvd101x commented Oct 20, 2023

Hi, I included this repo

https://github.com/dvd101x/vite-alpine
based on the vanilla template https://vitejs.dev/guide/#trying-vite-online

@aalaap
Copy link

aalaap commented May 2, 2024

add a router please

@sonyarianto Alpine.js doesn't need a router as it works within .html files. Simply create other HTML files and link to them with an <a href="...">.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment