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:
yeuimu
2026-08-26 14:23:09 +08:00
parent be0b90e68f
commit 6c61a4e871
982 changed files with 74156 additions and 179393 deletions
@@ -1,147 +1,147 @@
---
title: Use import.meta.glob for Dynamic Component Registration in Vite
impact: MEDIUM
impactDescription: require.context from Webpack doesn't work in Vite projects
type: gotcha
tags: [vue3, component-registration, vite, dynamic-import, migration, webpack]
---
# Use import.meta.glob for Dynamic Component Registration in Vite
**Impact: MEDIUM** - When migrating from Webpack to Vite or starting a new Vite project, the `require.context` pattern for dynamically registering components won't work. Vite uses `import.meta.glob` instead. Using the wrong approach will cause build errors or runtime failures.
## Task Checklist
- [ ] Replace `require.context` with `import.meta.glob` in Vite projects
- [ ] Update component registration patterns when migrating from Vue CLI to Vite
- [ ] Use `{ eager: true }` for synchronous loading when needed
- [ ] Handle async components appropriately with `defineAsyncComponent`
**Incorrect (Webpack pattern - doesn't work in Vite):**
```javascript
// main.js - WRONG for Vite
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// This Webpack-specific API doesn't exist in Vite
const requireComponent = require.context(
'./components/base',
false,
/Base[A-Z]\w+\.vue$/
)
requireComponent.keys().forEach(fileName => {
const componentConfig = requireComponent(fileName)
const componentName = fileName
.split('/')
.pop()
.replace(/\.\w+$/, '')
app.component(componentName, componentConfig.default || componentConfig)
})
app.mount('#app')
```
**Correct (Vite pattern):**
```javascript
// main.js - Correct for Vite
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// Vite's glob import - eager loading for synchronous registration
const modules = import.meta.glob('./components/base/Base*.vue', { eager: true })
for (const path in modules) {
// Extract component name from path: './components/base/BaseButton.vue' -> 'BaseButton'
const componentName = path.split('/').pop().replace('.vue', '')
app.component(componentName, modules[path].default)
}
app.mount('#app')
```
## Lazy Loading with Async Components
```javascript
// main.js - Lazy loading variant
import { createApp, defineAsyncComponent } from 'vue'
import App from './App.vue'
const app = createApp(App)
// Without { eager: true }, returns functions that return Promises
const modules = import.meta.glob('./components/base/Base*.vue')
for (const path in modules) {
const componentName = path.split('/').pop().replace('.vue', '')
// Wrap in defineAsyncComponent for lazy loading
app.component(componentName, defineAsyncComponent(modules[path]))
}
app.mount('#app')
```
## Glob Pattern Examples
```javascript
// All .vue files in a directory (not recursive)
import.meta.glob('./components/*.vue', { eager: true })
// All .vue files recursively
import.meta.glob('./components/**/*.vue', { eager: true })
// Specific naming pattern
import.meta.glob('./components/Base*.vue', { eager: true })
// Multiple patterns
import.meta.glob([
'./components/Base*.vue',
'./components/App*.vue'
], { eager: true })
// Exclude patterns
import.meta.glob('./components/**/*.vue', {
eager: true,
ignore: ['**/*.test.vue', '**/*.spec.vue']
})
```
## TypeScript Support
```typescript
// main.ts - with proper typing
import { createApp, Component } from 'vue'
import App from './App.vue'
const app = createApp(App)
const modules = import.meta.glob<{ default: Component }>(
'./components/base/Base*.vue',
{ eager: true }
)
for (const path in modules) {
const componentName = path.split('/').pop()!.replace('.vue', '')
app.component(componentName, modules[path].default)
}
app.mount('#app')
```
## Migration Checklist (Webpack to Vite)
| Webpack | Vite |
|---------|------|
| `require.context(dir, recursive, regex)` | `import.meta.glob(pattern, options)` |
| Synchronous by default | Use `{ eager: true }` for sync |
| `.keys()` returns array | Returns object with paths as keys |
| Returns module directly | Access via `.default` for ES modules |
## Reference
- [Vite - Glob Import](https://vitejs.dev/guide/features.html#glob-import)
- [Vue.js Component Registration](https://vuejs.org/guide/components/registration.html)
---
title: Use import.meta.glob for Dynamic Component Registration in Vite
impact: MEDIUM
impactDescription: require.context from Webpack doesn't work in Vite projects
type: gotcha
tags: [vue3, component-registration, vite, dynamic-import, migration, webpack]
---
# Use import.meta.glob for Dynamic Component Registration in Vite
**Impact: MEDIUM** - When migrating from Webpack to Vite or starting a new Vite project, the `require.context` pattern for dynamically registering components won't work. Vite uses `import.meta.glob` instead. Using the wrong approach will cause build errors or runtime failures.
## Task Checklist
- [ ] Replace `require.context` with `import.meta.glob` in Vite projects
- [ ] Update component registration patterns when migrating from Vue CLI to Vite
- [ ] Use `{ eager: true }` for synchronous loading when needed
- [ ] Handle async components appropriately with `defineAsyncComponent`
**Incorrect (Webpack pattern - doesn't work in Vite):**
```javascript
// main.js - WRONG for Vite
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// This Webpack-specific API doesn't exist in Vite
const requireComponent = require.context(
'./components/base',
false,
/Base[A-Z]\w+\.vue$/
)
requireComponent.keys().forEach(fileName => {
const componentConfig = requireComponent(fileName)
const componentName = fileName
.split('/')
.pop()
.replace(/\.\w+$/, '')
app.component(componentName, componentConfig.default || componentConfig)
})
app.mount('#app')
```
**Correct (Vite pattern):**
```javascript
// main.js - Correct for Vite
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// Vite's glob import - eager loading for synchronous registration
const modules = import.meta.glob('./components/base/Base*.vue', { eager: true })
for (const path in modules) {
// Extract component name from path: './components/base/BaseButton.vue' -> 'BaseButton'
const componentName = path.split('/').pop().replace('.vue', '')
app.component(componentName, modules[path].default)
}
app.mount('#app')
```
## Lazy Loading with Async Components
```javascript
// main.js - Lazy loading variant
import { createApp, defineAsyncComponent } from 'vue'
import App from './App.vue'
const app = createApp(App)
// Without { eager: true }, returns functions that return Promises
const modules = import.meta.glob('./components/base/Base*.vue')
for (const path in modules) {
const componentName = path.split('/').pop().replace('.vue', '')
// Wrap in defineAsyncComponent for lazy loading
app.component(componentName, defineAsyncComponent(modules[path]))
}
app.mount('#app')
```
## Glob Pattern Examples
```javascript
// All .vue files in a directory (not recursive)
import.meta.glob('./components/*.vue', { eager: true })
// All .vue files recursively
import.meta.glob('./components/**/*.vue', { eager: true })
// Specific naming pattern
import.meta.glob('./components/Base*.vue', { eager: true })
// Multiple patterns
import.meta.glob([
'./components/Base*.vue',
'./components/App*.vue'
], { eager: true })
// Exclude patterns
import.meta.glob('./components/**/*.vue', {
eager: true,
ignore: ['**/*.test.vue', '**/*.spec.vue']
})
```
## TypeScript Support
```typescript
// main.ts - with proper typing
import { createApp, Component } from 'vue'
import App from './App.vue'
const app = createApp(App)
const modules = import.meta.glob<{ default: Component }>(
'./components/base/Base*.vue',
{ eager: true }
)
for (const path in modules) {
const componentName = path.split('/').pop()!.replace('.vue', '')
app.component(componentName, modules[path].default)
}
app.mount('#app')
```
## Migration Checklist (Webpack to Vite)
| Webpack | Vite |
|---------|------|
| `require.context(dir, recursive, regex)` | `import.meta.glob(pattern, options)` |
| Synchronous by default | Use `{ eager: true }` for sync |
| `.keys()` returns array | Returns object with paths as keys |
| Returns module directly | Access via `.default` for ES modules |
## Reference
- [Vite - Glob Import](https://vitejs.dev/guide/features.html#glob-import)
- [Vue.js Component Registration](https://vuejs.org/guide/components/registration.html)