@pythoughts/vue-skills-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -0
- package/index.mjs +139 -0
- package/package.json +34 -0
- package/skills/create-adaptable-composable/SKILL.md +76 -0
- package/skills/vue-best-practices/SKILL.md +154 -0
- package/skills/vue-best-practices/references/animation-class-based-technique.md +254 -0
- package/skills/vue-best-practices/references/animation-state-driven-technique.md +291 -0
- package/skills/vue-best-practices/references/component-async.md +97 -0
- package/skills/vue-best-practices/references/component-data-flow.md +350 -0
- package/skills/vue-best-practices/references/component-fallthrough-attrs.md +174 -0
- package/skills/vue-best-practices/references/component-keep-alive.md +137 -0
- package/skills/vue-best-practices/references/component-slots.md +216 -0
- package/skills/vue-best-practices/references/component-suspense.md +228 -0
- package/skills/vue-best-practices/references/component-teleport.md +108 -0
- package/skills/vue-best-practices/references/component-transition-group.md +128 -0
- package/skills/vue-best-practices/references/component-transition.md +125 -0
- package/skills/vue-best-practices/references/composables.md +290 -0
- package/skills/vue-best-practices/references/directives.md +162 -0
- package/skills/vue-best-practices/references/perf-avoid-component-abstraction-in-lists.md +159 -0
- package/skills/vue-best-practices/references/perf-v-once-v-memo-directives.md +182 -0
- package/skills/vue-best-practices/references/perf-virtualize-large-lists.md +187 -0
- package/skills/vue-best-practices/references/plugins.md +166 -0
- package/skills/vue-best-practices/references/reactivity.md +346 -0
- package/skills/vue-best-practices/references/render-functions.md +201 -0
- package/skills/vue-best-practices/references/sfc.md +310 -0
- package/skills/vue-best-practices/references/state-management.md +135 -0
- package/skills/vue-best-practices/references/updated-hook-performance.md +187 -0
- package/skills/vue-debug-guides/SKILL.md +205 -0
- package/skills/vue-debug-guides/reference/animation-key-for-rerender.md +160 -0
- package/skills/vue-debug-guides/reference/animation-transitiongroup-performance.md +241 -0
- package/skills/vue-debug-guides/reference/async-component-error-handling.md +115 -0
- package/skills/vue-debug-guides/reference/async-component-keepalive-ref-issue.md +112 -0
- package/skills/vue-debug-guides/reference/async-component-suspense-control.md +84 -0
- package/skills/vue-debug-guides/reference/async-component-vue-router.md +109 -0
- package/skills/vue-debug-guides/reference/attrs-event-listener-merging.md +205 -0
- package/skills/vue-debug-guides/reference/checkbox-true-false-value-form-submission.md +118 -0
- package/skills/vue-debug-guides/reference/cleanup-side-effects.md +172 -0
- package/skills/vue-debug-guides/reference/click-events-on-components.md +180 -0
- package/skills/vue-debug-guides/reference/component-naming-conflicts.md +159 -0
- package/skills/vue-debug-guides/reference/component-ref-requires-defineexpose.md +176 -0
- package/skills/vue-debug-guides/reference/composable-avoid-hidden-side-effects.md +208 -0
- package/skills/vue-debug-guides/reference/composable-call-location-restrictions.md +141 -0
- package/skills/vue-debug-guides/reference/composable-naming-return-pattern.md +139 -0
- package/skills/vue-debug-guides/reference/composable-tovalue-inside-watcheffect.md +182 -0
- package/skills/vue-debug-guides/reference/composition-api-not-functional-programming.md +120 -0
- package/skills/vue-debug-guides/reference/composition-api-script-setup-async-context.md +203 -0
- package/skills/vue-debug-guides/reference/composition-api-vs-react-hooks-differences.md +156 -0
- package/skills/vue-debug-guides/reference/computed-array-mutation.md +148 -0
- package/skills/vue-debug-guides/reference/computed-conditional-dependencies.md +147 -0
- package/skills/vue-debug-guides/reference/computed-no-parameters.md +159 -0
- package/skills/vue-debug-guides/reference/computed-no-side-effects.md +107 -0
- package/skills/vue-debug-guides/reference/computed-return-value-readonly.md +160 -0
- package/skills/vue-debug-guides/reference/configure-app-before-mount.md +89 -0
- package/skills/vue-debug-guides/reference/declare-emits-for-documentation.md +212 -0
- package/skills/vue-debug-guides/reference/define-expose-before-await.md +192 -0
- package/skills/vue-debug-guides/reference/define-model-default-value-sync.md +139 -0
- package/skills/vue-debug-guides/reference/defineEmits-must-be-top-level.md +164 -0
- package/skills/vue-debug-guides/reference/defineEmits-no-runtime-and-type-mixed.md +170 -0
- package/skills/vue-debug-guides/reference/definemodel-object-mutation-no-emit.md +148 -0
- package/skills/vue-debug-guides/reference/dom-update-timing-nexttick.md +90 -0
- package/skills/vue-debug-guides/reference/dynamic-argument-constraints.md +146 -0
- package/skills/vue-debug-guides/reference/dynamic-component-registration-vite.md +147 -0
- package/skills/vue-debug-guides/reference/event-modifier-order-matters.md +101 -0
- package/skills/vue-debug-guides/reference/exact-modifier-for-precise-shortcuts.md +155 -0
- package/skills/vue-debug-guides/reference/fallthrough-attrs-overwrite-vue3.md +159 -0
- package/skills/vue-debug-guides/reference/in-dom-template-parsing-caveats.md +149 -0
- package/skills/vue-debug-guides/reference/inheritattrs-false-for-wrapper-components.md +230 -0
- package/skills/vue-debug-guides/reference/keepalive-router-nested-double-mount.md +222 -0
- package/skills/vue-debug-guides/reference/keepalive-transition-memory-leak.md +144 -0
- package/skills/vue-debug-guides/reference/keyup-modifier-timing.md +137 -0
- package/skills/vue-debug-guides/reference/lifecycle-dom-access-timing.md +216 -0
- package/skills/vue-debug-guides/reference/lifecycle-hooks-synchronous-registration.md +156 -0
- package/skills/vue-debug-guides/reference/lifecycle-ssr-awareness.md +184 -0
- package/skills/vue-debug-guides/reference/local-components-not-in-descendants.md +151 -0
- package/skills/vue-debug-guides/reference/mount-return-value.md +88 -0
- package/skills/vue-debug-guides/reference/multi-root-component-class-attrs.md +93 -0
- package/skills/vue-debug-guides/reference/native-event-collision-with-emits.md +162 -0
- package/skills/vue-debug-guides/reference/no-passive-with-prevent.md +141 -0
- package/skills/vue-debug-guides/reference/no-v-if-with-v-for.md +136 -0
- package/skills/vue-debug-guides/reference/perf-computed-object-stability.md +157 -0
- package/skills/vue-debug-guides/reference/perf-props-stability-update-optimization.md +140 -0
- package/skills/vue-debug-guides/reference/plugin-global-properties-sparingly.md +109 -0
- package/skills/vue-debug-guides/reference/plugin-install-before-mount.md +124 -0
- package/skills/vue-debug-guides/reference/plugin-prefer-provide-inject-over-global-properties.md +120 -0
- package/skills/vue-debug-guides/reference/plugin-typescript-type-augmentation.md +157 -0
- package/skills/vue-debug-guides/reference/prop-defineprops-scope-limitation.md +161 -0
- package/skills/vue-debug-guides/reference/provide-inject-debugging-challenges.md +203 -0
- package/skills/vue-debug-guides/reference/provide-inject-default-value-factory.md +244 -0
- package/skills/vue-debug-guides/reference/provide-inject-reactivity-not-automatic.md +226 -0
- package/skills/vue-debug-guides/reference/provide-inject-synchronous-setup.md +235 -0
- package/skills/vue-debug-guides/reference/reactive-destructuring.md +89 -0
- package/skills/vue-debug-guides/reference/reactivity-debugging-hooks.md +132 -0
- package/skills/vue-debug-guides/reference/reactivity-markraw-for-non-reactive.md +149 -0
- package/skills/vue-debug-guides/reference/reactivity-proxy-identity-hazard.md +96 -0
- package/skills/vue-debug-guides/reference/reactivity-same-tick-batching.md +166 -0
- package/skills/vue-debug-guides/reference/ref-value-access.md +61 -0
- package/skills/vue-debug-guides/reference/refs-in-collections-need-value.md +81 -0
- package/skills/vue-debug-guides/reference/render-function-avoid-internal-vnode-properties.md +151 -0
- package/skills/vue-debug-guides/reference/render-function-vnodes-must-be-unique.md +133 -0
- package/skills/vue-debug-guides/reference/rendering-render-function-h-import-vue3.md +148 -0
- package/skills/vue-debug-guides/reference/rendering-render-function-return-from-setup.md +148 -0
- package/skills/vue-debug-guides/reference/rendering-render-function-slots-as-functions.md +168 -0
- package/skills/vue-debug-guides/reference/rendering-resolve-component-for-string-names.md +231 -0
- package/skills/vue-debug-guides/reference/select-initial-value-ios-bug.md +91 -0
- package/skills/vue-debug-guides/reference/self-referencing-component-name.md +157 -0
- package/skills/vue-debug-guides/reference/sfc-named-exports-forbidden.md +184 -0
- package/skills/vue-debug-guides/reference/sfc-scoped-css-child-component-styling.md +156 -0
- package/skills/vue-debug-guides/reference/sfc-scoped-css-dynamic-content.md +193 -0
- package/skills/vue-debug-guides/reference/sfc-scoped-css-slot-content.md +242 -0
- package/skills/vue-debug-guides/reference/sfc-script-setup-reactivity.md +195 -0
- package/skills/vue-debug-guides/reference/slot-forwarding-to-child-components.md +143 -0
- package/skills/vue-debug-guides/reference/slot-implicit-default-content.md +155 -0
- package/skills/vue-debug-guides/reference/slot-name-reserved-prop.md +109 -0
- package/skills/vue-debug-guides/reference/slot-named-scoped-explicit-default.md +95 -0
- package/skills/vue-debug-guides/reference/slot-render-scope-parent-only.md +135 -0
- package/skills/vue-debug-guides/reference/slot-v-slot-on-components-or-templates-only.md +122 -0
- package/skills/vue-debug-guides/reference/ssr-hydration-mismatch-causes.md +280 -0
- package/skills/vue-debug-guides/reference/ssr-platform-specific-apis.md +256 -0
- package/skills/vue-debug-guides/reference/state-ssr-cross-request-pollution.md +276 -0
- package/skills/vue-debug-guides/reference/suspense-no-builtin-error-handling.md +127 -0
- package/skills/vue-debug-guides/reference/suspense-ssr-hydration-issues.md +159 -0
- package/skills/vue-debug-guides/reference/tailwind-dynamic-class-generation.md +144 -0
- package/skills/vue-debug-guides/reference/teleport-scoped-styles-limitation.md +191 -0
- package/skills/vue-debug-guides/reference/teleport-ssr-hydration.md +152 -0
- package/skills/vue-debug-guides/reference/teleport-target-must-exist.md +113 -0
- package/skills/vue-debug-guides/reference/template-expressions-restrictions.md +114 -0
- package/skills/vue-debug-guides/reference/template-functions-no-side-effects.md +187 -0
- package/skills/vue-debug-guides/reference/template-ref-null-with-v-if.md +123 -0
- package/skills/vue-debug-guides/reference/template-ref-unwrapping-top-level.md +104 -0
- package/skills/vue-debug-guides/reference/template-ref-v-for-order.md +172 -0
- package/skills/vue-debug-guides/reference/textarea-no-interpolation.md +72 -0
- package/skills/vue-debug-guides/reference/transition-group-flip-inline-elements.md +152 -0
- package/skills/vue-debug-guides/reference/transition-group-move-animation-position-absolute.md +130 -0
- package/skills/vue-debug-guides/reference/transition-group-no-default-wrapper-vue3.md +152 -0
- package/skills/vue-debug-guides/reference/transition-js-hooks-done-callback.md +251 -0
- package/skills/vue-debug-guides/reference/transition-nested-duration.md +182 -0
- package/skills/vue-debug-guides/reference/transition-reusable-scoped-style.md +245 -0
- package/skills/vue-debug-guides/reference/transition-router-view-appear.md +193 -0
- package/skills/vue-debug-guides/reference/transition-type-when-mixed.md +172 -0
- package/skills/vue-debug-guides/reference/transition-unmount-hook-timing.md +149 -0
- package/skills/vue-debug-guides/reference/ts-defineprops-boolean-default-false.md +225 -0
- package/skills/vue-debug-guides/reference/ts-defineprops-imported-types-limitations.md +281 -0
- package/skills/vue-debug-guides/reference/ts-event-handler-explicit-typing.md +213 -0
- package/skills/vue-debug-guides/reference/ts-reactive-no-generic-argument.md +196 -0
- package/skills/vue-debug-guides/reference/ts-shallowref-for-dynamic-components.md +218 -0
- package/skills/vue-debug-guides/reference/ts-template-ref-null-handling.md +249 -0
- package/skills/vue-debug-guides/reference/ts-template-type-casting.md +214 -0
- package/skills/vue-debug-guides/reference/ts-withdefaults-mutable-factory-function.md +171 -0
- package/skills/vue-debug-guides/reference/undeclared-emits-double-firing.md +195 -0
- package/skills/vue-debug-guides/reference/use-template-ref-vue35.md +158 -0
- package/skills/vue-debug-guides/reference/v-else-must-follow-v-if.md +136 -0
- package/skills/vue-debug-guides/reference/v-for-component-props.md +95 -0
- package/skills/vue-debug-guides/reference/v-for-computed-reverse-sort.md +86 -0
- package/skills/vue-debug-guides/reference/v-for-key-attribute.md +90 -0
- package/skills/vue-debug-guides/reference/v-for-range-starts-at-one.md +66 -0
- package/skills/vue-debug-guides/reference/v-if-null-check-order.md +171 -0
- package/skills/vue-debug-guides/reference/v-model-ignores-html-attributes.md +83 -0
- package/skills/vue-debug-guides/reference/v-model-ime-composition.md +83 -0
- package/skills/vue-debug-guides/reference/v-model-number-modifier-behavior.md +124 -0
- package/skills/vue-debug-guides/reference/v-show-template-limitation.md +124 -0
- package/skills/vue-debug-guides/reference/watch-async-cleanup.md +180 -0
- package/skills/vue-debug-guides/reference/watch-async-creation-memory-leak.md +176 -0
- package/skills/vue-debug-guides/reference/watch-deep-same-object-reference.md +165 -0
- package/skills/vue-debug-guides/reference/watch-flush-timing.md +189 -0
- package/skills/vue-debug-guides/reference/watch-reactive-property-getter.md +108 -0
- package/skills/vue-debug-guides/reference/watcheffect-async-dependency-tracking.md +173 -0
- package/skills/vue-debug-guides/reference/watcheffect-flush-post-for-refs.md +176 -0
- package/skills/vue-jsx-best-practices/SKILL.md +12 -0
- package/skills/vue-jsx-best-practices/reference/render-function-jsx-vue-vs-react.md +141 -0
- package/skills/vue-options-api-best-practices/SKILL.md +23 -0
- package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-lifecycle-hooks.md +95 -0
- package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-methods.md +68 -0
- package/skills/vue-options-api-best-practices/reference/stateful-methods-lifecycle.md +61 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-arrow-functions-validators.md +141 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-computed-return-types.md +192 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-proptype-complex-types.md +212 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-provide-inject-limitations.md +135 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-type-event-handlers.md +202 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-use-definecomponent.md +172 -0
- package/skills/vue-options-api-best-practices/reference/ts-strict-mode-options-api.md +197 -0
- package/skills/vue-pinia-best-practices/SKILL.md +21 -0
- package/skills/vue-pinia-best-practices/reference/pinia-no-active-pinia-error.md +248 -0
- package/skills/vue-pinia-best-practices/reference/pinia-setup-store-return-all-state.md +227 -0
- package/skills/vue-pinia-best-practices/reference/pinia-store-destructuring-breaks-reactivity.md +193 -0
- package/skills/vue-pinia-best-practices/reference/state-url-for-ephemeral-filters.md +238 -0
- package/skills/vue-pinia-best-practices/reference/state-use-pinia-for-large-apps.md +262 -0
- package/skills/vue-pinia-best-practices/reference/store-method-binding-parentheses.md +191 -0
- package/skills/vue-router-best-practices/SKILL.md +23 -0
- package/skills/vue-router-best-practices/reference/router-beforeenter-no-param-trigger.md +167 -0
- package/skills/vue-router-best-practices/reference/router-beforerouteenter-no-this.md +176 -0
- package/skills/vue-router-best-practices/reference/router-guard-async-await-pattern.md +227 -0
- package/skills/vue-router-best-practices/reference/router-navigation-guard-infinite-loop.md +187 -0
- package/skills/vue-router-best-practices/reference/router-navigation-guard-next-deprecated.md +150 -0
- package/skills/vue-router-best-practices/reference/router-param-change-no-lifecycle.md +181 -0
- package/skills/vue-router-best-practices/reference/router-simple-routing-cleanup.md +209 -0
- package/skills/vue-router-best-practices/reference/router-use-vue-router-for-production.md +183 -0
- package/skills/vue-testing-best-practices/SKILL.md +29 -0
- package/skills/vue-testing-best-practices/reference/async-component-testing.md +163 -0
- package/skills/vue-testing-best-practices/reference/teleport-testing-complexity.md +158 -0
- package/skills/vue-testing-best-practices/reference/testing-async-await-flushpromises.md +175 -0
- package/skills/vue-testing-best-practices/reference/testing-browser-vs-node-runners.md +208 -0
- package/skills/vue-testing-best-practices/reference/testing-component-blackbox-approach.md +144 -0
- package/skills/vue-testing-best-practices/reference/testing-composables-helper-wrapper.md +238 -0
- package/skills/vue-testing-best-practices/reference/testing-e2e-playwright-recommended.md +242 -0
- package/skills/vue-testing-best-practices/reference/testing-no-snapshot-only.md +197 -0
- package/skills/vue-testing-best-practices/reference/testing-pinia-store-setup.md +228 -0
- package/skills/vue-testing-best-practices/reference/testing-suspense-async-components.md +229 -0
- package/skills/vue-testing-best-practices/reference/testing-vitest-recommended-for-vue.md +204 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Install Plugins Before Mounting the App
|
|
2
|
+
|
|
3
|
+
## Rule
|
|
4
|
+
|
|
5
|
+
All plugins must be installed using `app.use()` BEFORE calling `app.mount()`. Installing plugins after the app is mounted can lead to reactivity issues, missing dependencies, and unexpected behavior.
|
|
6
|
+
|
|
7
|
+
## Why This Matters
|
|
8
|
+
|
|
9
|
+
1. **Hidden dependencies**: Components may render before plugins they depend on are available, causing runtime errors.
|
|
10
|
+
|
|
11
|
+
2. **Reactivity issues**: Late plugin installation can cause subtle reactivity problems where provided values aren't properly reactive.
|
|
12
|
+
|
|
13
|
+
3. **Initialization order**: Many plugins (like vue-router, pinia) need to set up state before any component renders.
|
|
14
|
+
|
|
15
|
+
4. **Ecosystem complexity**: Adding plugins after mount can cause issues with Vue's internal ecosystem and hydration in SSR scenarios.
|
|
16
|
+
|
|
17
|
+
## Bad Practice
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { createApp } from 'vue'
|
|
21
|
+
import App from './App.vue'
|
|
22
|
+
import router from './router'
|
|
23
|
+
import i18nPlugin from './plugins/i18n'
|
|
24
|
+
|
|
25
|
+
const app = createApp(App)
|
|
26
|
+
|
|
27
|
+
// Mounting first - plugins not yet available!
|
|
28
|
+
app.mount('#app')
|
|
29
|
+
|
|
30
|
+
// Installing after mount - TOO LATE!
|
|
31
|
+
app.use(router)
|
|
32
|
+
app.use(i18nPlugin, { locale: 'en' })
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Good Practice
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { createApp } from 'vue'
|
|
39
|
+
import App from './App.vue'
|
|
40
|
+
import router from './router'
|
|
41
|
+
import { createPinia } from 'pinia'
|
|
42
|
+
import i18nPlugin from './plugins/i18n'
|
|
43
|
+
|
|
44
|
+
const app = createApp(App)
|
|
45
|
+
|
|
46
|
+
// Install all plugins BEFORE mounting
|
|
47
|
+
app.use(createPinia())
|
|
48
|
+
app.use(router)
|
|
49
|
+
app.use(i18nPlugin, { locale: 'en' })
|
|
50
|
+
|
|
51
|
+
// Mount LAST
|
|
52
|
+
app.mount('#app')
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Plugin Installation Order
|
|
56
|
+
|
|
57
|
+
The order of `app.use()` calls can matter when plugins depend on each other:
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
const app = createApp(App)
|
|
61
|
+
|
|
62
|
+
// 1. State management first (other plugins might need it)
|
|
63
|
+
app.use(createPinia())
|
|
64
|
+
|
|
65
|
+
// 2. Router (may depend on state)
|
|
66
|
+
app.use(router)
|
|
67
|
+
|
|
68
|
+
// 3. Other plugins (may depend on router or state)
|
|
69
|
+
app.use(authPlugin)
|
|
70
|
+
app.use(i18nPlugin, { locale: 'en' })
|
|
71
|
+
|
|
72
|
+
// 4. Mount last
|
|
73
|
+
app.mount('#app')
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Async Plugin Installation
|
|
77
|
+
|
|
78
|
+
If you need to perform async operations before mounting:
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
import { createApp } from 'vue'
|
|
82
|
+
import App from './App.vue'
|
|
83
|
+
import { loadPlugins } from './plugins'
|
|
84
|
+
|
|
85
|
+
async function bootstrap() {
|
|
86
|
+
const app = createApp(App)
|
|
87
|
+
|
|
88
|
+
// Await async plugin setup
|
|
89
|
+
const i18nPlugin = await loadI18nMessages()
|
|
90
|
+
|
|
91
|
+
// Install all plugins
|
|
92
|
+
app.use(i18nPlugin)
|
|
93
|
+
|
|
94
|
+
// Mount after everything is ready
|
|
95
|
+
app.mount('#app')
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
bootstrap()
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Duplicate Installation Protection
|
|
102
|
+
|
|
103
|
+
Vue's `app.use()` automatically prevents duplicate plugin installation:
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
app.use(myPlugin)
|
|
107
|
+
app.use(myPlugin) // This second call is ignored - no double installation
|
|
108
|
+
|
|
109
|
+
// This is handled internally by Vue, providing a safety net
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Common Symptoms of Late Plugin Installation
|
|
113
|
+
|
|
114
|
+
- `inject()` returns `undefined` unexpectedly
|
|
115
|
+
- Router navigation guards not firing
|
|
116
|
+
- Store state not reactive
|
|
117
|
+
- Template errors about undefined global properties
|
|
118
|
+
- Hydration mismatches in SSR
|
|
119
|
+
|
|
120
|
+
## References
|
|
121
|
+
|
|
122
|
+
- [Vue.js Plugins Documentation](https://vuejs.org/guide/reusability/plugins.html)
|
|
123
|
+
- [Vue.js Application API](https://vuejs.org/api/application.html)
|
|
124
|
+
- [Vue 3 Migration Guide - Global API](https://v3-migration.vuejs.org/breaking-changes/global-api.html)
|
package/skills/vue-debug-guides/reference/plugin-prefer-provide-inject-over-global-properties.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Prefer provide/inject Over Global Properties in Plugins
|
|
2
|
+
|
|
3
|
+
## Rule
|
|
4
|
+
|
|
5
|
+
When creating Vue plugins, prefer using `app.provide()` to make plugin functionality available to components instead of attaching properties to `app.config.globalProperties`.
|
|
6
|
+
|
|
7
|
+
## Why This Matters
|
|
8
|
+
|
|
9
|
+
1. **globalProperties don't work in setup()**: Properties attached to `globalProperties` are only accessible via `this` in Options API. They are NOT available in the Composition API's `setup()` function.
|
|
10
|
+
|
|
11
|
+
2. **Type safety**: `provide/inject` integrates better with TypeScript and requires less type augmentation boilerplate.
|
|
12
|
+
|
|
13
|
+
3. **Testability**: Injected dependencies are easier to mock in tests compared to global properties.
|
|
14
|
+
|
|
15
|
+
4. **Code clarity**: Explicit `inject()` calls make dependencies visible, while global properties can appear "magic".
|
|
16
|
+
|
|
17
|
+
5. **Scoping**: `provide/inject` follows Vue's component hierarchy, making it easier to provide different values to different parts of your app.
|
|
18
|
+
|
|
19
|
+
## Bad Practice
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// plugins/i18n.ts
|
|
23
|
+
export default {
|
|
24
|
+
install(app, options) {
|
|
25
|
+
// Attaching to globalProperties - only works with Options API
|
|
26
|
+
app.config.globalProperties.$translate = (key: string) => {
|
|
27
|
+
return key.split('.').reduce((o, i) => o?.[i], options)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// In component - requires type augmentation for TypeScript
|
|
33
|
+
// Also DOES NOT work in <script setup>
|
|
34
|
+
export default {
|
|
35
|
+
mounted() {
|
|
36
|
+
console.log(this.$translate('greeting.hello'))
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Good Practice
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
// plugins/i18n.ts
|
|
45
|
+
import type { InjectionKey, App } from 'vue'
|
|
46
|
+
|
|
47
|
+
export interface I18nOptions {
|
|
48
|
+
[key: string]: string | I18nOptions
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface I18n {
|
|
52
|
+
translate: (key: string) => string
|
|
53
|
+
options: I18nOptions
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const i18nKey: InjectionKey<I18n> = Symbol('i18n')
|
|
57
|
+
|
|
58
|
+
export default {
|
|
59
|
+
install(app: App, options: I18nOptions) {
|
|
60
|
+
const translate = (key: string): string => {
|
|
61
|
+
return key.split('.').reduce((o, i) => o?.[i], options) as string ?? key
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Use provide for Composition API compatibility
|
|
65
|
+
app.provide(i18nKey, { translate, options })
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// In component - works in setup() and has full type safety
|
|
70
|
+
<script setup lang="ts">
|
|
71
|
+
import { inject } from 'vue'
|
|
72
|
+
import { i18nKey } from '@/plugins/i18n'
|
|
73
|
+
|
|
74
|
+
const i18n = inject(i18nKey)
|
|
75
|
+
console.log(i18n?.translate('greeting.hello'))
|
|
76
|
+
</script>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Hybrid Approach
|
|
80
|
+
|
|
81
|
+
If you must support both APIs (e.g., for backwards compatibility), provide both:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
export default {
|
|
85
|
+
install(app: App, options: I18nOptions) {
|
|
86
|
+
const i18n = {
|
|
87
|
+
translate: (key: string) => /* ... */
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// For Composition API
|
|
91
|
+
app.provide(i18nKey, i18n)
|
|
92
|
+
|
|
93
|
+
// For Options API (use sparingly)
|
|
94
|
+
app.config.globalProperties.$i18n = i18n
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## TypeScript Type Augmentation (if using globalProperties)
|
|
100
|
+
|
|
101
|
+
If you must use globalProperties, you need proper type augmentation:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// types/vue.d.ts
|
|
105
|
+
export {}
|
|
106
|
+
|
|
107
|
+
declare module 'vue' {
|
|
108
|
+
interface ComponentCustomProperties {
|
|
109
|
+
$translate: (key: string) => string
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**Important**: The file MUST contain `export {}` or another top-level export/import. Without it, the augmentation will OVERWRITE types instead of augmenting them.
|
|
115
|
+
|
|
116
|
+
## References
|
|
117
|
+
|
|
118
|
+
- [Vue.js Plugins Documentation](https://vuejs.org/guide/reusability/plugins.html)
|
|
119
|
+
- [Vue.js Provide/Inject](https://vuejs.org/guide/components/provide-inject.html)
|
|
120
|
+
- [TypeScript with Options API](https://vuejs.org/guide/typescript/options-api.html)
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Proper TypeScript Type Augmentation for Plugins
|
|
2
|
+
|
|
3
|
+
## Rule
|
|
4
|
+
|
|
5
|
+
When creating Vue plugins that add global properties, you MUST properly augment TypeScript types. The augmentation file MUST contain at least one top-level `import` or `export` statement to be treated as a module.
|
|
6
|
+
|
|
7
|
+
## Why This Matters
|
|
8
|
+
|
|
9
|
+
1. **Without module syntax, types are overwritten**: If your augmentation file isn't a module, it will OVERWRITE Vue's types instead of augmenting them, breaking type checking for the entire application.
|
|
10
|
+
|
|
11
|
+
2. **Type safety**: Proper augmentation enables autocomplete and type checking for plugin-provided properties.
|
|
12
|
+
|
|
13
|
+
3. **IDE support**: Developers get proper IntelliSense for global properties like `this.$translate`.
|
|
14
|
+
|
|
15
|
+
4. **Error prevention**: Catch typos and incorrect usage at compile time rather than runtime.
|
|
16
|
+
|
|
17
|
+
## Critical Rule: Module Syntax Required
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// BAD - This OVERWRITES Vue types instead of augmenting!
|
|
21
|
+
// types/vue.d.ts
|
|
22
|
+
declare module 'vue' {
|
|
23
|
+
interface ComponentCustomProperties {
|
|
24
|
+
$translate: (key: string) => string
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// GOOD - The export {} makes this a module, so it AUGMENTS types
|
|
29
|
+
// types/vue.d.ts
|
|
30
|
+
export {} // This line is CRITICAL!
|
|
31
|
+
|
|
32
|
+
declare module 'vue' {
|
|
33
|
+
interface ComponentCustomProperties {
|
|
34
|
+
$translate: (key: string) => string
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Complete Plugin Type Augmentation Example
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
// plugins/i18n.ts
|
|
43
|
+
import type { App, InjectionKey } from 'vue'
|
|
44
|
+
|
|
45
|
+
export interface I18nOptions {
|
|
46
|
+
locale: string
|
|
47
|
+
messages: Record<string, Record<string, string>>
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface I18nInstance {
|
|
51
|
+
translate: (key: string) => string
|
|
52
|
+
locale: string
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const i18nInjectionKey: InjectionKey<I18nInstance> = Symbol('i18n')
|
|
56
|
+
|
|
57
|
+
export function createI18n(options: I18nOptions) {
|
|
58
|
+
const i18n: I18nInstance = {
|
|
59
|
+
translate(key: string) {
|
|
60
|
+
return options.messages[options.locale]?.[key] ?? key
|
|
61
|
+
},
|
|
62
|
+
locale: options.locale
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
install(app: App) {
|
|
67
|
+
// For Composition API
|
|
68
|
+
app.provide(i18nInjectionKey, i18n)
|
|
69
|
+
|
|
70
|
+
// For Options API / templates
|
|
71
|
+
app.config.globalProperties.$t = i18n.translate
|
|
72
|
+
app.config.globalProperties.$i18n = i18n
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// types/i18n.d.ts (or in the same file after export)
|
|
78
|
+
export {}
|
|
79
|
+
|
|
80
|
+
declare module 'vue' {
|
|
81
|
+
interface ComponentCustomProperties {
|
|
82
|
+
$t: (key: string) => string
|
|
83
|
+
$i18n: I18nInstance
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Alternative: Augment @vue/runtime-core
|
|
89
|
+
|
|
90
|
+
Some plugins augment `@vue/runtime-core` instead of `vue`:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// types/global.d.ts
|
|
94
|
+
export {}
|
|
95
|
+
|
|
96
|
+
declare module '@vue/runtime-core' {
|
|
97
|
+
interface ComponentCustomProperties {
|
|
98
|
+
$myPlugin: MyPluginInstance
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Both approaches work, but `'vue'` is more common in application code.
|
|
104
|
+
|
|
105
|
+
## Ensure tsconfig.json Includes the Declaration File
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"compilerOptions": {
|
|
110
|
+
// ...
|
|
111
|
+
},
|
|
112
|
+
"include": [
|
|
113
|
+
"src/**/*.ts",
|
|
114
|
+
"src/**/*.vue",
|
|
115
|
+
"types/**/*.d.ts" // Include your declaration files
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## For Library Authors: package.json Types Field
|
|
121
|
+
|
|
122
|
+
If publishing a plugin as a package:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"name": "my-vue-plugin",
|
|
127
|
+
"types": "./dist/types/index.d.ts",
|
|
128
|
+
"exports": {
|
|
129
|
+
".": {
|
|
130
|
+
"types": "./dist/types/index.d.ts",
|
|
131
|
+
"import": "./dist/index.mjs"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Common Errors and Solutions
|
|
138
|
+
|
|
139
|
+
### Error: Property '$xyz' does not exist on type
|
|
140
|
+
|
|
141
|
+
1. Check that your `.d.ts` file has `export {}` or an import statement
|
|
142
|
+
2. Verify the file is included in `tsconfig.json`
|
|
143
|
+
3. Restart your TypeScript language server (VS Code: Cmd+Shift+P > "Restart TS Server")
|
|
144
|
+
|
|
145
|
+
### Error: Types work in some components but not others
|
|
146
|
+
|
|
147
|
+
This often happens when using Vetur instead of Volar. If you're on Vue 3, switch to Volar (Vue - Official extension).
|
|
148
|
+
|
|
149
|
+
### Error in Options API but not Composition API
|
|
150
|
+
|
|
151
|
+
Global properties on `this` require proper augmentation of `ComponentCustomProperties`. The Composition API uses `inject()` which is typed separately.
|
|
152
|
+
|
|
153
|
+
## References
|
|
154
|
+
|
|
155
|
+
- [Vue.js TypeScript with Options API](https://vuejs.org/guide/typescript/options-api.html)
|
|
156
|
+
- [TypeScript Module Augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation)
|
|
157
|
+
- [Vue.js Plugins Documentation](https://vuejs.org/guide/reusability/plugins.html)
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: defineProps Cannot Access Variables from script setup
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: Variables declared in script setup are not accessible inside defineProps arguments
|
|
5
|
+
type: gotcha
|
|
6
|
+
tags: [vue3, props, script-setup, defineProps, compiler]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# defineProps Cannot Access Variables from script setup
|
|
10
|
+
|
|
11
|
+
**Impact: MEDIUM** - Code inside the `defineProps()` argument cannot access other variables declared in `<script setup>`. The entire expression is moved to an outer function scope when compiled, making local variables inaccessible.
|
|
12
|
+
|
|
13
|
+
This commonly surprises developers trying to use imported constants or computed validation logic.
|
|
14
|
+
|
|
15
|
+
## Task Checklist
|
|
16
|
+
|
|
17
|
+
- [ ] Define validation constants outside `<script setup>` or in a separate file
|
|
18
|
+
- [ ] Import constants before using them in defineProps
|
|
19
|
+
- [ ] Use external type definitions for TypeScript props
|
|
20
|
+
- [ ] For dynamic validation, use watchers instead of prop validators
|
|
21
|
+
|
|
22
|
+
**Incorrect:**
|
|
23
|
+
```vue
|
|
24
|
+
<script setup>
|
|
25
|
+
import { ref } from 'vue'
|
|
26
|
+
|
|
27
|
+
// These are in <script setup> scope
|
|
28
|
+
const VALID_SIZES = ['sm', 'md', 'lg']
|
|
29
|
+
const maxLength = ref(100)
|
|
30
|
+
|
|
31
|
+
defineProps({
|
|
32
|
+
size: {
|
|
33
|
+
type: String,
|
|
34
|
+
// WRONG: VALID_SIZES is not accessible here
|
|
35
|
+
validator: (v) => VALID_SIZES.includes(v) // ReferenceError!
|
|
36
|
+
},
|
|
37
|
+
name: {
|
|
38
|
+
type: String,
|
|
39
|
+
// WRONG: Cannot access refs
|
|
40
|
+
validator: (v) => v.length <= maxLength.value // ReferenceError!
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
</script>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Correct:**
|
|
47
|
+
```vue
|
|
48
|
+
<script>
|
|
49
|
+
// Define constants in regular <script> block (module scope)
|
|
50
|
+
export const VALID_SIZES = ['sm', 'md', 'lg']
|
|
51
|
+
export const MAX_LENGTH = 100
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<script setup>
|
|
55
|
+
// Now accessible in defineProps
|
|
56
|
+
defineProps({
|
|
57
|
+
size: {
|
|
58
|
+
type: String,
|
|
59
|
+
validator: (v) => VALID_SIZES.includes(v) // Works!
|
|
60
|
+
},
|
|
61
|
+
name: {
|
|
62
|
+
type: String,
|
|
63
|
+
validator: (v) => v.length <= MAX_LENGTH // Works!
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
</script>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Pattern: Import from External File
|
|
70
|
+
|
|
71
|
+
```javascript
|
|
72
|
+
// validation.js
|
|
73
|
+
export const VALID_SIZES = ['sm', 'md', 'lg']
|
|
74
|
+
export const VALID_COLORS = ['red', 'blue', 'green']
|
|
75
|
+
export const sizeValidator = (v) => VALID_SIZES.includes(v)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
```vue
|
|
79
|
+
<script setup>
|
|
80
|
+
import { VALID_SIZES, VALID_COLORS, sizeValidator } from './validation'
|
|
81
|
+
|
|
82
|
+
// Imported values ARE accessible
|
|
83
|
+
defineProps({
|
|
84
|
+
size: {
|
|
85
|
+
type: String,
|
|
86
|
+
validator: sizeValidator
|
|
87
|
+
},
|
|
88
|
+
color: {
|
|
89
|
+
type: String,
|
|
90
|
+
validator: (v) => VALID_COLORS.includes(v)
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
</script>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Pattern: Dual Script Blocks
|
|
97
|
+
|
|
98
|
+
```vue
|
|
99
|
+
<script>
|
|
100
|
+
// Regular script for module-level declarations
|
|
101
|
+
const options = {
|
|
102
|
+
themes: ['light', 'dark', 'system'],
|
|
103
|
+
defaults: {
|
|
104
|
+
theme: 'light',
|
|
105
|
+
size: 'md'
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
</script>
|
|
109
|
+
|
|
110
|
+
<script setup>
|
|
111
|
+
// options is accessible here
|
|
112
|
+
const props = defineProps({
|
|
113
|
+
theme: {
|
|
114
|
+
type: String,
|
|
115
|
+
default: options.defaults.theme,
|
|
116
|
+
validator: (v) => options.themes.includes(v)
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
</script>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## TypeScript: External Type Definitions
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
// types.ts
|
|
126
|
+
export interface UserProps {
|
|
127
|
+
name: string
|
|
128
|
+
email: string
|
|
129
|
+
age?: number
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```vue
|
|
134
|
+
<script setup lang="ts">
|
|
135
|
+
import type { UserProps } from './types'
|
|
136
|
+
|
|
137
|
+
// Type imports work fine
|
|
138
|
+
const props = defineProps<UserProps>()
|
|
139
|
+
</script>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Why This Happens
|
|
143
|
+
|
|
144
|
+
Vue's compiler transforms `<script setup>` code. The `defineProps()` call is extracted and moved to component options at compile time, before the setup function runs:
|
|
145
|
+
|
|
146
|
+
```javascript
|
|
147
|
+
// Your code:
|
|
148
|
+
const MY_CONST = 'value'
|
|
149
|
+
defineProps({ prop: { default: MY_CONST } })
|
|
150
|
+
|
|
151
|
+
// Compiled (simplified):
|
|
152
|
+
export default {
|
|
153
|
+
props: { prop: { default: MY_CONST } }, // MY_CONST doesn't exist here!
|
|
154
|
+
setup() {
|
|
155
|
+
const MY_CONST = 'value' // Defined too late
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Reference
|
|
161
|
+
- [Vue.js Script Setup - defineProps](https://vuejs.org/api/sfc-script-setup.html#defineprops-defineemits)
|