feat(deploy): production deployment setup and fixes
- Debian-based api image (bookworm-slim), docker/debian mirrors, prisma binaryTargets for openssl 3.0 - nginx: admin SPA under /admin, TLS via acme.sh (ZeroSSL) + auto-renewal cron, http->https redirect - prisma: add origin_goods.delisted migration, sync missing schema (good_image/tag_font_color/good_tags), fix users.createdAt Timestamptz - api: CORS wildcard reflection, helmet CORP cross-origin, price backfill in persistProductDetail, categoryIcon ancestor fallback, mediaByColor per-color gallery in public goods detail - admin: /admin base path (vite + router) - import-data.mjs: udt_name casting, serial sequence advance fix
This commit is contained in:
@@ -1,124 +0,0 @@
|
||||
# Install Plugins Before Mounting the App
|
||||
|
||||
## Rule
|
||||
|
||||
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.
|
||||
|
||||
## Why This Matters
|
||||
|
||||
1. **Hidden dependencies**: Components may render before plugins they depend on are available, causing runtime errors.
|
||||
|
||||
2. **Reactivity issues**: Late plugin installation can cause subtle reactivity problems where provided values aren't properly reactive.
|
||||
|
||||
3. **Initialization order**: Many plugins (like vue-router, pinia) need to set up state before any component renders.
|
||||
|
||||
4. **Ecosystem complexity**: Adding plugins after mount can cause issues with Vue's internal ecosystem and hydration in SSR scenarios.
|
||||
|
||||
## Bad Practice
|
||||
|
||||
```typescript
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import i18nPlugin from './plugins/i18n'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
// Mounting first - plugins not yet available!
|
||||
app.mount('#app')
|
||||
|
||||
// Installing after mount - TOO LATE!
|
||||
app.use(router)
|
||||
app.use(i18nPlugin, { locale: 'en' })
|
||||
```
|
||||
|
||||
## Good Practice
|
||||
|
||||
```typescript
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import { createPinia } from 'pinia'
|
||||
import i18nPlugin from './plugins/i18n'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
// Install all plugins BEFORE mounting
|
||||
app.use(createPinia())
|
||||
app.use(router)
|
||||
app.use(i18nPlugin, { locale: 'en' })
|
||||
|
||||
// Mount LAST
|
||||
app.mount('#app')
|
||||
```
|
||||
|
||||
## Plugin Installation Order
|
||||
|
||||
The order of `app.use()` calls can matter when plugins depend on each other:
|
||||
|
||||
```typescript
|
||||
const app = createApp(App)
|
||||
|
||||
// 1. State management first (other plugins might need it)
|
||||
app.use(createPinia())
|
||||
|
||||
// 2. Router (may depend on state)
|
||||
app.use(router)
|
||||
|
||||
// 3. Other plugins (may depend on router or state)
|
||||
app.use(authPlugin)
|
||||
app.use(i18nPlugin, { locale: 'en' })
|
||||
|
||||
// 4. Mount last
|
||||
app.mount('#app')
|
||||
```
|
||||
|
||||
## Async Plugin Installation
|
||||
|
||||
If you need to perform async operations before mounting:
|
||||
|
||||
```typescript
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import { loadPlugins } from './plugins'
|
||||
|
||||
async function bootstrap() {
|
||||
const app = createApp(App)
|
||||
|
||||
// Await async plugin setup
|
||||
const i18nPlugin = await loadI18nMessages()
|
||||
|
||||
// Install all plugins
|
||||
app.use(i18nPlugin)
|
||||
|
||||
// Mount after everything is ready
|
||||
app.mount('#app')
|
||||
}
|
||||
|
||||
bootstrap()
|
||||
```
|
||||
|
||||
## Duplicate Installation Protection
|
||||
|
||||
Vue's `app.use()` automatically prevents duplicate plugin installation:
|
||||
|
||||
```typescript
|
||||
app.use(myPlugin)
|
||||
app.use(myPlugin) // This second call is ignored - no double installation
|
||||
|
||||
// This is handled internally by Vue, providing a safety net
|
||||
```
|
||||
|
||||
## Common Symptoms of Late Plugin Installation
|
||||
|
||||
- `inject()` returns `undefined` unexpectedly
|
||||
- Router navigation guards not firing
|
||||
- Store state not reactive
|
||||
- Template errors about undefined global properties
|
||||
- Hydration mismatches in SSR
|
||||
|
||||
## References
|
||||
|
||||
- [Vue.js Plugins Documentation](https://vuejs.org/guide/reusability/plugins.html)
|
||||
- [Vue.js Application API](https://vuejs.org/api/application.html)
|
||||
- [Vue 3 Migration Guide - Global API](https://v3-migration.vuejs.org/breaking-changes/global-api.html)
|
||||
Reference in New Issue
Block a user