feat(build): migrate to Vue 3 + bootstrap-vue-next#773
feat(build): migrate to Vue 3 + bootstrap-vue-next#773ErikBjare merged 9 commits intoActivityWatch:vue3from
Conversation
Phase 1 of Vue 3 migration (aw-webui#772): - vue 2.7 -> 3.5, vue-router 3 -> 4 - bootstrap-vue -> bootstrap-vue-next (bootstrap 4 -> 5) - chart.js 3 -> 4 (required by vue-chartjs v5) - @vitejs/plugin-vue2 -> @vitejs/plugin-vue - Remove webpack/@vue/cli-* packages entirely - Remove Vue 2-only packages: vue-datetime, vue-color, vue-awesome, vuedraggable v2 - Add vuedraggable v4, @fullcalendar/vue3 v6 - Update main.js: createApp() + createBootstrap() (bootstrap-vue-next API) - Update route.js: createRouter() + createWebHashHistory() (Vue Router 4 API) - Update stores/index.js: remove PiniaVuePlugin (Vue 2 only) - Update filters.js: export functions instead of Vue.filter() (removed in Vue 3) - Fix Vue.extend() -> defineComponent() in 3 components - Fix Calendar.vue: @fullcalendar/vue -> @fullcalendar/vue3 - Fix TimelineBarChart.vue: vue-chartjs/legacy -> vue-chartjs (v5 API) - Add vite.config.js stub plugin for Vue 2-only packages - Disable transformAssetUrls to allow runtime-served assets (logo.png) - Add IconPlaceholder.vue stub for vue-awesome icon component - Fix Header/Footer component names (reserved in Vue 3 ESLint rules) Build: 2191 modules transformed, dist generated successfully. Components still use Vue 2 Options API - individual migration in follow-up commits.
There was a problem hiding this comment.
Important
Looks good to me! 👍
Reviewed everything up to 5500d9b in 16 seconds. Click for details.
- Reviewed
729lines of code in14files - Skipped
1files when reviewing. - Skipped posting
0draft comments. View those below. - Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
Workflow ID: wflow_jGB2URIKIUFsDPmO
You can customize by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.
Greptile SummaryThis is a well-executed Phase 1 Vue 3 migration that successfully gets the build passing while deferring UI polish (icon replacements, bootstrap-vue-next component renames, filter syntax in templates) to Phase 2. All core Vue 2 → Vue 3 API changes are applied correctly across the 33 changed files. Key changes:
Two non-blocking suggestions remain:
Confidence Score: 4/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["main.js\ncreatApp(App)"] --> B["app.use(createBootstrap())"]
A --> C["app.use(router)\nVue Router 4"]
A --> D["app.use(pinia)\nPinia (no PiniaVuePlugin)"]
A --> E["app.config.globalProperties\n$aw · PRODUCTION · COMMIT_HASH"]
A --> F["app.mixin(asyncErrorCaptured)"]
A --> G["app.component(...)\ndefineAsyncComponent × 22 globals"]
A --> H["app.mount('#app')"]
H --> I["configureClient()\nrequires settings store"]
subgraph Build["Vite build"]
J["vue2StubPlugin\nresolveId / load"] --> K["Stubs:\nvue-awesome\nvue-color\nvue-datetime\nvue-d3-sunburst"]
L["@vitejs/plugin-vue\ntransformAssetUrls: false"]
M["VitePWA"]
end
subgraph Router["src/route.js"]
N["createRouter()\ncreateWebHashHistory()"]
O["/:pathMatch(.*)*\n→ NotFound"]
end
subgraph Filters["src/util/filters.js"]
P["Named exports\niso8601 · shortdate · shorttime\nfriendlytime · friendlyduration\nfriendlyperiod · orderBy"]
end
|
…ility @vue/eslint-config-typescript ^10 requires eslint-plugin-vue ^8, which conflicts with ^9 (needed for Vue 3). Upgrading to ^11 resolves the ERESOLVE peer dependency conflict that was breaking npm ci in CI.
- Bump ESLint ecmaVersion from 2017 to 2020 (supports dynamic import()) - Remove broken regex-style override patterns (ESLint uses globs, not regex) - Remove recursive vue-eslint-parser override that caused stack overflow - Replace @vue/cli-plugin-babel/preset with @babel/preset-env in babel config - Remove @vue/cli-plugin-unit-jest preset from Jest config (package removed) - Replace @vue/vue2-jest with @vue/vue3-jest for .vue file transforms - Add testEnvironmentOptions to fix @vue/test-utils browser build resolution - Add @vue/vue3-jest to devDependencies
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #773 +/- ##
==========================================
- Coverage 25.71% 25.57% -0.14%
==========================================
Files 30 30
Lines 1754 1783 +29
Branches 307 316 +9
==========================================
+ Hits 451 456 +5
+ Misses 1281 1258 -23
- Partials 22 69 +47 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
The e2e tests connect to http://127.0.0.1:27180 but Vite defaults to binding on 'localhost' which may resolve to ::1 (IPv6) on Ubuntu 24.04 CI runners, causing ConnectionRefused errors.
Vue 3 breaking changes that were missed in the initial migration:
- $emit('input') → $emit('update:modelValue') in all custom components
that support v-model (InputTimeInterval, QueryOptions, SelectCategories,
SelectCategoriesOrPattern, ColorPicker). This was causing Timeline view
to be stuck on "Loading..." because daterange was never emitted.
- beforeDestroy → beforeUnmount lifecycle hook (InputTimeInterval,
Activity, CategorizationSettings). Vue 3 renamed this hook.
- {{ value | filterName }} pipe syntax → {{ filterName(value) }} function
calls across all 14 affected components. Vue 3 removed global filters;
functions are imported from ~/util/filters and exposed via methods.
Resolve merge conflicts: - package.json: keep master's dompurify ^3.3.2, exports-loader, imports-loader - package-lock.json: regenerated via npm install Build verified: vite build succeeds, all 59 tests pass.
|
@greptileai review @TimeToBuildBob Thinking about merging this into a separate branch from master for now, maybe a |
|
Good call on the Before merging (even into - template(slot="button-content")
+ template(#button-content)Minor issues that can land later:
|
- Header.vue: fix Vue 2 slot syntax (slot= → #) on Activity and Tools
dropdown buttons — broken in Vue 3, caused empty navbar dropdowns
- vite.config.js: give setCsp/autoInject unique plugin names ('set-csp'
and 'auto-inject') instead of duplicate 'html-transform'
- package.json: move vue-router from devDependencies to dependencies
(it's a runtime import, not a build tool)
In Vue 3, app.config.globalProperties must be set before mounting. Move $aw alongside the other global properties (PRODUCTION, COMMIT_HASH, $isAndroid) before the mount() call. configureClient() stays after mount since it depends on the settings store being initialized.
|
Addressed Greptile review findings in two commits:
|
|
I changed the base branch for this PR to vue3. @greptileai review @TimeToBuildBob merge when ready, make sure to keep track of the follow-up plan and PRs. Might make sense to advertise the vue3 branch in related issues and maybe even master README. |
| vue({ | ||
| // Disable asset URL transformation so that runtime-provided assets | ||
| // (like /logo.png served by aw-server) are not treated as build-time imports. | ||
| template: { | ||
| transformAssetUrls: false, | ||
| }, | ||
| }), |
There was a problem hiding this comment.
transformAssetUrls: false disables all template asset resolution
Setting transformAssetUrls: false is a blanket override that prevents @vitejs/plugin-vue from turning any src="..." attribute in a template into a proper module import. This means local component-relative images (e.g. <img src="./icon.svg">) won't be bundled correctly in a future component that adds them.
The real goal is to avoid treating the server-served /logo.png as a build-time import. A more targeted fix is to configure only the asset types/tags you want rather than disabling the feature entirely:
| vue({ | |
| // Disable asset URL transformation so that runtime-provided assets | |
| // (like /logo.png served by aw-server) are not treated as build-time imports. | |
| template: { | |
| transformAssetUrls: false, | |
| }, | |
| }), | |
| vue({ | |
| template: { | |
| // Only transform img[src] and source[src]; skip script[src] so that | |
| // runtime-provided paths (like /logo.png from aw-server) are left alone. | |
| transformAssetUrls: { | |
| img: ['src', 'srcset'], | |
| source: ['src', 'srcset'], | |
| }, | |
| }, | |
| }), |
This keeps bundling for genuinely local images while leaving absolute/protocol paths (served by aw-server at runtime) untouched.
|
I just looked at the screenshot posted by CI at 0d6f503#commitcomment-180290865 You should use your own vision abilities to build and inspect screenshots and iterate until issues are fixed. You can even compare with old screenshots. |
Major visual fixes for the Vue 3 migration: - Replace empty IconPlaceholder with @fortawesome/vue-fontawesome — maps all 50+ vue-awesome icon names to Font Awesome 6 equivalents, fixing missing icons throughout the app (navbar, footer, buckets, settings, etc.) - Migrate Bootstrap 4 → 5 utility classes across all 30+ Vue files: .ml-* → .ms-*, .mr-* → .me-*, .pl-* → .ps-*, .pr-* → .pe-*, .float-left → .float-start, .float-right → .float-end, .text-left → .text-start, .text-right → .text-end - Fix Buckets.vue: replace Vue 2 $root.$emit modal control with bootstrap-vue-next v-model pattern - Fix Home.vue: add null guard for serverStore.info access that crashed render before server info loaded - Fix Buckets.vue: add null guard for serverStore.info.hostname - Update vite.config.js: add comment explaining why transformAssetUrls: false is needed (runtime /logo.png from aw-server, not a build asset) Co-authored-by: Bob <bob@superuserlabs.org>
Visual fixes based on CI screenshot inspectionInspected all 20 CI screenshots across three server backends. Found and fixed six categories of issues: 1. Missing icons (empty spans everywhere)The
2. Bootstrap 4 → 5 class migration (30+ files)All BS4 utility classes were still in use. Migrated across all Vue files:
This fixes the footer spacing issues (links running together) and general layout. 3. Vue 2 modal pattern → Vue 3Buckets.vue used 4. Null guard for server info
5.
|
|
Note: CI isn't running because the Build workflow only triggers on PRs targeting
Build and lint pass locally: |
|
Ready to merge — all visual fixes applied (icons, BS5 classes, Vue 3 patterns), merge state is CLEAN. I don't have merge permissions on this repo though, so you'll need to click the button @ErikBjare. Follow-up plan for the vue3 branch after merge:
|
|
@TimeToBuildBob Add vue3 to the workflow trigger branches |
|
Merged this, do the CI stuff in follow-up PR with the remaining fixes |
Summary
Phase 1 of Vue 3 migration (requested in #772):
@vue/cli-*/ webpack deps, keep Vite only@fullcalendar/vue→@fullcalendar/vue3(v6)Key changes
src/main.js:new Vue(...).$mount()→createApp(App).mount()src/route.js:new VueRouter()→createRouter()src/util/filters.js: Vue 2Vue.filter()→ named function exportsvue-awesome,vue-color,vue-datetime,vue-d3-sunburst) — renders placeholder components until proper Vue 3 alternatives are addedVue.extend()→defineComponent()Build status
Build succeeds:
✓ 2191 modules transformed, built in 26sWhat's left (Phase 2+)
bootstrap-vuecomponent names (<b-button>, etc.) tobootstrap-vue-nextequivalents{{ value | filterName }}template filter syntaxvuedraggable@2usageTest plan
npm run buildsucceedsImportant
Migrate from Vue 2 to Vue 3, updating components, routing, and build tools, while stubbing Vue 2-only packages.
src/main.jsto usecreateApp()instead ofnew Vue().Vue.filter()with named function exports insrc/util/filters.js.defineComponent()instead ofVue.extend()in components likeQueryOptions.vueandSelectCategories.vue.vue-awesome,vue-color,vue-datetime,vue-d3-sunburstinvite.config.js.vue-routerto 4.x and updatesrc/route.jsto usecreateRouter().@fullcalendar/vuewith@fullcalendar/vue3inCalendar.vue.vue-chartjsto 5.x inTimelineBarChart.vue.@vue/cli-*and webpack dependencies, use Vite exclusively.package.jsonscripts to use Vite for serving and building.vue2StubPlugininvite.config.jsto handle Vue 2-only packages.HeaderandFootercomponents toAwHeaderandAwFooter.vue-awesomeicons withIconPlaceholder.vue.src/main.jsusingdefineAsyncComponent().vite.config.jsto handle CSP and auto-inject scripts.src/route.jsfor Vue Router 4.x syntax.src/stores/index.jsto use Pinia withoutPiniaVuePlugin.This description was created by
for 5500d9b. You can customize this summary. It will automatically update as commits are pushed.