How to Use Vue.js Without NPM in Legacy Projects
Did you know that Vue.js can be embedded directly into web pages without build processes and npm? Yes, Vue.js can be integrated just like jQuery that you’ve been using for ages!
Why Use Vue.js from CDN?
If you have legacy websites still using jQuery and want to add modern features without rewriting the entire source code, you can try this easy method to integrate Vue.js through CDN.
Benefits of Using Vue.js via CDN
- ✅ No need for build tools (webpack, vite, etc.)
- ✅ No need to install npm packages
- ✅ Easy integration into old websites
- ✅ Still get modern developer experience
- ✅ No need to rewrite entire application code
Tutorial: Adding Vue.js to Legacy Websites
Here are the complete steps to integrate Vue.js into your web pages:
1. Add Vue.js CDN to HTML <head> Tag
First, add the Vue.js CDN link to the <head> section of your HTML file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue.js CDN Example</title>
<!-- Add Vue.js from CDN -->
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
</head>
<body>
<!-- Your HTML content -->
</body>
</html>
Vue.js CDN Options:
- Vue 3:
https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js - Vue 2:
https://cdn.jsdelivr.net/npm/vue@2 - Unpkg:
https://unpkg.com/vue@3/dist/vue.global.js
2. Define Root Element for Vue.js
Choose an element on the page (e.g., <div id="app">) that will become the Vue application root. This is the area where Vue.js will manage content and interactivity:
<body>
<div id="app">
<h1>{{ message }}</h1>
<button @click="updateMessage">Click Me!</button>
</div>
</body>
3. Write Vue.js Script
Add the Vue.js JavaScript code before the closing </body> tag:
For Vue 3:
<script>
const { createApp } = Vue;
createApp({
data() {
return {
message: 'Hello from Vue.js 3!'
}
},
methods: {
updateMessage() {
this.message = 'Message has been updated!';
}
}
}).mount('#app');
</script>
For Vue 2:
<script>
new Vue({
el: '#app',
data: {
message: 'Hello from Vue.js 2!'
},
methods: {
updateMessage() {
this.message = 'Message has been updated!';
}
}
});
</script>
Complete Example: Simple To-Do List
Here’s a complete implementation of a To-Do List using Vue.js from CDN:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue.js To-Do List</title>
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 50px auto;
padding: 20px;
}
.todo-item {
padding: 10px;
margin: 5px 0;
background: #f4f4f4;
border-radius: 5px;
display: flex;
justify-content: space-between;
align-items: center;
}
.completed {
text-decoration: line-through;
opacity: 0.6;
}
button {
padding: 5px 10px;
cursor: pointer;
}
input[type="text"] {
padding: 8px;
width: 80%;
margin-right: 10px;
}
</style>
</head>
<body>
<div id="app">
<h1>{{ title }}</h1>
<div>
<input
v-model="newTodo"
@keyup.enter="addTodo"
type="text"
placeholder="Add new task...">
<button @click="addTodo">Add</button>
</div>
<div v-if="todos.length === 0" style="margin-top: 20px;">
<p>No tasks. Add your first task!</p>
</div>
<div v-else>
<div
v-for="(todo, index) in todos"
:key="index"
class="todo-item"
:class="{ completed: todo.done }">
<span @click="toggleTodo(index)">
{{ todo.text }}
</span>
<button @click="removeTodo(index)">Delete</button>
</div>
</div>
<p style="margin-top: 20px;">
Total: {{ todos.length }} tasks |
Completed: {{ completedCount }} |
Remaining: {{ remainingCount }}
</p>
</div>
<script>
const { createApp } = Vue;
createApp({
data() {
return {
title: 'My Task List',
newTodo: '',
todos: []
}
},
computed: {
completedCount() {
return this.todos.filter(todo => todo.done).length;
},
remainingCount() {
return this.todos.filter(todo => !todo.done).length;
}
},
methods: {
addTodo() {
if (this.newTodo.trim()) {
this.todos.push({
text: this.newTodo,
done: false
});
this.newTodo = '';
}
},
removeTodo(index) {
this.todos.splice(index, 1);
},
toggleTodo(index) {
this.todos[index].done = !this.todos[index].done;
}
}
}).mount('#app');
</script>
</body>
</html>
Integration with Existing jQuery
You can use Vue.js and jQuery together on the same page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue.js + jQuery</title>
<!-- jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
</head>
<body>
<!-- jQuery Section -->
<div id="jquery-section">
<h2>jQuery Section</h2>
<button id="jquery-btn">Click with jQuery</button>
<p id="jquery-output"></p>
</div>
<!-- Vue.js Section -->
<div id="app">
<h2>Vue.js Section</h2>
<button @click="count++">Click with Vue: {{ count }}</button>
</div>
<script>
// jQuery code
$('#jquery-btn').click(function() {
$('#jquery-output').text('jQuery works!');
});
// Vue.js code
const { createApp } = Vue;
createApp({
data() {
return {
count: 0
}
}
}).mount('#app');
</script>
</body>
</html>
When Should You Use Vue.js via CDN?
✅ Use CDN If:
- Legacy websites that are difficult to completely change
- Small projects or quick prototypes
- Don’t need build tools and modern toolchain
- Want to add interactive features without major migration
- Learning and experimenting with Vue.js
❌ Don’t Use CDN If:
- New projects built from scratch
- Large applications with many components
- Need maximum performance optimization
- Require Single File Components (.vue files)
- Need TypeScript and modern tooling
Vue.js CDN Best Practices
1. Use Production Version
For production, use the minified version:
<!-- Development (with warnings) -->
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
<!-- Production (optimized) -->
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
2. Specify Exact Version
Don’t use @latest, specify an exact version:
<!-- ❌ Not recommended -->
<script src="https://cdn.jsdelivr.net/npm/vue@latest"></script>
<!-- ✅ Recommended -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.global.prod.js"></script>
3. Use SRI (Subresource Integrity)
For security, add integrity hash:
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.global.prod.js"
integrity="sha384-..."
crossorigin="anonymous">
</script>
4. Consider Caching
Use popular CDNs so browsers can leverage cache:
- jsDelivr:
https://cdn.jsdelivr.net/npm/vue@3 - unpkg:
https://unpkg.com/vue@3 - cdnjs:
https://cdnjs.cloudflare.com/ajax/libs/vue/3.4.15/vue.global.prod.min.js
Migrating from jQuery to Vue.js
If you want to start gradually migrating from jQuery to Vue.js:
jQuery Code:
// jQuery
$('#button').click(function() {
$('#output').text('Hello World');
$('#output').addClass('active');
});
Vue.js Equivalent:
<div id="app">
<button @click="updateText">Click</button>
<p :class="{ active: isActive }">{{ message }}</p>
</div>
<script>
const { createApp } = Vue;
createApp({
data() {
return {
message: '',
isActive: false
}
},
methods: {
updateText() {
this.message = 'Hello World';
this.isActive = true;
}
}
}).mount('#app');
</script>
Limitations of Vue.js via CDN
Keep in mind some limitations when using Vue.js from CDN:
- No Single File Components (.vue files)
- No Hot Module Replacement (HMR)
- No automatic code splitting
- No built-in TypeScript support
- No tree-shaking for bundle optimization
- No preprocessors (Sass, Less, etc.)
Alternative: Petite-Vue for Simpler Cases
If you only need basic Vue.js features, consider using petite-vue (only 6KB):
<script src="https://unpkg.com/petite-vue" defer init></script>
<div v-scope="{ count: 0 }">
<button @click="count++">{{ count }}</button>
</div>
Petite-vue is perfect for progressive enhancement and simple interactions.
Conclusion
Vue.js can be easily integrated into legacy websites using CDN, without build processes or npm. This approach is ideal for:
- ✅ Adding interactive features to old pages
- ✅ Improving developer experience without major migration
- ✅ Quick learning and prototyping
- ✅ Gradual transition from jQuery to modern frameworks
However, for new projects and large applications, it’s still recommended to use Vue.js with npm and build tools to get maximum benefits from the Vue.js ecosystem.
Resources
Was this article helpful? If you successfully integrated Vue.js into your legacy website, share your experience in the comments! Don’t forget to subscribe for more Vue.js tutorials! 🚀