Build System Notes - Phase 3
Current Status
Development Build ✅
- Status: Fully functional
- Build tool: Turbopack (via
npm run dev) - Startup time: ~500ms
- Hot reload: Working
- Package resolution: Symlinked packages work perfectly
Production Build ❌
- Status: Blocked by Turbopack limitation
- Build tool: Turbopack (via
npm run build) - Issue: Turbopack cannot resolve symlinked packages (
file:protocol dependencies) in production builds - Error: “Module not found: Can’t resolve ‘@sofondo/core’” (and similar for other framework packages)
Technical Analysis
The Problem
Next.js 16 uses Turbopack as the default bundler for both development and production builds. While Turbopack handles symlinked packages fine in development mode, it fails to resolve them during production builds.
The platform uses file: protocol dependencies in package.json:
{
"dependencies": {
"@sofondo/core": "file:../sofondo-monorepo/packages/core",
"@sofondo/react": "file:../sofondo-monorepo/packages/react",
"@sofondo/styles": "file:../sofondo-monorepo/packages/styles"
}
}
These create symlinks in node_modules/@sofondo/* pointing to the monorepo packages. Turbopack’s production bundler cannot follow these symlinks properly.
Why Webpack Doesn’t Help
- Next.js 16 has Turbopack as the only production bundler
- The
TURBOPACK=0environment variable is ignored during builds - There is no
--no-turbopackflag fornext build - Webpack is no longer available as a production build option in Next.js 16
Solutions
Solution 1: Publish to npm Registry (Recommended for v1.0)
When to use: Production releases, public/private npm packages
Pros:
- Standard npm workflow
- Works with all build tools
- Easy for external consumers
- Semantic versioning
- Can be private or public
Cons:
- Requires publishing step
- Version management overhead
- Need npm account/organization
Implementation:
# In monorepo
cd packages/core && npm publish --access restricted
cd packages/react && npm publish --access restricted
cd packages/styles && npm publish --access restricted
# In platform, update package.json
{
"dependencies": {
"@sofondo/core": "^0.1.0",
"@sofondo/react": "^0.1.0",
"@sofondo/styles": "^0.1.0"
}
}
Solution 2: GitHub Packages (Recommended for Now)
When to use: Private packages during development, team collaboration
Pros:
- Free for private repos
- Git-based workflow
- No need for npm account
- Automated with GitHub Actions
Cons:
- Requires GitHub authentication
- Slightly more setup than npm
Implementation:
- Add
.npmrcto monorepo root:
@sofondo:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
- Update
package.jsonin each package:
{
"publishConfig": {
"registry": "https://npm.pkg.github.com/@sofondo"
}
}
- Publish packages:
npm publish
- Update platform dependencies to use versions instead of
file:
Solution 3: Local Verdaccio Registry
When to use: Local development, testing publish workflow
Pros:
- Local npm registry
- No external dependencies
- Test publish process
- Fast
Cons:
- Extra service to run
- Not suitable for production
- Need to configure registry
Implementation:
# Install and run Verdaccio
npm install -g verdaccio
verdaccio
# Configure npm to use local registry
npm set registry http://localhost:4873
# Publish packages
cd packages/core && npm publish
Solution 4: Yalc (Alternative to symlinks)
When to use: Local development when symlinks don’t work
Pros:
- Copies files instead of symlinking
- Works with all bundlers
- Simple workflow
- No registry needed
Cons:
- Manual update step
- Not real-time like symlinks
- Extra tool dependency
Implementation:
# Install yalc
npm install -g yalc
# In monorepo packages
cd packages/core && yalc publish
cd packages/react && yalc publish
cd packages/styles && yalc publish
# In platform
yalc add @sofondo/core @sofondo/react @sofondo/styles
# After changes to framework
cd packages/core && yalc push
Solution 5: Move Platform into Monorepo (Long-term)
When to use: When ready to consolidate
Pros:
- Single repo for everything
- No symlink/registry issues
- Shared tooling
- Easier version management
Cons:
- Larger repo
- Different workflow
- Migration effort
Implementation:
Move sofondo-platform to sofondo-monorepo/apps/platform and update Turborepo config to include apps.
Recommendations
For Current Development (Phase 3)
- Keep using symlinks for development - Works perfectly with
npm run dev - Accept production build limitation for now - Focus on feature development
- Document the limitation - Make it clear in README
For Next Steps (Phase 4+)
- Set up GitHub Packages - Enables production builds and team collaboration
- Add publish workflow - Automate with GitHub Actions
- Version management - Use changesets or similar tool
For v1.0 Release
- Publish to npm - Public or private depending on strategy
- Semantic versioning - Follow semver strictly
- Migration guide - Help users upgrade
Current Workarounds
Until we implement one of the solutions above:
- Development: Use
npm run dev- works perfectly ✅ - Testing: Manual testing in dev mode
- Deployment: Not applicable yet (early development phase)
Next Steps for Phase 3
Since production builds are blocked by Turbopack, we’ll focus on:
- ✅ Document build system (this file)
- ⏭️ Review Turborepo caching configuration
- ⏭️ Analyze dev mode bundle sizes
- ⏭️ Optimize development experience
- ⏭️ Plan registry/publish strategy