Yuki Takei 1 месяц назад
Родитель
Сommit
6111ffdf94

+ 483 - 0
.kiro/specs/reduce-modules-loaded/design.md

@@ -0,0 +1,483 @@
+# Design Document: reduce-modules-loaded
+
+## Overview
+
+**Purpose**: This feature reduces the excessive module count (10,066 modules) compiled for the `[[...path]]` catch-all page in `apps/app`, improving developer experience through faster compilation times and a tighter development feedback loop.
+
+**Users**: GROWI developers working on `apps/app` will benefit from significantly reduced `turbo run dev` compilation times when accessing pages during local development.
+
+**Impact**: Changes the current build configuration, import patterns, and potentially the Next.js version to eliminate unnecessary module loading — particularly server-side modules leaking into the client compilation graph.
+
+### Goals
+- Reduce the `[[...path]]` page module count from 10,066 to a significantly lower number (target: measurable reduction with before/after metrics)
+- Identify and fix server-side module leakage into client bundle
+- Optimize barrel export patterns to prevent full module tree traversal
+- Evaluate and apply Next.js official configuration options for module reduction
+- If beneficial, upgrade Next.js to unlock `bundlePagesRouterDependencies` and `serverExternalPackages`
+
+### Non-Goals
+- Migration from Pages Router to App Router
+- Complete elimination of barrel exports across the entire codebase
+- Turbopack adoption in Phase 1 (deferred to Phase 2b due to webpack config incompatibility; see `research.md` — Turbopack Compatibility section)
+- Performance optimization beyond module count reduction (runtime perf, SSR latency, etc.)
+
+## Architecture
+
+### Existing Architecture Analysis
+
+GROWI `apps/app` uses Next.js 14 with Pages Router, Webpack, and the following relevant configuration:
+
+| Mechanism | Current State | Gap |
+|-----------|--------------|-----|
+| `optimizePackageImports` | 11 `@growi/*` packages | Not expanded to third-party or internal barrel-heavy modules |
+| null-loader (client exclusion) | `mongoose`, `dtrace-provider`, `mathjax-full` | 30+ server-only packages not covered |
+| `next/dynamic` + LazyLoaded pattern | Well-implemented for modal components | Already correct — not a primary contributor |
+| `@next/bundle-analyzer` | Installed, not routinely used | Useful for investigating module composition, but NOT for measuring dev compilation module count |
+| `bundlePagesRouterDependencies` | Not configured | Requires Next.js 15+ |
+| `serverExternalPackages` | Not configured | Requires Next.js 15+ |
+
+**Confirmed Import Violations**:
+1. `src/client/components/RecentActivity/ActivityListItem.tsx` → `~/server/util/locale-utils` (server boundary violation)
+2. `src/client/components/InAppNotification/.../PageBulkExportJobModelNotification.tsx` → `~/models/serializers/.../page-bulk-export-job.ts` → `import mongoose from 'mongoose'` (server module via serializer)
+
+**High-Impact Barrel Exports**:
+- `src/states/ui/editor/index.ts` — 7 wildcard re-exports
+- `src/features/page-tree/index.ts` — 3-level cascading barrels (15+ modules)
+- `src/utils/axios/index.ts` — re-exports entire axios library
+
+### Architecture Pattern & Boundary Map
+
+**Selected pattern**: Phased configuration-driven optimization with incremental structural fixes
+
+The optimization is divided into two phases. Phase 1 operates within the current Next.js 14 + Webpack architecture. Phase 2 evaluates and optionally executes a Next.js version upgrade based on Phase 1 results.
+
+```mermaid
+graph TB
+    subgraph Phase1[Phase 1 - v14 Optimizations]
+        A1[Bundle Analysis Baseline] --> A2[Expand optimizePackageImports]
+        A1 --> A3[Fix Import Violations]
+        A1 --> A4[Expand null-loader Rules]
+        A2 --> A5[Measure Module Count]
+        A3 --> A5
+        A4 --> A5
+        A5 --> A6[Refactor High-Impact Barrels]
+        A6 --> A7[Final Measurement]
+    end
+
+    subgraph Phase2[Phase 2 - Version Upgrade Evaluation]
+        B1[Evaluate Phase 1 Results]
+        B1 --> B2{Sufficient Reduction?}
+        B2 -->|Yes| B3[Document Results]
+        B2 -->|No| B4[Next.js 15 Upgrade]
+        B4 --> B5[Enable bundlePagesRouterDependencies]
+        B4 --> B6[Configure serverExternalPackages]
+        B4 --> B7[Resolve next-superjson Blocker]
+    end
+
+    A7 --> B1
+```
+
+**Domain boundaries**:
+- Build Configuration (`next.config.js`) — config-only changes, zero code risk
+- Import Graph (source files) — import path fixes, moderate risk
+- Framework Version (Next.js/React) — major upgrade, high risk
+
+**Existing patterns preserved**: Pages Router, `getServerSideProps`, Jotai/SWR state management, feature-based directory structure
+
+### Technology Stack
+
+| Layer | Choice / Version | Role in Feature | Notes |
+|-------|------------------|-----------------|-------|
+| Build System | Next.js ^14.2.35 (Phase 1) / ^15.x (Phase 2) | Module bundling, compilation | Webpack bundler |
+| Bundler | Webpack 5 (via Next.js) | Module resolution, tree-shaking | Turbopack deferred to Phase 2b |
+| Analysis | `@next/bundle-analyzer` | Baseline and verification measurement | Already installed |
+| Linting | Biome (existing) | Import boundary enforcement | Optional ESLint rule for server/client boundary |
+
+## System Flows
+
+### Phase 1: Optimization Flow
+
+```mermaid
+sequenceDiagram
+    participant Dev as Developer
+    participant DevServer as next dev
+    participant BA as Bundle Analyzer
+    participant Config as next.config.js
+    participant Src as Source Files
+
+    Note over Dev,DevServer: Baseline Measurement
+    Dev->>DevServer: turbo run dev + access page
+    DevServer-->>Dev: Compiled in 51.5s (10066 modules)
+
+    Note over Dev,BA: Investigation (optional)
+    Dev->>BA: ANALYZE=true pnpm run build
+    BA-->>Dev: Module composition treemap
+
+    Note over Dev,Src: Apply Optimizations
+    Dev->>Config: Expand optimizePackageImports
+    Dev->>Config: Add null-loader rules for server packages
+    Dev->>Src: Fix client to server import violations
+    Dev->>Src: Refactor high-impact barrel exports
+
+    Note over Dev,DevServer: Verification Measurement
+    Dev->>DevServer: turbo run dev + access page
+    DevServer-->>Dev: Compiled in Ys (M modules)
+```
+
+## Requirements Traceability
+
+| Requirement | Summary | Components | Interfaces | Flows |
+|-------------|---------|------------|------------|-------|
+| 1.1-1.4 | Next.js config research | ConfigResearch | — | Phase 1 |
+| 2.1-2.3 | Module count root cause analysis | DevCompilationMeasurement | — | Phase 1 |
+| 3.1-3.3 | Server-side leakage prevention | ImportViolationFix, NullLoaderExpansion | — | Phase 1 |
+| 3.4 | serverExternalPackages | NextjsUpgrade | next.config.js | Phase 2 |
+| 4.1-4.4 | Barrel export and package import optimization | OptimizePackageImportsExpansion, BarrelExportRefactor | — | Phase 1 |
+| 5.1-5.4 | Next.js version evaluation and upgrade | NextjsUpgrade | next.config.js | Phase 2 |
+| 6.1-6.3 | Compilation time and module count reduction | — (outcome) | — | Both |
+| 7.1-7.3 | Lazy loading verification | LazyLoadVerification | — | Phase 1 |
+
+## Components and Interfaces
+
+| Component | Domain | Intent | Req Coverage | Key Dependencies | Contracts |
+|-----------|--------|--------|--------------|-----------------|-----------|
+| DevCompilationMeasurement | Build | Measure dev module count as primary metric; bundle analyzer for investigation | 1.4, 2.1-2.3, 6.1 | Dev server log (P0), `@next/bundle-analyzer` (P1) | — |
+| OptimizePackageImportsExpansion | Build Config | Expand barrel file optimization coverage | 1.1, 4.3, 4.4 | `next.config.js` (P0) | Config |
+| NullLoaderExpansion | Build Config | Exclude additional server packages from client bundle | 3.1, 3.2 | `next.config.js` (P0) | Config |
+| ImportViolationFix | Source | Fix confirmed client-to-server import violations | 3.1, 3.2, 3.3 | Source files (P0) | — |
+| BarrelExportRefactor | Source | Refactor high-impact barrel exports to direct exports | 4.1, 4.2 | State/feature barrel files (P1) | — |
+| LazyLoadVerification | Build | Verify lazy-loaded components excluded from initial compilation | 7.1-7.3 | Bundle analysis output (P1) | — |
+| NextjsUpgrade | Framework | Evaluate and execute Next.js 15 upgrade | 5.1-5.4, 3.4 | next-superjson (P0 blocker), React 19 (P0) | Config |
+| ConfigResearch | Documentation | Document Next.js config options and applicability | 1.1-1.3 | — | — |
+
+### Build Configuration Domain
+
+#### DevCompilationMeasurement
+
+| Field | Detail |
+|-------|--------|
+| Intent | Measure dev compilation module count and time as the primary DX metric; use bundle analyzer as a supplementary investigation tool |
+| Requirements | 1.4, 2.1, 2.2, 2.3, 6.1 |
+
+**Responsibilities & Constraints**
+- Record dev compilation output (`Compiled /[[...path]] in Xs (N modules)`) as the **primary success metric**
+- Use `@next/bundle-analyzer` (`ANALYZE=true`) only as a **supplementary investigation tool** to understand which modules are included and trace import chains — NOT as the success metric
+- Establish baseline before any optimization, then measure after each step
+- Note: dev compilation does NOT tree-shake, so module count reflects the full dependency graph — this is exactly the metric we want to reduce
+
+**Important Distinction**:
+- `next dev` module count = modules webpack processes during on-demand compilation (no tree-shaking) → **this is what makes dev slow**
+- `next build` + ANALYZE = production bundle after tree-shaking → useful for investigation but does NOT reflect dev DX
+
+**Dependencies**
+- External: `@next/bundle-analyzer` — supplementary investigation tool (P1)
+- Inbound: Dev server compilation log — primary metric source (P0)
+
+**Contracts**: —
+
+**Implementation Notes**
+- Primary measurement: `turbo run dev` → access page → read `Compiled /[[...path]] in Xs (N modules)` from log
+- Clean `.next` directory before each measurement for consistent results
+- Supplementary: `ANALYZE=true pnpm run app:build` to inspect module composition when investigating specific leakage paths
+- Repeat measurement 3 times and take median to account for system variability
+
+#### OptimizePackageImportsExpansion
+
+| Field | Detail |
+|-------|--------|
+| Intent | Expand `optimizePackageImports` in `next.config.js` to cover barrel-heavy internal and third-party packages |
+| Requirements | 1.1, 4.3, 4.4 |
+
+**Responsibilities & Constraints**
+- Add packages identified by bundle analysis as barrel-heavy contributors
+- Maintain the existing 11 `@growi/*` entries
+- Identify third-party packages with barrel exports not in the auto-optimized list
+
+**Dependencies**
+- Outbound: `next.config.js` `experimental.optimizePackageImports` — config array (P0)
+- Inbound: BundleAnalysis — identifies which packages need optimization
+
+**Contracts**: Config [x]
+
+##### Configuration Interface
+
+Current configuration to extend:
+
+```typescript
+// next.config.js — experimental.optimizePackageImports
+// Existing entries preserved; new entries added based on bundle analysis
+const optimizePackageImports: string[] = [
+  // Existing @growi/* packages (11)
+  '@growi/core',
+  '@growi/editor',
+  '@growi/pluginkit',
+  '@growi/presentation',
+  '@growi/preset-themes',
+  '@growi/remark-attachment-refs',
+  '@growi/remark-drawio',
+  '@growi/remark-growi-directive',
+  '@growi/remark-lsx',
+  '@growi/slack',
+  '@growi/ui',
+  // Candidates for addition (validate with bundle analysis):
+  // - Third-party packages with barrel exports not in auto-list
+  // - Internal directories if supported by config
+];
+```
+
+**Implementation Notes**
+- Zero-risk config change — does not affect runtime behavior
+- Validate each addition with before/after module count measurement
+- Some packages may already be auto-optimized by Next.js (check against the auto-list in docs)
+
+#### NullLoaderExpansion
+
+| Field | Detail |
+|-------|--------|
+| Intent | Expand null-loader rules in webpack config to exclude additional server-only packages from client bundle |
+| Requirements | 3.1, 3.2 |
+
+**Responsibilities & Constraints**
+- Add null-loader rules for server-only packages confirmed to appear in client bundle by bundle analysis
+- Maintain existing rules for `dtrace-provider`, `mongoose`, `mathjax-full`
+- Only add packages that are actually present in the client bundle (verify with bundle analysis first)
+
+**Dependencies**
+- Outbound: `next.config.js` `webpack()` config — null-loader rules (P0)
+- Inbound: BundleAnalysis — confirms which server packages are in client bundle
+
+**Contracts**: Config [x]
+
+##### Configuration Interface
+
+```typescript
+// next.config.js — webpack config, client-side only (!options.isServer)
+// Existing patterns preserved; candidates added after bundle analysis verification
+const serverPackageExclusions: RegExp[] = [
+  /dtrace-provider/,   // existing
+  /mongoose/,          // existing
+  /mathjax-full/,      // existing
+  // Candidates (add only if confirmed in client bundle):
+  // /@elastic\/elasticsearch/,
+  // /passport/,
+  // /@aws-sdk\//,
+  // /@azure\//,
+  // /@google-cloud\//,
+  // /openai/,
+  // /@opentelemetry\//,
+  // /ldapjs/,
+  // /nodemailer/,
+  // /multer/,
+  // /socket\.io/,
+];
+```
+
+**Implementation Notes**
+- Must verify each package appears in client bundle before adding rule (avoid unnecessary config)
+- null-loader replaces module content with empty module — no runtime impact for correctly excluded packages
+- If a package is accidentally excluded that IS needed on client, it will cause runtime errors — test thoroughly
+
+### Source Code Domain
+
+#### ImportViolationFix
+
+| Field | Detail |
+|-------|--------|
+| Intent | Fix confirmed client-to-server import violations that cause server modules to leak into client bundle |
+| Requirements | 3.1, 3.2, 3.3 |
+
+**Responsibilities & Constraints**
+- Fix the confirmed import violation in `ActivityListItem.tsx` (`~/server/util/locale-utils`)
+- Fix the serializer import in `PageBulkExportJobModelNotification.tsx` (pulls in mongoose)
+- Ensure fixed modules maintain identical functionality
+- Establish a pattern for preventing future violations
+
+**Dependencies**
+- Inbound: BundleAnalysis — identifies import chains causing leakage (P0)
+
+**Contracts**: —
+
+##### Confirmed Violations to Fix
+
+| File | Violation | Fix Strategy |
+|------|-----------|-------------|
+| `src/client/components/RecentActivity/ActivityListItem.tsx` | Imports `getLocale` from `~/server/util/locale-utils` | Extract `getLocale` to a client-safe utility module (the function only needs `date-fns/locale`, no server deps) |
+| `src/client/components/InAppNotification/.../PageBulkExportJobModelNotification.tsx` | Imports serializer that has `import mongoose from 'mongoose'` | Split serializer: server-side `stringifySnapshot` stays in `~/models/`; client-side `parseSnapshot` moves to client-accessible module |
+| `src/stores/in-app-notification.ts` | Imports `~/models/serializers/.../user` | Verify this serializer is clean (confirmed: no mongoose import). Low priority. |
+
+**Implementation Notes**
+- The `getLocale` function itself has no server dependencies — only `date-fns/locale` and `@growi/core/dist/interfaces`. The file's location in `~/server/util/` is misleading; extracting it to `~/utils/` or `~/client/util/` resolves the violation.
+- For the serializer split: `parseSnapshot` is a pure JSON parsing function; `stringifySnapshot` uses mongoose and should remain server-only.
+- Consider adding a lint rule to prevent `src/client/**` or `src/components/**` from importing `src/server/**`.
+
+#### BarrelExportRefactor
+
+| Field | Detail |
+|-------|--------|
+| Intent | Refactor high-impact barrel export files to reduce unnecessary module tree traversal |
+| Requirements | 4.1, 4.2 |
+
+**Responsibilities & Constraints**
+- Refactor after verifying that `optimizePackageImports` expansion does not already resolve the issue
+- Prioritize files with highest module count impact (determined by bundle analysis)
+- Maintain backward compatibility — consumers should not need to change their import paths unless necessary
+
+**Dependencies**
+- Inbound: OptimizePackageImportsExpansion — determines which barrels are already optimized (P1)
+- Inbound: BundleAnalysis — quantifies barrel impact (P1)
+
+**Contracts**: —
+
+##### Target Barrel Files (Priority Order)
+
+| File | Issue | Refactor Strategy |
+|------|-------|-------------------|
+| `src/utils/axios/index.ts` | `export * from 'axios'` re-exports entire library | Replace with specific named exports used by consumers |
+| `src/states/ui/editor/index.ts` | 7 wildcard `export *` | Convert to named re-exports; or verify `optimizePackageImports` handles it |
+| `src/features/page-tree/index.ts` | 3-level cascading barrel (15+ modules) | Flatten to single-level named exports; or consumers import directly from submodules |
+| `src/states/page/index.ts` | 2 wildcard + named exports | Convert to named re-exports if still problematic after config optimization |
+
+**Implementation Notes**
+- Attempt `optimizePackageImports` expansion first — if it handles barrel files for `@growi/*` packages effectively, many of these refactors become unnecessary
+- For `utils/axios/index.ts`, the `export * from 'axios'` pattern is universally problematic; this should be fixed regardless of other optimizations
+- Barrel refactoring may require updating import paths across many files — use IDE refactoring tools and verify with `turbo run lint:typecheck`
+
+### Build Verification Domain
+
+#### LazyLoadVerification
+
+| Field | Detail |
+|-------|--------|
+| Intent | Verify that lazy-loaded components are correctly excluded from initial page compilation |
+| Requirements | 7.1, 7.2, 7.3 |
+
+**Responsibilities & Constraints**
+- Verify the existing `*LazyLoaded` pattern (dynamic.tsx + useLazyLoader) does not contribute to initial module count
+- Confirm `index.ts` files in lazy-loaded component directories only re-export from `dynamic.tsx`
+- Check bundle analysis output for any lazy-loaded component modules in the initial bundle
+
+**Dependencies**
+- Inbound: BundleAnalysis — verifies exclusion from initial bundle (P1)
+
+**Contracts**: —
+
+**Implementation Notes**
+- Gap analysis confirms the LazyLoaded pattern is already well-implemented
+- This component is primarily a verification step, not a fix
+- If any lazy-loaded components are found in the initial bundle, the fix follows the existing `dynamic.tsx` pattern
+
+### Framework Upgrade Domain (Phase 2)
+
+#### NextjsUpgrade
+
+| Field | Detail |
+|-------|--------|
+| Intent | Evaluate and optionally execute Next.js 15 upgrade to unlock `bundlePagesRouterDependencies` and `serverExternalPackages` |
+| Requirements | 5.1, 5.2, 5.3, 5.4, 3.4 |
+
+**Responsibilities & Constraints**
+- Only proceed if Phase 1 results indicate insufficient module reduction
+- Address the `next-superjson` compatibility blocker before upgrading
+- Use the official `@next/codemod` for automated migration
+- Maintain React 18 compatibility with Pages Router (backward compat available in v15)
+
+**Dependencies**
+- External: `next-superjson` — SWC plugin compatibility (P0 blocker)
+- External: React 19 — peer dependency (P0, but backward compat available)
+- External: `@next/codemod` — migration automation (P1)
+
+**Contracts**: Config [x]
+
+##### Configuration Interface (Post-Upgrade)
+
+```typescript
+// next.config.js — New v15 options
+const nextConfig = {
+  // Enable automatic server-side dependency bundling for Pages Router
+  bundlePagesRouterDependencies: true,
+  // Exclude heavy server-only packages from bundling
+  serverExternalPackages: [
+    'mongoose',
+    // Additional packages based on bundle analysis
+  ],
+};
+```
+
+##### Known Blockers
+
+| Blocker | Severity | Mitigation |
+|---------|----------|------------|
+| `next-superjson` SWC plugin broken in v15 | Critical | Research alternatives: manual superjson in getServerSideProps, or use `superjson` directly without SWC plugin |
+| `I18NextHMRPlugin` (webpack plugin) | Medium | Only affects dev HMR for i18n; can use `--webpack` flag for dev |
+| React 19 peer dependency | Low | Pages Router has React 18 backward compat in v15 |
+| `@next/font` removal | Low | Codemod available; switch to `next/font` |
+
+**Implementation Notes**
+- Run codemod first: `npx @next/codemod@canary upgrade latest`
+- Test with `--webpack` flag to isolate bundler-related issues from framework issues
+- The `bundlePagesRouterDependencies: true` setting is the highest-value v15 feature for this spec — it automatically bundles server-side deps, which combined with `serverExternalPackages` provides fine-grained control
+- Research `next-superjson` alternatives during Phase 1 to have a mitigation ready
+
+## Testing Strategy
+
+### Verification Tests (Module Count — Primary DX Metric)
+- **Primary**: Run `turbo run dev`, access page, record `Compiled /[[...path]] in Xs (N modules)` from log before and after each optimization step
+- **Supplementary**: Run `ANALYZE=true pnpm run app:build` only when investigating specific module composition (e.g., tracing which server modules appear in client bundle)
+- Clean `.next` directory before each measurement; repeat 3 times, take median
+
+### Regression Tests
+- `turbo run lint:typecheck --filter @growi/app` — verify no type errors from import changes
+- `turbo run lint:biome --filter @growi/app` — verify no lint violations
+- `turbo run test --filter @growi/app` — verify all existing tests pass
+- `turbo run build --filter @growi/app` — verify production build succeeds
+- Manual smoke test: access `[[...path]]` page and verify all functionality works (page rendering, editing, navigation, modals)
+
+### Phase 2 Additional Tests
+- All Phase 1 tests
+- `npx @next/codemod@canary upgrade latest --dry` — preview upgrade changes
+- Test superjson serialization: verify `getServerSideProps` data correctly serialized/deserialized for all page routes
+- Test i18n HMR: verify locale changes reflect in dev mode (may degrade if I18NextHMRPlugin is removed)
+
+## Performance & Scalability
+
+**Target Metrics**:
+- **Primary (DX metric)**: Dev compilation module count for `[[...path]]` page (baseline: 10,066 modules)
+- **Secondary (DX metric)**: Dev compilation time for `[[...path]]` page (baseline: 51.5s)
+- **Supplementary (investigation only)**: Production bundle composition via `@next/bundle-analyzer`
+
+> **Important**: The primary metric is the dev compilation log, NOT the production bundle analyzer. Dev compilation does not tree-shake, so the module count directly reflects what makes development slow. Production bundle analysis is useful for tracing import chains but does not represent the dev experience.
+
+**Measurement Protocol**:
+1. Clean `.next` directory (`rm -rf apps/app/.next`)
+2. Run `turbo run dev`
+3. Navigate to `/` or any wiki page path in the browser
+4. Record `Compiled /[[...path]] in Xs (N modules)` from the terminal log
+5. Repeat 3 times, take median value
+6. Record results in a comparison table for each optimization step
+
+## Supporting References
+
+### Server-Only Package Candidates for null-loader
+
+From `apps/app/package.json`, the following packages are server-only and should be excluded from client bundle if they appear there:
+
+| Category | Packages |
+|----------|----------|
+| Database | `mongoose`, `mongodb`, `mongoose-gridfs`, `mongoose-paginate-v2`, `mongoose-unique-validator` |
+| Search | `@elastic/elasticsearch7`, `@elastic/elasticsearch8`, `@elastic/elasticsearch9` |
+| Auth | `passport`, `passport-github2`, `passport-google-oauth20`, `passport-ldapauth`, `passport-saml` |
+| Cloud Storage | `@aws-sdk/client-s3`, `@aws-sdk/s3-request-presigner`, `@azure/storage-blob`, `@google-cloud/storage` |
+| AI | `openai`, `@azure/openai` |
+| Identity | `@azure/identity`, `ldapjs` |
+| File Upload | `multer`, `multer-autoreap` |
+| Email | `nodemailer`, `nodemailer-ses-transport` |
+| Real-time | `socket.io`, `y-socket.io`, `y-mongodb-provider` |
+| Session/Cache | `connect-redis`, `redis` |
+| Observability | `@opentelemetry/*` (8 packages) |
+
+> Only add null-loader rules for packages confirmed present in the client bundle by bundle analysis.
+
+### Auto-Optimized Packages (No Need to Add to optimizePackageImports)
+
+The following packages are automatically optimized by Next.js and should NOT be added to the config:
+`lucide-react`, `date-fns`, `lodash-es`, `ramda`, `antd`, `react-bootstrap`, `ahooks`, `@ant-design/icons`, `@headlessui/react`, `@headlessui-float/react`, `@heroicons/react/*`, `@visx/visx`, `@tremor/react`, `rxjs`, `@mui/material`, `@mui/icons-material`, `recharts`, `react-use`, `@material-ui/*`, `@tabler/icons-react`, `mui-core`, `react-icons/*`, `effect`, `@effect/*`

