Vue.js course Β· Module 1: Vue and Vite
Diagnostic Tools
In this lesson5
In space, diagnostics are a matter of life and death. Vue DevTools is our system scanner.
A panel shows a wrong reading and you don't know why: is it the data, the template, or maybe the component never rendered at all? Adding console.log in ten places is guesswork. You need tools that show you the inside of a running application.
Vue DevTools
Vue DevTools are the official developer tools for Vue; versions 7 and later support only Vue 3. The first way to install them is the browser extension:
- Chrome: Vue.js devtools
- Firefox: Vue.js devtools
- Edge: Vue.js devtools
The second way is the vite-plugin-vue-devtools plugin, which the create-vue wizard adds to the Vite configuration for you. In development mode you then open the panel with a button at the bottom of the page, without installing anything in the browser. In Vite projects I recommend exactly this way - the DevTools documentation recommends it because of its additional features.
Diagnostic Features
- Component Inspector - scan the module tree
- State Inspector - monitor reactive data in real time
- Timeline - track event and change history
- Router - debug navigation
- Pinia - manage the mission database
In current versions, the component inspector and the state inspector form one Components tab: the tree on the left, and on the right the data of the selected component, which you can edit live. The tree of a typical application looks like this:
1App
2βββ MainLayout (layout: header, sidebar)
3 βββ DashboardView (view)
4 βββ OxygenCard (UI)
5 βββ AlertButton (UI)At the top stands the root component, below it the layout, inside the layout a view, and at the end the smallest interface elements. Click any node and you'll see its data next to it.
Debugging Protocols
Logging system changes
Sometimes you want to react to every change, for example log it to the console or raise an alarm. That's what the watch function is for: the first argument is the watched source, the second is a function that Vue calls after every change, with the new and the old value:
1import { ref, watch } from 'vue'
2
3const oxygenLevel = ref(98.5)
4
5// Change monitoring
6watch(oxygenLevel, (newLevel, oldLevel) => {
7 console.log(`Oxygen level: ${oldLevel}% β ${newLevel}%`)
8
9 if (newLevel < 90) {
10 console.error('ALERT: Low oxygen level!')
11 }
12})Set oxygenLevel.value to 88, and the console shows an entry with an arrow followed by a red alert. watch doesn't display anything and doesn't change the oxygen level - it only reacts. The difference from computed is simple: computed calculates a value, watch performs an action.
Debug in template
The second technique is a diagnostic panel in the template. The v-if directive displays an element only when the condition is true, and JSON.stringify turns an object with data into readable text:
1<template>
2 <!-- Diagnostic panel -->
3 <div v-if="debugMode" class="debug-panel">
4 <pre>{{ JSON.stringify(systemData, null, 2) }}</pre>
5 </div>
6
7 <!-- Critical indicators -->
8 <div class="critical-systems">
9 <span>O2: {{ oxygen }}%</span>
10 <span>Temp: {{ temperature }}Β°C</span>
11 <span>Pressure: {{ pressure }} hPa</span>
12 </div>
13</template>When debugMode is false, Vue doesn't create the diagnostic panel at all, and the indicators below it keep working unchanged. The variables used in the template are declared as ref() in the <script setup> section omitted here.
Sensor simulator
For testing, a field in which you type a reading comes in handy. The v-model directive binds the field to a container in both directions: the number you type goes into oxygen, and a change of oxygen in the code goes into the field. The v-if and v-else pair displays one of two paragraphs:
1<template>
2 <input v-model="oxygen" type="number" />
3 <p v-if="oxygen >= 90">Oxygen normal</p>
4 <p v-else>ALERT: low oxygen level</p>
5</template>
6
7<script setup>
8import { ref } from 'vue'
9
10const oxygen = ref(95)
11</script>Type 85, and the alert replaces the normal message. v-else must come right after the element with v-if, because it refers to its condition. You'll learn conditional directives in the Hologram Workshop and forms with v-model in the Control Simulator.
Hot Module Replacement
Vite automatically updates modules without restarting, and the server terminal reports which file it swapped:
112:04:31 [vite] (client) hmr update /src/components/LifeSupport.vueThe time format depends on your system settings, and (client) stands for the browser environment. Changes are visible instantly - critical during system development!
Operational Commands
| Command | Description |
|---|---|
npm run dev | Development mode (simulator) |
npm run build | Compile for deployment |
npm run preview | Test production version |
npm run test:unit | Run unit tests (Vitest) |
npm run lint | Check code quality |
These are scripts from package.json that the wizard adds depending on the options you chose - hence test:unit instead of plain test. A typical work cycle: npm run dev, editing components, a refresh through HMR, and before deployment npm run build followed by checking the result with npm run preview.
Preparing for Deployment
The build runs in four stages. Vite starts from index.html and finds the entry script in it. Then Rolldown loads the modules one by one: each is transformed first (the Vue plugin compiles .vue files, and the Oxc tool turns TypeScript and JSX into JavaScript), and only then does Rolldown read its imports and fetch the next files, building a dependency graph. Next, Rolldown bundles the modules into chunks, removes unused code and minifies the result, and finally the files land in the dist folder. Up to version 7 the transformation was done by esbuild and the bundling by Rollup.
1# Compile the system
2npm run build
3
4# Output in /dist directory
5dist/
6βββ index.html
7βββ assets/
8β βββ index-[hash].js # Compiled logic
9β βββ index-[hash].css # Compiled styles[hash] is a fingerprint of the file's contents: when the code changes, the name changes too, so the browser won't use an old version from its cache. npm run preview serves this folder locally, but it isn't a production server - we'll deal with deployment at the Launch Platform.
This code will fly to Mars. Every bug could cost the crew's lives. Test thoroughly! In the editor below, change the counter, type a message and toggle the system while watching the same changes in DevTools.
Remember: DevTools shows the inside of the system, watch reacts to every change, and npm run build packs the tested code into the dist folder.
Code for this lesson: src/App.vue
1<template>
2 <div class="nova-lab">
3 <h1>Vue DevTools</h1>
4
5 <section class="info">
6 <h2>Your best friend during development</h2>
7 <p>
8 Vue DevTools is a browser extension that allows you to:
9 </p>
10 <ul>
11 <li>Browse the component tree</li>
12 <li>Inspect and edit state</li>
13 <li>Track events</li>
14 <li>Debug Pinia stores</li>
15 <li>Analyze performance</li>
16 </ul>
17 </section>
18
19 <section class="demo">
20 <h2>Interactive State</h2>
21 <p>Open DevTools and observe how the state changes:</p>
22
23 <div class="state-demo">
24 <div class="counter">
25 <button @click="count--">-</button>
26 <span>{{ count }}</span>
27 <button @click="count++">+</button>
28 </div>
29
30 <div class="input-demo">
31 <input v-model="message" placeholder="Type a message..." />
32 <p>{{ message }}</p>
33 </div>
34
35 <div class="toggle-demo">
36 <label>
37 <input type="checkbox" v-model="isActive" />
38 System active
39 </label>
40 <div class="status" :class="{ active: isActive }">
41 {{ isActive ? 'ONLINE' : 'OFFLINE' }}
42 </div>
43 </div>
44 </div>
45 </section>
46
47 <section class="install">
48 <h2>Installation</h2>
49 <div class="browser-links">
50 <a href="https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd" target="_blank" class="browser-btn">
51 Chrome
52 </a>
53 <a href="https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/" target="_blank" class="browser-btn">
54 Firefox
55 </a>
56 <a href="https://microsoftedge.microsoft.com/addons/detail/vuejs-devtools/olofadcdnkkjdfgjcmjaadnlehnnihnl" target="_blank" class="browser-btn">
57 Edge
58 </a>
59 </div>
60 </section>
61 </div>
62</template>
63
64<script setup>
65import { ref } from 'vue'
66
67const count = ref(0)
68const message = ref('')
69const isActive = ref(true)
70</script>
71
72<style>
73.nova-lab {
74 min-height: 100vh;
75 background: #0a0e27;
76 color: #e0e0e0;
77 padding: 2rem;
78 font-family: system-ui, sans-serif;
79}
80
81h1 {
82 color: #00ff88;
83 text-align: center;
84}
85
86section {
87 background: rgba(26, 30, 55, 0.8);
88 border: 1px solid #00b4d8;
89 border-radius: 12px;
90 padding: 1.5rem;
91 margin: 1.5rem auto;
92 max-width: 600px;
93}
94
95h2 {
96 color: #00b4d8;
97 margin-top: 0;
98}
99
100ul {
101 list-style: none;
102 padding: 0;
103}
104
105ul li {
106 padding: 0.5rem 0;
107 border-bottom: 1px solid rgba(0, 180, 216, 0.2);
108}
109
110ul li::before {
111 content: "Β» ";
112 color: #00ff88;
113}
114
115.state-demo {
116 display: flex;
117 flex-direction: column;
118 gap: 1rem;
119}
120
121.counter {
122 display: flex;
123 align-items: center;
124 justify-content: center;
125 gap: 1rem;
126}
127
128.counter button {
129 width: 40px;
130 height: 40px;
131 background: #00b4d8;
132 color: #0a0e27;
133 border: none;
134 border-radius: 8px;
135 font-size: 1.25rem;
136 cursor: pointer;
137}
138
139.counter span {
140 font-size: 1.5rem;
141 font-weight: bold;
142 color: #00ff88;
143 min-width: 60px;
144 text-align: center;
145}
146
147.input-demo input {
148 width: 100%;
149 padding: 0.75rem;
150 background: #1a1e37;
151 border: 2px solid #00b4d8;
152 border-radius: 8px;
153 color: #fff;
154}
155
156.input-demo p {
157 color: #00ff88;
158 font-style: italic;
159 min-height: 1.5rem;
160}
161
162.toggle-demo {
163 display: flex;
164 align-items: center;
165 justify-content: space-between;
166}
167
168.toggle-demo label {
169 display: flex;
170 align-items: center;
171 gap: 0.5rem;
172 cursor: pointer;
173}
174
175.status {
176 padding: 0.5rem 1rem;
177 border-radius: 20px;
178 font-weight: bold;
179 background: rgba(255, 68, 68, 0.2);
180 color: #ff4444;
181}
182
183.status.active {
184 background: rgba(0, 255, 136, 0.2);
185 color: #00ff88;
186}
187
188.browser-links {
189 display: flex;
190 gap: 1rem;
191 justify-content: center;
192 flex-wrap: wrap;
193}
194
195.browser-btn {
196 padding: 0.75rem 1.5rem;
197 background: #1a1e37;
198 border: 2px solid #00b4d8;
199 border-radius: 8px;
200 color: #00b4d8;
201 text-decoration: none;
202 transition: all 0.2s;
203}
204
205.browser-btn:hover {
206 background: #00b4d8;
207 color: #0a0e27;
208}
209</style>Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. What are the official developer tools for Vue.js called?
2. What command compiles a Vue/Vite project for production?
3. What is the watch() function used for in Vue 3?
4. Who is the creator of both Vue.js and Vite?
Hands-on tasks in the game
- Vertical ordering
Arrange the process of installing and running a Vue.js project from scratch:
- Code editor
Complete the component with watch() monitoring changes to a reactive variable and logging them to the console.
- Click in order
Arrange the syntax of the watch function in Vue 3:
- Vertical ordering
Arrange the typical Vite workflow from development to production:
- Horizontal ordering
Arrange the syntax for conditional rendering of an element:
- Code editor
Use v-if and v-else to conditionally display system status depending on a variable's value.
- Vertical ordering
Arrange the Vue project structure from the entry file to the component:
- Horizontal ordering
Arrange the syntax of a button with click event handling in Vue:
- Click in order
Arrange the correct import of the ref function from Vue:
- Vertical ordering
Arrange the order of operations in the main.js file:
- Horizontal ordering
Arrange the syntax for dynamic CSS class binding in Vue:
- Click in order
Arrange the syntax of a computed property in Vue 3:
- Vertical ordering
Arrange the stages of the Vite build process from source code to production:
- Click in order
Arrange the correct style section with the scoped attribute:
- Horizontal ordering
Arrange the syntax of an input with two-way data binding in Vue:
- Vertical ordering
Arrange the component hierarchy from the highest to the lowest level: