Skip to main content

Architecture | Vue JS 3 Application Without Build

Introduction

Not long ago I wrote a brief article describing how to create a simple Vue JS application without any build pipeline. It was received with a lot of interest and feedback. Many readers have asked whether a similar feat would be possible with the upcoming Vue 3 release of the framework. The answer turns out to be positive. Also with Vue 3 one can go quite far and enjoy the powers of the progressive web framework without any build process.

The original article about Vue 2 version can be found at https://letsdebug.it/post/minimalistic-vue. Below we describe how a similar setup can be realized with Vue 3.

Source code for the article can be found at https://bitbucket.org/letsdebugit/minimalistic-vue-3.

Application Design

Similar to the Vue 2 example, we will create a small one-page web application with a header, content area and a footer. In the content area there’s a message and a button. When user clicks on the button, the message changes. The UI is made of Vue components represented by custom HTML tags.

Project structure

The project is structured identically as Vue 2 version:

index.html
index.js
index.css
header/
    header.js
    header.css
content/
    content.js
    content.css
footer/
    footer.js
    footer.css

Our logical UI components are clearly reflected in the physical structure of the project. There are changes though inside the components’ code, as described below.

Bootstrapping

When browser loads index.html, the following happens:

  • Vue JS v.3 library is fetched from CDN repository at https://unpkg.com/[email protected].
  • Component stylesheets are fetched
  • Application module is imported from index.js and executed

When index.js is executed, it imports and registers subsequent modules which contain our components:

  • Content from /content/content.js
  • Header from /header/header.js
  • Footer from /footer/footer.js

Finally it creates application instance and mounts it into <main> tag inside index.html file.

Components

With the new version of the framework we can utilize the new functional programming model a.k.a. Composition API. Instead of data, computed and methods sections we will use the setup() function, which will wire up all the internals of the components. To ensure propagation of data to UI and reaction to changes, we will use reactive and computed wrappers provided by the Composition API.

Component code is structured as follows:

    const template = `
      <div>
      ...
      </div>
    `

    export default {
      template,

      setup () {
      }
    }

As an example, we present footer component which displays some text on the left and a ticking clock on the right:

    const { reactive, computed } = Vue

    const template = `
      <footer>
        <div class="left">
          <slot></slot>
        </div>
        <div class="middle">
        </div>
        <div class="right">
          Current time: <b>{{ state.nowString }}</b>
        </div>
      </footer>
    `

    export default {
      template,

      setup () {
        const state = reactive({
          now: new Date(),
          nowString: computed(() => state.now.toTimeString().substr(0, 8))
        })

        window.setInterval(() => {
          state.now = new Date()
        }, 1000)

        return { state }
      }
    }

The main application component is in the index.js file. Its task is to assign custom HTML tags such as <app-header> or <app-footer> to all our components.

    import Header from './header/header.js'
    import Content from './content/content.js'
    import Footer from './footer/footer.js'

    const { createApp } = Vue

    const App = createApp({
      components: {
        'app-header': Header,
        'app-content': Content,
        'app-footer': Footer
      }
    }

    window.addEventListener('load', () => {
      App.mount('main')
    })

These custom tags are then used to build our application UI in index.html file. We ended up with a UI which is trivially simple to read:

    <!doctype html>
    <html>

    <head>
      <meta charset="utf-8">
      <title>Minimalistic Vue 3</title>
      <link rel="stylesheet" href="index.css">
      <link rel="stylesheet" href="header/header.css">
      <link rel="stylesheet" href="content/content.css">
      <link rel="stylesheet" href="footer/footer.css">
      <script src="https://unpkg.com/[email protected]"></script>
      <script src="index.js" type="module"></script>
    </head>

    <body>
      <main>
        <app-header bg-color="#c5cae2">
        </app-header>

        <app-content>
        </app-content>

        <app-footer>
          (c) Tomasz Waraksa, Dublin, Ireland
        </app-footer>
      </main>
    </body>

    </html>

Summary

In the end, we have nearly the full power of Vue 3 including the awesome Composition API, all without any complexities of a build process. To deploy this application we would simply copy the files to a web server.

References

The complete source code can be found at https://bitbucket.org/letsdebugit/minimalistic-vue-3. Feel free to clone and reuse this code. Any suggestions or questions are most welcome!

All credits and thanks go to the creators of the awesome Vue JS framework.