+ 240 - 0
.kiro/specs/reduce-modules-loaded/gap-analysis.md

@@ -0,0 +1,240 @@
+# Gap Analysis: reduce-modules-loaded
+
+## 1. Current State Investigation
+
+### Key Files & Architecture
+
+| Asset | Path | Role |
+|-------|------|------|
+| Next.js config | `apps/app/next.config.js` | Build config with webpack rules, transpilePackages, optimizePackageImports |
+| Catch-all page | `apps/app/src/pages/[[...path]]/index.page.tsx` | Main page route — 10,066 modules on compilation |
+| Server-side props | `apps/app/src/pages/[[...path]]/server-side-props.ts` | getServerSideProps logic |
+| Common props | `apps/app/src/pages/common-props.ts` | Shared server-side props |
+| Transpile utils | `apps/app/src/utils/next.config.utils.js` | Dynamic ESM package discovery for transpilePackages |
+| Package.json | `apps/app/package.json` | 193 dependencies (32+ server-only) |
+
+### Existing Optimization Mechanisms
+
+1. **`optimizePackageImports`** — configured for 11 `@growi/*` packages
+2. **null-loader** — excludes `dtrace-provider`, `mongoose`, `mathjax-full` from client bundle
+3. **`next/dynamic`** — used for 6+ components with `{ ssr: false }`
+4. **LazyLoaded pattern** — `*LazyLoaded` wrapper components use `useLazyLoader` hook with dynamic `import()` — correctly defers actual component loading
+5. **`@next/bundle-analyzer`** — already installed but not routinely used
+
+### Conventions Observed
+
+- **Pages Router** with `getServerSideProps` (not App Router)
+- **next-superjson** for serialization in SSR
+- `pageExtensions: ['page.tsx', 'page.ts', 'page.jsx', 'page.js']`
+- Feature-based organization in `src/features/`
+- State management: Jotai atoms in `src/states/`, SWR hooks in `src/stores/`
+
+---
+
+## 2. Requirement-to-Asset Map
+
+### Requirement 1: Next.js Official Configuration Research
+
+| Need | Status | Notes |
+|------|--------|-------|
+| `optimizePackageImports` evaluation | **Partially Exists** | Configured for 11 @growi/* packages; not expanded to cover barrel-heavy third-party deps |
+| `bundlePagesRouterDependencies` evaluation | **Missing** | Not configured; requires Next.js 15+ |
+| `serverExternalPackages` evaluation | **Missing** | Not configured; requires Next.js 15+ |
+| Turbopack evaluation | **Missing** | Currently using Webpack; Turbopack stable in Next.js 15+ |
+| Bundle analysis tooling | **Exists** | `@next/bundle-analyzer` installed; `next experimental-analyze` available in v16.1+ |
+
+### Requirement 2: Module Count Root Cause Analysis
+
+| Need | Status | Notes |
+|------|--------|-------|
+| Bundle analysis tooling | **Exists** | `@next/bundle-analyzer` already in `next.config.js` (ANALYZE env var) |
+| Server-side module identification | **Gap** | No automated mechanism to detect server module leakage |
+| Barrel export impact quantification | **Gap** | No tooling to measure per-barrel module overhead |
+
+### Requirement 3: Server-Side Module Leakage Prevention
+
+| Need | Status | Notes |
+|------|--------|-------|
+| null-loader for mongoose | **Exists** | Already configured |
+| null-loader for other server packages | **Gap — CRITICAL** | 30+ server-only packages NOT excluded (see below) |
+| Client → server import detection | **Gap** | No ESLint rule or build-time check |
+| `serverExternalPackages` | **Gap** | Requires Next.js 15+ |
+
+**Confirmed Leakage Paths:**
+
+1. **`src/client/components/RecentActivity/ActivityListItem.tsx`** → `~/server/util/locale-utils` → pulls in `^/config/i18next.config` (lightweight, but breaks server/client boundary)
+2. **`src/client/components/InAppNotification/ModelNotification/PageBulkExportJobModelNotification.tsx`** → `~/models/serializers/.../page-bulk-export-job.ts` → **`import mongoose from 'mongoose'`** → pulls in entire mongoose + MongoDB driver (but null-loader should catch this on client)
+3. **`src/stores/in-app-notification.ts`** → `~/models/serializers/.../user.ts` (clean — no mongoose import)
+
+**Server-Only Packages Missing from null-loader:**
+
+| Package | Type | Estimated Module Impact |
+|---------|------|----------------------|
+| `@elastic/elasticsearch*` (v7/v8/v9) | Search | High |
+| `passport`, `passport-*` (5 packages) | Auth | Medium |
+| `@aws-sdk/*` | Cloud storage | High |
+| `@azure/*` (3 packages) | Cloud + AI | High |
+| `@google-cloud/storage` | Cloud storage | Medium |
+| `openai`, `@azure/openai` | AI | Medium |
+| `@opentelemetry/*` (8 packages) | Observability | Medium |
+| `ldapjs` | Auth | Low |
+| `nodemailer*` | Email | Low |
+| `multer*` | File upload | Low |
+| `redis`, `connect-redis` | Session | Low |
+| `socket.io` | Real-time | Medium |
+
+> **Note:** Whether these packages actually get pulled into the client bundle depends on whether any client-reachable import chain references them. The null-loader for mongoose suggests this category of leakage has been observed before.
+
+### Requirement 4: Barrel Export and Package Import Optimization
+
+| Need | Status | Notes |
+|------|--------|-------|
+| Expand `optimizePackageImports` | **Gap** | Only 11 @growi/* packages; missing third-party barrel-heavy deps |
+| Eliminate `export *` in states/ | **Gap** | 7+ barrel export files in `src/states/` with `export *` patterns |
+| Eliminate `export *` in features/ | **Gap** | `features/page-tree/index.ts` cascades to 15+ modules |
+| Direct imports instead of barrel | **Gap** | Requires refactoring import paths across codebase |
+
+**High-Impact Barrel Export Files:**
+
+| File | Wildcard Exports | Cascading Depth |
+|------|-----------------|----------------|
+| `src/states/ui/editor/index.ts` | 7 `export *` | 1 level |
+| `src/features/page-tree/index.ts` | 3 `export *` | 3 levels → 15+ modules |
+| `src/features/page-tree/hooks/_inner/index.ts` | 8 `export *` | 1 level |
+| `src/states/page/index.ts` | 2 `export *` + named | 1 level |
+| `src/utils/axios/index.ts` | `export * from 'axios'` | Re-exports entire library |
+
+### Requirement 5: Next.js Version Evaluation and Upgrade
+
+| Need | Status | Notes |
+|------|--------|-------|
+| Current version: Next.js `^14.2.35` | **Exists** | Pages Router architecture |
+| Upgrade to v15 evaluation | **Research Needed** | Breaking changes, React 19 dependency, `bundlePagesRouterDependencies` |
+| Upgrade to v16 evaluation | **Research Needed** | Turbopack default, experimental-analyze tool |
+| Migration effort assessment | **Research Needed** | 30+ page files, custom webpack config, superjson plugin |
+
+### Requirement 6: Compilation Time and Module Count Reduction
+
+| Need | Status | Notes |
+|------|--------|-------|
+| Baseline measurement | **Exists** | 10,066 modules / 51.5s for `[[...path]]` |
+| Before/after metrics framework | **Gap** | No automated benchmarking in CI |
+| Functional regression testing | **Exists** | Vitest test suite, Turbo test pipeline |
+
+### Requirement 7: Lazy Loading and Dynamic Import Verification
+
+| Need | Status | Notes |
+|------|--------|-------|
+| LazyLoaded wrapper pattern | **Exists — Well Designed** | `dynamic.tsx` files use `useLazyLoader` with dynamic `import()` |
+| Index re-export pattern | **Exists — Clean** | `index.ts` files only re-export from `dynamic.tsx`, not the actual component |
+| Verification tooling | **Gap** | No automated check that lazy-loaded components stay out of initial bundle |
+
+**Good News:** The `*LazyLoaded` pattern is already well-implemented:
+```
+index.ts → exports from dynamic.tsx → useLazyLoader(() => import('./ActualComponent'))
+```
+The actual component is only loaded when the trigger condition is met. This is NOT a major contributor to the 10,066 module count.
+
+---
+
+## 3. Implementation Approach Options
+
+### Option A: Configuration-First (No Version Upgrade)
+
+**Approach:** Maximize optimizations within Next.js 14 + Webpack
+
+1. Expand `optimizePackageImports` to cover more barrel-heavy packages
+2. Add null-loader rules for additional server-only packages
+3. Fix confirmed client → server import violations
+4. Refactor critical barrel exports (`states/ui/editor`, `features/page-tree`, `utils/axios`)
+
+**Trade-offs:**
+- ✅ No breaking changes, lowest risk
+- ✅ Immediately measurable impact
+- ✅ Each change is independently verifiable
+- ❌ Limited by Webpack's tree-shaking capabilities
+- ❌ `bundlePagesRouterDependencies` and `serverExternalPackages` unavailable
+- ❌ No Turbopack benefits (automatic import optimization, faster HMR)
+
+### Option B: Next.js 15 Upgrade + Configuration
+
+**Approach:** Upgrade to Next.js 15, then apply v15-specific optimizations
+
+1. Upgrade Next.js 14 → 15 (address breaking changes)
+2. Enable `bundlePagesRouterDependencies` + `serverExternalPackages`
+3. Expand `optimizePackageImports`
+4. Fix client → server import violations
+5. Optionally enable Turbopack for dev
+
+**Trade-offs:**
+- ✅ Unlocks `bundlePagesRouterDependencies` and `serverExternalPackages`
+- ✅ Turbopack available (auto-optimizes imports, 14x faster cold start)
+- ✅ Better tree-shaking in Webpack 5 improvements
+- ❌ React 19 dependency — breaking change risk across all components
+- ❌ `next-superjson` compatibility unknown
+- ❌ Medium-to-high migration effort (30+ page files, custom webpack config)
+- ❌ Risk of regressions across authentication, i18n, etc.
+
+### Option C: Hybrid — Configuration-First, Then Upgrade (Recommended)
+
+**Approach:** Phase 1 optimizes within v14; Phase 2 evaluates and executes upgrade
+
+**Phase 1 (Low Risk, Immediate Impact):**
+1. Run `@next/bundle-analyzer` to establish baseline and identify top contributors
+2. Expand `optimizePackageImports` list
+3. Add null-loader rules for confirmed server-only packages in client bundle
+4. Fix client → server import violations (1 confirmed: `ActivityListItem.tsx`)
+5. Refactor high-impact barrel exports
+6. Measure before/after module count
+
+**Phase 2 (Higher Risk, Longer Term):**
+1. Evaluate Next.js 15/16 upgrade feasibility based on Phase 1 findings
+2. If module count reduction from Phase 1 is insufficient, proceed with upgrade
+3. Enable `bundlePagesRouterDependencies` + `serverExternalPackages`
+4. Evaluate Turbopack adoption for dev mode
+
+**Trade-offs:**
+- ✅ Quick wins first — validates approach before committing to upgrade
+- ✅ Phase 1 findings inform Phase 2 decisions
+- ✅ Incremental risk management
+- ❌ More total effort if upgrade is ultimately needed
+- ❌ Two phases of testing/validation
+
+---
+
+## 4. Effort & Risk Assessment
+
+| Requirement | Effort | Risk | Justification |
+|-------------|--------|------|---------------|
+| Req 1: Config Research | S (1-2 days) | Low | Docs research + local testing |
+| Req 2: Root Cause Analysis | S (1-2 days) | Low | Run bundle analyzer, document findings |
+| Req 3: Server-Side Leakage Fix | M (3-5 days) | Medium | Import chain fixes, null-loader expansion, testing |
+| Req 4: Barrel Export Optimization | M (3-5 days) | Medium | Widespread refactoring of import paths |
+| Req 5: Next.js Upgrade | L-XL (1-3 weeks) | High | React 19, breaking changes, 30+ pages, plugin compat |
+| Req 6: Module Count Reduction | — | — | Outcome of Reqs 1-5 |
+| Req 7: Lazy Loading Verification | S (1 day) | Low | Already well-implemented, needs verification only |
+
+**Overall Effort:** M-L (depending on whether upgrade is pursued)
+**Overall Risk:** Medium (Phase 1) / High (if Next.js upgrade)
+
+---
+
+## 5. Research Items for Design Phase
+
+1. **Next.js 15 breaking changes inventory** — Full compatibility assessment with GROWI's Pages Router, `next-superjson`, custom webpack config
+2. **Turbopack Pages Router support** — Confirm Turbopack works with `getServerSideProps`, `pageExtensions`, custom webpack rules
+3. **null-loader effectiveness validation** — Confirm which server packages actually appear in client bundle (some may already be tree-shaken)
+4. **`bundlePagesRouterDependencies` impact measurement** — Test with GROWI-like setup to measure actual module reduction
+5. **ESLint boundary rule** — Evaluate `eslint-plugin-import` or `@nx/enforce-module-boundaries` for preventing client → server imports
+
+---
+
+## 6. Recommendations for Design Phase
+
+1. **Preferred approach:** Option C (Hybrid) — start with configuration-first optimizations, evaluate upgrade based on results
+2. **First action:** Run `ANALYZE=true pnpm run build` to generate bundle analysis report — this will immediately reveal the top module contributors
+3. **Quick wins to prioritize:**
+   - Expand `optimizePackageImports` (zero-risk config change)
+   - Fix `ActivityListItem.tsx` server import (1 file change)
+   - Verify null-loader coverage for mongoose is effective
+4. **Defer:** Next.js upgrade decision until after Phase 1 metrics are collected

+ 89 - 0
.kiro/specs/reduce-modules-loaded/requirements.md

@@ -0,0 +1,89 @@
+# Requirements Document
+
+## Introduction
+
+When running `turbo run dev` for `apps/app` and accessing a page, Next.js compiles the `[[...path]]` catch-all route with over 10,000 modules (`Compiled /[[...path]] in 51.5s (10066 modules)`). This is excessive and likely caused by unnecessary server-side modules being pulled into the client bundle, barrel export patterns causing full module tree traversal, and suboptimal tree-shaking. The goal is to investigate root causes, identify effective Next.js configuration options from official documentation, reduce the module count significantly, and improve developer experience (DX) by reducing compilation time. If a Next.js major upgrade is needed to achieve these goals, it should be pursued.
+
+## Requirements
+
+### Requirement 1: Next.js Official Configuration Research
+
+**Objective:** As a developer, I want to research and identify effective Next.js configuration options from official documentation that can reduce the module count and compilation time, so that I can apply proven optimization strategies.
+
+#### Acceptance Criteria
+
+1. The research shall evaluate the following Next.js configuration options for applicability to the GROWI Pages Router architecture:
+   - `optimizePackageImports` — barrel file optimization for packages with hundreds of re-exports (documented to reduce modules by up to 90% for libraries like `@material-ui/icons`: 11,738 → 632 modules)
+   - `bundlePagesRouterDependencies` — automatic server-side dependency bundling for Pages Router (matches App Router default behavior)
+   - `serverExternalPackages` — opt-out specific heavy/native dependencies from server-side bundling to use native Node.js `require`
+   - Turbopack adoption — automatic import optimization without manual `optimizePackageImports` config, with 14x faster cold starts and 28x faster HMR vs Webpack
+2. The research shall document which options are applicable to the current GROWI setup (Pages Router, Next.js 14, Webpack) and which require a version upgrade.
+3. The research shall produce a prioritized list of configuration changes with estimated impact, based on official Next.js benchmarks and the GROWI-specific module analysis.
+4. Where Next.js provides built-in bundle analysis tools (`@next/bundle-analyzer`, `next experimental-analyze`), the research shall evaluate their use for identifying the top module contributors in the `[[...path]]` page.
+
+### Requirement 2: Module Count Root Cause Analysis
+
+**Objective:** As a developer, I want to understand why the `[[...path]]` page loads 10,000+ modules during compilation, so that I can identify actionable optimization targets.
+
+#### Acceptance Criteria
+
+1. When the developer runs a Next.js bundle analysis on the `[[...path]]` page, the GROWI build system shall produce a report identifying the top module contributors by count and size.
+2. The GROWI build system shall identify server-side-only modules (e.g., mongoose, Express models, migration scripts) that are incorrectly included in the client-side compilation of the `[[...path]]` page.
+3. When barrel export files (index.ts with `export *`) are analyzed, the build analysis shall identify which barrel exports cause unnecessary module traversal and quantify the additional modules pulled in by each.
+
+### Requirement 3: Server-Side Module Leakage Prevention
+
+**Objective:** As a developer, I want server-side modules to be excluded from client-side compilation, so that the module count is reduced and compilation time improves.
+
+#### Acceptance Criteria
+
+1. The GROWI application shall ensure that server-side modules (Mongoose models, Express routes, migration scripts, server services) are not included in the client-side module graph of any Next.js page.
+2. When `getServerSideProps` or server-side utility functions import server-only modules, the Next.js build system shall tree-shake those imports from the client bundle.
+3. If a shared module inadvertently imports server-side code, the build system shall detect and report the import chain that causes the leakage.
+4. Where `serverExternalPackages` is available (Next.js 15+), the GROWI build system shall use it to exclude heavy server-only packages (e.g., mongoose, sharp) from server-side bundling.
+
+### Requirement 4: Barrel Export and Package Import Optimization
+
+**Objective:** As a developer, I want to reduce the impact of barrel exports on module resolution, so that importing a single hook or component does not pull in the entire module subtree.
+
+#### Acceptance Criteria
+
+1. When a single export is imported from a state module (e.g., `~/states/page`), the build system shall resolve only the necessary module and its direct dependencies, not the entire barrel export tree.
+2. The GROWI application shall avoid `export * from` patterns in high-traffic import paths (states, stores, features) where tree-shaking is ineffective.
+3. Where `optimizePackageImports` is configured in `next.config.js`, the GROWI build system shall include all internal `@growi/*` packages and high-impact third-party packages that use barrel exports.
+4. The GROWI build system shall expand the existing `optimizePackageImports` list beyond the current 11 `@growi/*` packages to cover additional barrel-heavy dependencies identified in the module analysis.
+
+### Requirement 5: Next.js Version Evaluation and Upgrade
+
+**Objective:** As a developer, I want to evaluate whether upgrading Next.js (from v14 to v15 or later) provides meaningful module optimization improvements, so that I can make an informed upgrade decision.
+
+#### Acceptance Criteria
+
+1. The evaluation shall document which Next.js 15+ features are relevant to reducing module count, specifically:
+   - Turbopack as stable/default bundler (automatic import optimization, no `optimizePackageImports` config needed)
+   - `bundlePagesRouterDependencies` option (automatic server-side dependency bundling for Pages Router)
+   - `serverExternalPackages` (stable rename of `serverComponentsExternalPackages`)
+   - Improved tree-shaking and module resolution
+2. If the Next.js upgrade is determined to be beneficial, the GROWI application shall be upgraded with all breaking changes addressed.
+3. When the upgrade is performed, the GROWI application shall pass all existing tests and build successfully.
+4. If the upgrade is determined to be not beneficial or too risky, the evaluation shall document the reasoning and alternative approaches achievable on the current version.
+
+### Requirement 6: Compilation Time and Module Count Reduction
+
+**Objective:** As a developer, I want the `[[...path]]` page compilation to be significantly faster with fewer modules, so that the development feedback loop is improved.
+
+#### Acceptance Criteria
+
+1. After optimizations, the `[[...path]]` page shall compile with significantly fewer modules than the current 10,066 (target: measurable reduction documented with before/after metrics).
+2. The GROWI application shall maintain full functional correctness after module reduction — no features shall be broken or missing.
+3. While in development mode, the GROWI application shall not show any new runtime errors or warnings introduced by the module optimization changes.
+
+### Requirement 7: Lazy Loading and Dynamic Import Verification
+
+**Objective:** As a developer, I want lazy-loaded components to be truly excluded from the initial compilation, so that they do not contribute to the module count until actually needed.
+
+#### Acceptance Criteria
+
+1. When a component is declared as "lazy loaded" (e.g., `*LazyLoaded` components), the GROWI build system shall not include that component's full dependency tree in the initial page compilation.
+2. The GROWI application shall use `next/dynamic` with `{ ssr: false }` for all heavy modal components that are not needed on initial page render.
+3. Where a lazy-loaded component wrapper (`index.ts`) re-exports the actual component statically, the GROWI application shall restructure the export to prevent static resolution of the full component tree.

+ 144 - 0
.kiro/specs/reduce-modules-loaded/research.md

@@ -0,0 +1,144 @@
+# Research & Design Decisions
+
+## Summary
+- **Feature**: `reduce-modules-loaded`
+- **Discovery Scope**: Complex Integration (build system optimization + potential major framework upgrade)
+- **Key Findings**:
+  - `next-superjson` SWC plugin is broken in Next.js 15 — critical blocker for upgrade
+  - Turbopack (default in v16) does NOT support `webpack()` config — GROWI's null-loader rules and I18NextHMRPlugin are incompatible
+  - `optimizePackageImports` expansion and barrel export refactoring are zero-risk optimizations achievable on current v14
+  - `bundlePagesRouterDependencies` + `serverExternalPackages` require Next.js 15+ but provide significant server-side bundling control
+
+## Research Log
+
+### Next.js 15 Breaking Changes for Pages Router
+- **Context**: Evaluating whether Next.js 15 upgrade is feasible for GROWI's Pages Router architecture
+- **Sources Consulted**: [Next.js v15 Upgrade Guide](https://nextjs.org/docs/app/guides/upgrading/version-15)
+- **Findings**:
+  - React 19 is minimum requirement, but backward compatibility for React 18 is available with Pages Router
+  - `bundlePagesRouterDependencies` is now stable (renamed from `experimental.bundlePagesExternals`)
+  - `serverExternalPackages` is now stable (renamed from `experimental.serverComponentsExternalPackages`)
+  - Async Request APIs change (`cookies`, `headers`, etc.) — App Router only, does NOT affect Pages Router
+  - `@next/font` package removed → must use `next/font` (codemod available)
+  - Caching defaults changed (fetch, Route Handlers) — primarily App Router concern
+- **Implications**:
+  - Pages Router migration is relatively low-impact for the async API changes
+  - The main upgrade value is `bundlePagesRouterDependencies` + `serverExternalPackages`
+  - React 18 backward compat means component migration can be gradual
+
+### next-superjson Compatibility with Next.js 15
+- **Context**: GROWI uses `next-superjson` for SSR serialization in `getServerSideProps`
+- **Sources Consulted**: [next-superjson GitHub](https://github.com/remorses/next-superjson), web search results
+- **Findings**:
+  - `next-superjson-plugin` (SWC-based) is broken in Next.js 15 due to SWC version incompatibility
+  - The `next-superjson` wrapper (used by GROWI — see `withSuperjson()` in `next.config.js`) may have the same issue
+  - GROWI registers custom ObjectId transformer via `superjson.registerCustom`
+  - Alternative: Manual superjson serialization in `getServerSideProps` without the plugin
+- **Implications**:
+  - **Critical blocker** for Next.js 15 upgrade
+  - Must either find a compatible version, migrate to manual superjson usage, or replace with native serialization
+  - This could affect all 30+ page files that use `getServerSideProps`
+
+### Turbopack Compatibility with GROWI
+- **Context**: Turbopack is the default bundler in Next.js 16; evaluating compatibility with GROWI's custom webpack config
+- **Sources Consulted**: [Turbopack API Reference](https://nextjs.org/docs/app/api-reference/turbopack)
+- **Findings**:
+  - Turbopack supports Pages Router and App Router
+  - Turbopack does NOT support `webpack()` configuration in `next.config.js`
+  - Turbopack does NOT support webpack plugins (e.g., `I18NextHMRPlugin`)
+  - Turbopack DOES support webpack loaders via `turbopack.rules` configuration
+  - Automatic import optimization eliminates need for `optimizePackageImports`
+  - Custom `pageExtensions`, `resolveAlias`, `resolveExtensions` are supported
+  - Sass is supported but `sassOptions.functions` is not
+- **GROWI-Specific Blockers**:
+  - `null-loader` rules for mongoose/dtrace-provider/mathjax-full → must be migrated to `turbopack.rules` or alternative exclusion mechanism
+  - `I18NextHMRPlugin` → no Turbopack equivalent; would need alternative HMR approach for i18n
+  - `source-map-loader` in dev mode → must be migrated to Turbopack loader config
+- **Implications**:
+  - Turbopack adoption requires migrating all custom webpack config
+  - The `--webpack` flag allows gradual migration (use Turbopack for dev, Webpack for build)
+  - Long-term Turbopack adoption is desirable but requires significant config migration
+
+### optimizePackageImports Effectiveness
+- **Context**: Evaluating whether expanding `optimizePackageImports` can reduce module count on current v14
+- **Sources Consulted**: [optimizePackageImports docs](https://nextjs.org/docs/pages/api-reference/config/next-config-js/optimizePackageImports), [Vercel blog](https://vercel.com/blog/how-we-optimized-package-imports-in-next-js)
+- **Findings**:
+  - Available since Next.js 13.5 (already usable on v14)
+  - Documented to reduce modules by up to 90% for barrel-heavy packages
+  - Benchmarks: `@material-ui/icons` 11,738 → 632 modules; `lucide-react` 1,583 → 333 modules
+  - Auto-optimized packages include: `lucide-react`, `date-fns`, `lodash-es`, `rxjs`, `@mui/*`, `recharts`, `react-use`, etc.
+  - Works by analyzing barrel files and remapping imports to specific module paths
+  - Handles nested barrel files and `export * from` patterns automatically
+- **Implications**:
+  - **Zero-risk, high-impact optimization** — can be applied immediately on v14
+  - Current GROWI config only covers 11 `@growi/*` packages
+  - Should be expanded to cover internal barrel-heavy directories and any third-party deps not in the auto-list
+
+### Bundle Analysis Tooling
+- **Context**: Need tooling to identify top module contributors and verify optimization impact
+- **Sources Consulted**: [Package Bundling Guide](https://nextjs.org/docs/pages/guides/package-bundling)
+- **Findings**:
+  - `@next/bundle-analyzer` already installed in GROWI; activated via `ANALYZE=true`
+  - `next experimental-analyze` (Turbopack-based) available in v16.1+ — more advanced with import chain tracing
+  - Bundle analyzer generates visual treemap reports for client and server bundles
+- **Implications**:
+  - Can run `ANALYZE=true pnpm run build` immediately to establish baseline
+  - Import chain tracing would help identify server module leakage paths
+  - v16.1 analyzer would be ideal but requires major version upgrade
+
+## Architecture Pattern Evaluation
+
+| Option | Description | Strengths | Risks / Limitations | Notes |
+|--------|-------------|-----------|---------------------|-------|
+| Phase 1: v14 Config Optimization | Expand optimizePackageImports, fix import violations, refactor barrel exports | Zero breaking changes, immediate impact, independently verifiable | Limited by Webpack tree-shaking; no `bundlePagesRouterDependencies` | Recommended first step |
+| Phase 2a: Next.js 15 Upgrade | Upgrade to v15 for `bundlePagesRouterDependencies` + `serverExternalPackages` | Unlocks Pages Router bundling control; stable features | next-superjson broken; React 19 migration | Requires superjson workaround |
+| Phase 2b: Turbopack Adoption (v16) | Upgrade to v16 with Turbopack default | Auto import optimization; 14x faster dev | webpack() config not supported; plugin migration | Longest-term option |
+
+## Design Decisions
+
+### Decision: Phased Approach — Config-First, Then Upgrade
+- **Context**: Need to reduce 10,066 modules with minimal risk while keeping upgrade path open
+- **Alternatives Considered**:
+  1. Direct Next.js 15 upgrade — high risk, next-superjson blocker
+  2. Config-only on v14 — safe but misses v15 bundling features
+  3. Hybrid phased approach — config first, upgrade informed by results
+- **Selected Approach**: Hybrid phased approach (Option C from gap analysis)
+- **Rationale**: Phase 1 provides immediate, low-risk wins. Phase 1 metrics inform whether Phase 2 upgrade is worth the migration cost. next-superjson blocker can be researched during Phase 1 without blocking progress.
+- **Trade-offs**: More total effort if upgrade is needed, but each phase independently delivers value
+- **Follow-up**: Measure module count after Phase 1; research next-superjson alternatives
+
+### Decision: Expand optimizePackageImports Before Refactoring Barrel Exports
+- **Context**: Both approaches reduce barrel export impact, but differ in effort and risk
+- **Alternatives Considered**:
+  1. Refactor all barrel exports to direct imports — high effort, many files affected
+  2. Expand `optimizePackageImports` to handle barrel files automatically — low effort, config-only
+  3. Both — maximum effect
+- **Selected Approach**: Expand `optimizePackageImports` first, measure impact, then refactor remaining barrels if needed
+- **Rationale**: `optimizePackageImports` achieves similar results to barrel refactoring with zero code changes. If the module count drops sufficiently, barrel refactoring may be unnecessary.
+- **Trade-offs**: `optimizePackageImports` may not catch all barrel patterns (e.g., side-effect-heavy modules)
+- **Follow-up**: Verify with bundle analysis which barrels are still problematic after config expansion
+
+### Decision: Fix Server Import Violations Over Expanding null-loader
+- **Context**: Server modules leaking into client bundle via direct imports
+- **Alternatives Considered**:
+  1. Expand null-loader rules for every server package — covers symptoms, not root cause
+  2. Fix import violations at source — eliminates the leakage path
+  3. Both — belt and suspenders
+- **Selected Approach**: Fix import violations at source as primary approach; expand null-loader as safety net for packages that might be transitively included
+- **Rationale**: Fixing imports is more maintainable than maintaining an ever-growing null-loader list. However, null-loader provides defense-in-depth for undiscovered leakage paths.
+- **Trade-offs**: Import fixes require more careful analysis; null-loader is simpler but masks problems
+- **Follow-up**: Use bundle analysis to confirm which server packages actually appear in client bundle
+
+## Risks & Mitigations
+- **Risk**: next-superjson incompatibility blocks Next.js 15 upgrade → **Mitigation**: Research alternatives during Phase 1; manual superjson serialization as fallback
+- **Risk**: Barrel export refactoring causes import breakage across codebase → **Mitigation**: Use `optimizePackageImports` first; refactor incrementally with tests
+- **Risk**: Module count reduction is insufficient from config-only changes → **Mitigation**: Bundle analysis will reveal if server module leakage is the primary cause, guiding whether upgrade is needed
+- **Risk**: I18NextHMRPlugin has no Turbopack equivalent → **Mitigation**: Use `--webpack` flag for dev until alternative is available; Turbopack adoption is Phase 2b
+
+## References
+- [Next.js v15 Upgrade Guide](https://nextjs.org/docs/app/guides/upgrading/version-15) — Breaking changes inventory
+- [Turbopack API Reference](https://nextjs.org/docs/app/api-reference/turbopack) — Supported features and known gaps
+- [optimizePackageImports (Pages Router)](https://nextjs.org/docs/pages/api-reference/config/next-config-js/optimizePackageImports) — Config documentation
+- [Package Bundling Guide (Pages Router)](https://nextjs.org/docs/pages/guides/package-bundling) — bundlePagesRouterDependencies, serverExternalPackages
+- [How we optimized package imports in Next.js](https://vercel.com/blog/how-we-optimized-package-imports-in-next-js) — Benchmarks and approach
+- [next-superjson GitHub](https://github.com/remorses/next-superjson) — Compatibility status

+ 22 - 0
.kiro/specs/reduce-modules-loaded/spec.json

@@ -0,0 +1,22 @@
+{
+  "feature_name": "reduce-modules-loaded",
+  "created_at": "2026-02-18T00:00:00.000Z",
+  "updated_at": "2026-02-19T11:00:00.000Z",
+  "language": "en",
+  "phase": "ready-for-implementation",
+  "approvals": {
+    "requirements": {
+      "generated": true,
+      "approved": true
+    },
+    "design": {
+      "generated": true,
+      "approved": true
+    },
+    "tasks": {
+      "generated": true,
+      "approved": true
+    }
+  },
+  "ready_for_implementation": true
+}

+ 197 - 0
.kiro/specs/reduce-modules-loaded/tasks.md

@@ -0,0 +1,197 @@
+# Implementation Plan
+
+## Progress Tracking Convention
+
+Analysis tasks (1.2, 3.1, 3.2, 4.1, 5.1, 5.2) may discover a large number of target files. To enable **resumability** and **progress tracking** across interrupted sessions, use the following approach:
+
+### Analysis Ledger File
+
+Create `.kiro/specs/reduce-modules-loaded/analysis-ledger.md` during task 1.2 and maintain it throughout Phase 1. This file serves as the single source of truth for discovered targets and their fix status.
+
+**Structure**:
+```markdown
+# Analysis Ledger
+
+## Measurements
+| Step | Task | Modules | Time | Date |
+|------|------|---------|------|------|
+| Baseline | 1.1 | 10,066 | 51.5s | YYYY-MM-DD |
+| After optimizePackageImports | 2.2 | N | Xs | YYYY-MM-DD |
+| ... | ... | ... | ... | ... |
+
+## Import Violations (Task 3)
+| # | File | Violation | Fix Strategy | Status |
+|---|------|-----------|--------------|--------|
+| 1 | src/client/.../ActivityListItem.tsx | imports ~/server/util/locale-utils | Extract getLocale to client util | pending |
+| 2 | src/client/.../PageBulkExportJobModelNotification.tsx | imports serializer with mongoose | Split parseSnapshot to client module | pending |
+| ... | | | | |
+
+## Server Packages in Client Bundle (Task 4)
+| # | Package | Confirmed in Client Bundle | null-loader Added | Status |
+|---|---------|---------------------------|-------------------|--------|
+| 1 | mongoose | Yes (existing rule) | Yes | done |
+| 2 | @elastic/elasticsearch | TBD | No | pending |
+| ... | | | | |
+
+## Barrel Exports to Refactor (Task 5)
+| # | File | Issue | Still Impactful After optimizePackageImports? | Status |
+|---|------|-------|-----------------------------------------------|--------|
+| 1 | src/utils/axios/index.ts | export * from 'axios' | N/A (always fix) | pending |
+| 2 | src/states/ui/editor/index.ts | 7 wildcard exports | TBD | pending |
+| ... | | | | |
+```
+
+**Rules**:
+- **Create** the ledger during task 1.2 with initial findings
+- **Append** new discoveries as each analysis task runs (tasks 3, 4, 5)
+- **Update Status** to `done` as each individual fix is applied
+- **Read** the ledger at the start of every task to understand current state
+- When resuming after an interruption, the ledger tells you exactly where to pick up
+
+## Phase 1: v14 Optimizations
+
+- [ ] 1. Establish baseline dev compilation measurement
+- [ ] 1.1 Record baseline module count and compilation time
+  - Clean the `.next` directory and start the dev server for `apps/app`
+  - Access the `[[...path]]` page route in the browser and capture the compilation log output showing module count and time
+  - Repeat the measurement 3 times (cleaning `.next` each time) and record the median values as the official baseline
+  - _Requirements: 2.1, 6.1_
+
+- [ ] 1.2 (P) Run supplementary bundle analysis and create analysis ledger
+  - Execute a production build with the bundle analyzer enabled to generate a visual treemap of the client and server bundles
+  - Identify the top module contributors by count in the `[[...path]]` page's client bundle
+  - Check whether server-only packages (mongoose, elasticsearch, passport, AWS SDK, etc.) appear in the client bundle treemap
+  - **Create `.kiro/specs/reduce-modules-loaded/analysis-ledger.md`** with the initial findings:
+    - Populate the Measurements table with the baseline from task 1.1
+    - Populate Import Violations with all discovered client→server import paths (use grep for `from '~/server/'` in `src/client/`, `src/components/`, `src/stores/`, `src/states/`)
+    - Populate Server Packages with confirmed/unconfirmed status for each candidate
+    - Populate Barrel Exports with all `export *` patterns found in high-traffic directories
+  - _Requirements: 1.4, 2.1, 2.2, 2.3_
+
+- [ ] 2. Expand `optimizePackageImports` configuration
+- [ ] 2.1 Identify barrel-heavy packages to add
+  - Review the bundle analysis findings and the transpilePackages list to identify third-party packages with barrel exports not already in the Next.js auto-optimized list
+  - Cross-reference with the list of auto-optimized packages documented in the design to avoid redundant entries
+  - Verify that candidate packages use barrel file patterns (re-export from index) that `optimizePackageImports` can optimize
+  - _Requirements: 1.1, 1.2, 1.3_
+
+- [ ] 2.2 Add candidate packages to the config and measure impact
+  - Add the identified packages to the `optimizePackageImports` array in `next.config.js`, preserving existing `@growi/*` entries
+  - Measure the dev compilation module count and time after the change, following the baseline measurement protocol
+  - **Update the Measurements table** in the analysis ledger with the post-optimization module count
+  - _Requirements: 4.3, 4.4, 6.1_
+
+- [ ] 3. Fix client-to-server import violations
+- [ ] 3.1 Scan for all import violations and update the ledger
+  - Search the entire `src/client/`, `src/components/`, `src/stores/`, and `src/states/` directories for imports from `~/server/`, `~/models/serializers/` (with server deps), or other server-only paths
+  - **Append** any newly discovered violations to the Import Violations table in the analysis ledger (the initial scan in 1.2 may not catch everything)
+  - For each violation, document the file path, the imported server module, and the proposed fix strategy
+  - _Requirements: 3.1, 3.3_
+
+- [ ] 3.2 (P) Fix all identified import violations
+  - Work through the Import Violations table in the analysis ledger, fixing each entry:
+    - Extract client-safe functions to client-accessible utility modules (e.g., `getLocale`)
+    - Split serializer files that mix server-only and client-safe functions (e.g., `parseSnapshot` vs `stringifySnapshot`)
+    - Update consumer import paths to use the new locations
+  - **Mark each entry as `done`** in the ledger as it is fixed
+  - Run type checking after each batch of fixes to catch broken imports early
+  - If interrupted, the ledger shows exactly which violations remain `pending`
+  - _Requirements: 3.1, 3.2, 3.3_
+
+- [ ] 3.3 Measure impact of import violation fixes
+  - Measure the dev compilation module count after fixing the import violations
+  - **Update the Measurements table** in the analysis ledger
+  - _Requirements: 6.1_
+
+- [ ] 4. Expand null-loader rules for server-only packages in client bundle
+- [ ] 4.1 Confirm which server packages appear in the client bundle
+  - Using the bundle analysis findings from task 1.2 and the Server Packages table in the analysis ledger, confirm each candidate package's presence in the client bundle
+  - **Update the `Confirmed in Client Bundle` column** for each entry (Yes/No)
+  - Only packages confirmed as `Yes` will receive null-loader rules
+  - _Requirements: 3.1, 3.2_
+
+- [ ] 4.2 Add null-loader rules and measure impact
+  - Add null-loader rules for all confirmed server-only packages to the webpack configuration in `next.config.js`, preserving existing rules
+  - **Mark each entry as `done`** in the ledger's `null-loader Added` column
+  - Measure the dev compilation module count after the change
+  - Manually verify no client-side runtime errors are introduced by the new exclusions
+  - **Update the Measurements table** in the analysis ledger
+  - _Requirements: 3.1, 3.2, 6.1_
+
+- [ ] 5. Refactor high-impact barrel exports
+- [ ] 5.1 Fix the axios barrel re-export
+  - Replace the `export * from 'axios'` pattern in the axios utility barrel with specific named exports that consumers actually use
+  - Update all consumer import paths if necessary
+  - This should be fixed regardless of `optimizePackageImports` results, as `export * from` a third-party library is universally problematic
+  - Run type checking to confirm no broken imports
+  - **Mark the axios entry as `done`** in the ledger
+  - _Requirements: 4.1, 4.2_
+
+- [ ] 5.2 Evaluate and refactor remaining barrel exports
+  - After applying `optimizePackageImports` expansion (task 2), check whether the state and feature barrel exports listed in the ledger are still contributing excessive modules
+  - **Update the `Still Impactful?` column** in the Barrel Exports table for each entry
+  - For entries still marked as impactful: convert wildcard `export *` patterns to explicit named re-exports or have consumers import directly from submodules
+  - **Mark each entry as `done`** in the ledger as it is refactored
+  - Update import paths across the codebase as needed, using IDE refactoring tools
+  - Run type checking and lint to verify correctness
+  - If interrupted, the ledger shows which barrel exports remain `pending`
+  - _Requirements: 4.1, 4.2_
+
+- [ ] 5.3 Measure impact of barrel export refactoring
+  - Measure the dev compilation module count after barrel refactoring
+  - **Update the Measurements table** in the analysis ledger
+  - _Requirements: 6.1_
+
+- [ ] 6. Verify lazy-loaded components are excluded from initial compilation
+  - Inspect the `*LazyLoaded` component patterns (`dynamic.tsx` + `useLazyLoader`) to confirm they do not contribute modules to the initial page compilation
+  - Verify that each lazy-loaded component's `index.ts` only re-exports from `dynamic.tsx` and never from the actual component module
+  - If any lazy-loaded components are found in the initial bundle, restructure their exports to follow the existing correct `dynamic.tsx` pattern
+  - _Requirements: 7.1, 7.2, 7.3_
+
+- [ ] 7. Phase 1 final measurement and regression verification
+- [ ] 7.1 Record final dev compilation metrics
+  - Clean the `.next` directory and measure the dev compilation module count and time using the standard protocol (3 runs, median)
+  - **Update the Measurements table** in the analysis ledger with the final row
+  - Compile a comparison table showing baseline vs. final values, with intermediate measurements from each optimization step
+  - _Requirements: 6.1, 6.2, 6.3_
+
+- [ ] 7.2 Run full regression test suite
+  - Execute type checking, linting, unit tests, and production build for `@growi/app`
+  - Perform a manual smoke test: access the `[[...path]]` page and verify page rendering, editing, navigation, and modal functionality all work correctly
+  - Confirm no new runtime errors or warnings in development mode
+  - _Requirements: 6.2, 6.3_
+
+## Phase 2: Next.js Version Upgrade Evaluation
+
+- [ ] 8. Evaluate Phase 1 results and Next.js upgrade decision
+- [ ] 8.1 Assess whether Phase 1 reduction is sufficient
+  - Review the final Measurements table in the analysis ledger
+  - Determine whether the reduction meets project goals or whether additional optimization via Next.js upgrade is warranted
+  - _Requirements: 5.1_
+
+- [ ] 8.2 Document Next.js 15+ feature evaluation
+  - Document which Next.js 15+ features (`bundlePagesRouterDependencies`, `serverExternalPackages`, Turbopack, improved tree-shaking) are relevant to further module reduction
+  - Document which features are applicable to the current GROWI Pages Router architecture vs. those that require additional migration
+  - Assess the `next-superjson` compatibility blocker and identify mitigation options (manual superjson, direct usage without SWC plugin, or alternative serialization)
+  - If the upgrade is not beneficial or too risky, document the reasoning and confirm that Phase 1 optimizations are the final solution
+  - _Requirements: 1.1, 1.2, 1.3, 5.1, 5.4_
+
+- [ ] 9. Execute Next.js 15 upgrade (conditional on task 8 decision)
+- [ ] 9.1 Run upgrade codemod and address breaking changes
+  - Run the official `@next/codemod` upgrade tool to apply automated migrations
+  - Address any breaking changes specific to the Pages Router (e.g., `@next/font` → `next/font`, renamed config options)
+  - Resolve the `next-superjson` compatibility issue using the mitigation strategy selected in task 8.2
+  - _Requirements: 5.2, 5.3_
+
+- [ ] 9.2 Enable v15-specific module optimization features
+  - Enable `bundlePagesRouterDependencies: true` in `next.config.js` for automatic server-side dependency bundling
+  - Configure `serverExternalPackages` to exclude heavy server-only packages from bundling
+  - Measure the dev compilation module count after enabling these features
+  - _Requirements: 3.4, 5.2_
+
+- [ ] 9.3 Run full regression test suite after upgrade
+  - Execute type checking, linting, unit tests, and production build
+  - Verify `getServerSideProps` superjson serialization works correctly across all page routes
+  - Verify i18n HMR still functions in development mode (may degrade if I18NextHMRPlugin is affected)
+  - Perform a manual smoke test for full functionality
+  - _Requirements: 5.3, 6.2, 6.3_