Using Vue.js Single File Component Without Module Bundlers

James Wee
6 min readMay 16, 2019

--

By the end of this article, you will be able to use Vue.js Single File Component in your web project without using any Module bundlers like Webpack.

Table of Content:

Introduction

In 2019, jQuery is still the most broadly used Web Frameworks on the web despite it ranking #2 as the most dreaded Frontend Web Frameworks.

When I think of jQuery I think of spaghetti and 5000 lines of Javascript file 😨

One of the key factors why so many developers are still stuck with jQuery is the fact that Module Bundlers like Webpack and Rollup are notoriously difficult to setup and maintain.

When I made the transition from jQuery to Vue.js two years ago, the motivation was to use Vue’s Single File Component (SFC), it was the main selling point for me.

Vue Single File Component (SFC) is the single most powerful onboarding feature of the framework that make onboarding process from jQuery to Vue much, MUCH, MUCH easier compared to other frameworks.

However, back then, it was impossible to use Vue SFC without Webpack. Now, it is very much possible to use Vue SFC without a module bundler. But before we start, let’s see how simple a Single File Component looks like.

This is Vue in its simplest form using its SFC taken from Vue’s documentation.

Excited? Now, I am going to show you how we can start a new project using Vue Single File Component without using any Module Bundlers. Let’s get started.

Quick & Dirty Setup (TLDR Setup)

Vue makes it too easy for us to use it in our existing application. If you want to get into the thick of things quickly without needing to worry about how code maintenance (like a hackathon), we can achieve this using just two (2) files.

.
├── index.html
└── js
└── components
└── myComponent.vue
/index.html

Let’s break down the code in the gist above.

<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/http-vue-loader"></script>

We are loading vue and http-vue-loader from the script tag via unpkg. Unpkg.com is a CDN for everything in npm.

<div id="app">
<span>Hello</span>
<app-world></app-world>
</div>

This part creates the HTML required for our Vue component to mount on. This will allow Vue to create a component tree from div#app. Our app will contain only one component called app-world. You can create as many as you want later.

new window.Vue({
el: '#app',
components: {
'app-world': window.httpVueLoader('/js/components/AppWorld.vue')
},
})

With window.Vue and window.httpVueLoader attached on the global (window) scope. This is how we initialize a new root Vue instance and mount it on #app. We are going to use httpVueLoader to load the AppWorld.vue component using a valid http path. Our component is can later be used as <app-world> in the HTML.

The AppWorld.vue will contain everything required to render a highlighted word “World” and log “Hello World” to the inspector console.

/js/components/AppWorld.vue

Next, this is just a typical Vue SFC, see how the scoped feature is supported as well. Do take note that I am using module.exports instead of export default. This is because httpVueLoader does not resolve modules required using the export syntax yet.

Simply run this project using Web Server for Chrome extension and and congratulations! You have loaded your first Vue SFC without even touching Webpack!

This kind of setup is perfect for hackathons, hacks and tests. However, for a real modern applications, we want to version control our dependencies and load the correct version every time. To do that, we are going to utilize the npm package called @pika/web(Pikaweb).

Let’s do it with a bit more elegance this time.

1. Get Started & Installation

Pikaweb makes it very easy for us to load dependencies that supports ES Modules from node_modules. Let’s start a new project with npm init and install our dependencies.

npm init
npm install -D @pika/web
npm install -S vue http-vue-loader

2. Configuration

Pikaweb by default will use whichever ES Module (ESM) set by your dependencies. This is often not what we want, so let’s define the paths to the correct distribution files in our dependencies. In your package.json file. Add the following property at the end:

{
"name": "My Version Controlled Project"
"dependencies": { ... }
"devDependencies": { ... }
"@pika/web": {
"webDependencies": [
"vue/dist/vue.esm.browser.js",
"http-vue-loader/src/httpVueLoader.js"
]
}

}

Explanation

The vue.esm.browser.js is a new distribution type introduced in Vue 2.6 that allows Vue to be imported as an ESM, use vue.esm.browser.min.js instead in production.

Next, the dist file for http-vue-loader is written in UMD. We can’t directly use those as ESM. To solve this problem, Pikaweb utilizes Rollup that utilizes rollup-plugin-commonjs to convert the file into an ESM. Some magic going on there. Let’s just roll with it 😏.

After you have updated the package.json file, execute Pikaweb like this in your terminal:

npx @pika/web

This will copy your dependencies specified in package.json into the web_modules folder. You should get something like this in the terminal:

3. Create Your Application Files

This is very much similar to the hackathon project earlier. Except this time you will have all the dependencies are version controlled with npm. Let’s create the files anyway.

.
├── package.json
├── node_modules
├── web_modules
├── index.html
└── js
├── app.js
├── components
└── myComponent.vue

Before we go to the code, remember Pikaweb copies our dependencies as ES modules into the web_modules folder. To use them, we have to call our script with type=”module”, like this:

<script type="module" src="path/to/file"></script>

This allows us to load the file as a module use import/export syntax in our code.

Let’s move on and edit our index.html file.

/index.html

Note that we shifted all our javascript code into app.js and import it as a module. This is all possible because of type=”module”. Here’s how app.js will look like.

/js/app.js

I just love the fact that we can use ES Modules in evergreen browsers right now. Goodbye spaghetti jQuery code.

The AppWorld.vue remains the same.

/js/components/AppWorld.vue

That’s it. Load it with Web Server For Chrome and you should get the same output as before.

If you’re new to Vue.js, you may not get the block of text that says:

“You are running Vue in development mode”

That is an output provided by vue-devtools. The must-have development tool if you’re developing on Vue. You can download it from Google Chrome.

Now is the time to start hacking and begin exploring new features provided by the Vue.js library. If you get stuck, I’ve setup an example on Github as a reference. Download or clone it to get started immediately.

Caveats

At the time of writing, around 85% of the world’s browsers support ESM. This example will not work on IE11.

There will also not be any code-splitting goodness here. But like Pikaweb said:

“In 2019, you should use a bundler because you want to, not because you need to.”

With large applications, I would still want to use a module bundler, mainly because Webpack & Rollup are both really good software and I recommend them. I use Webpack in my projects on a daily basis.

That’s It!

Thanks for reading. I hope I have delivered value and have helped you. Would love to hear what you guys think about this approach and happy to hear your suggestions on how to improve this.

If you like the content, help me share it around. You can also connect with me via social media at:

--

--

James Wee

⚡️Self Taught Web Programmer ⚡️Entrepreneur ⚡️Business Strategist ⚡️Creative & Digital Expert