Migrating from Farm v1 to v2
Farm v2 introduces significant improvements and changes to the configuration system, plugin APIs, and overall architecture. This guide will help you migrate your Farm v1 project to v2.
Overview of Changes
Farm v2 includes:
- New Output Formats: Added
umd,iife,system,amdformats (and array of formats) - Enhanced Plugin System: New Rust and JavaScript plugin hooks
- Server Middleware Rewrite: Replaced Koa with connect-style middleware
- HMR configuration: Origin validation depends on server mode; new sub-options (
clientPort,path,timeout,overlay,protocol) - New Features: CSS
transformToScript, CSS moduleslocalsConversion,minify.include/exclude,persistentCache.envs,persistentCache.globalBuiltinCacheKeyStrategy - Build pipeline changes: Updated bundling and plugin integration; measure your actual application and cache settings.
Breaking Changes
Configuration Changes
Use the server configuration key
Use server in v2. Do not apply a blanket rename to every v1 project: keep server if it is already present, and only replace devServer in older examples that use it.
Older configuration example:
// Check the API of your installed v1 release
export default {
devServer: {
port: 9000,
hmr: true,
}
}
v2:
// farm.config.ts (v2)
export default {
server: {
port: 9000,
hmr: true,
}
}
server.spa replaced by server.appType
The spa boolean option has been replaced with appType:
// v1: spa: true/false
// v2: appType: 'spa' | 'mpa' | 'custom'
export default {
server: {
appType: 'spa', // default
}
}
New server options in v2
origin— Set the origin of the dev server URLsallowedHosts— Restrict which hosts can access the servermiddlewareMode— Declared in the schema, but the current public path does not provide a verified middleware/HMR embedding workflow. It creates no HTTP server, while HMR initialization requires one.preview— Dedicated preview server configuration
Server Middleware API Change
Breaking: Farm v2 uses connect middleware instead of Koa.
v1 (Koa):
import { Middleware } from 'koa';
function myMiddleware(server): Middleware {
return async (ctx, next) => {
ctx.set('X-Custom', 'value');
await next();
};
}
v2 (connect):
function myMiddleware(server) {
return (req, res, next) => {
res.setHeader('X-Custom', 'value');
next();
};
}
Replace any koa-* middleware packages with their connect/express-compatible equivalents (e.g. koa-compress → compression).
HMR Origin Validation
Change: The HMR server now validates the Origin header from clients.
v1 behavior: HMR accepted connections from any origin
v2 behavior: HMR rejects connections with unrecognized Origin headers
What to do if you get HMR errors:
- Ensure your client and server use matching hostnames/domains
- Update your HMR configuration if needed:
// farm.config.ts
export default {
server: {
hmr: {
host: 'localhost',
port: 9801,
}
}
}
HMR New Sub-Options
v2 adds new HMR configuration options:
clientPort— Port for the HMR client (useful behind proxies)path— Custom HMR endpoint path (default:/__hmr)timeout— Connection timeout in millisecondsoverlay— Show/hide error overlay in browser (default:true)protocol— WebSocket protocol (wsorwss)
Plugin API Changes
Rust Plugin API
The Rust plugin trait has been enhanced with new hooks. See the Rust Plugin API documentation for detailed information.
New hooks in v2:
freeze_module— Called after a module is frozenmodule_graph_build_end— Called when the module graph build is completefreeze_module_graph_meta— Freeze module graph metadataprocess_resource_pots— Process resource pots after bundlingprocess_rendered_resource_pot— Process a resource pot after renderingaugment_resource_pot_hash— Augment resource pot hashprocess_generated_resources— Process resources after generationhandle_entry_resource— Handle entry resource processingmodule_graph_updated— Called after module graph is updated during HMRupdate_finished— Called when HMR update is finishedhandle_persistent_cached_module— Handle loading a module from persistent cache
JavaScript Plugin API
The JavaScript plugin interface has added new hooks. See the JavaScript Plugin API documentation for detailed information.
New hooks in v2:
freezeModule— Called after a module is frozenprocessRenderedResourcePot— Process a resource pot after renderingaugmentResourcePotHash— Augment resource pot hashfinalizeResources— Finalize all resources before outputupdateFinished— Called when HMR update is finished
Step-by-Step Migration Guide
1. Update Farm Version
Check the published channels before selecting matching v2 core, CLI and plugin versions. latest is not proof of a v2 release, and package major versions need not match. The candidate documented here is not an instruction to publish or install an unavailable version. Preserve the resolved lockfile.
npm view @farmfe/core dist-tags --json
npm view @farmfe/cli dist-tags --json
2. Update Configuration File
Review your farm.config.ts or farm.config.js:
-
Rename
devServertoserverts// Before (v1) export default { devServer: { port: 9000 } } // After (v2) export default { server: { port: 9000 } } -
Replace
spawithappTypets// Before (v1) server: { spa: true } // After (v2) server: { appType: 'spa' } -
Update middleware to connect-style (see Server Middleware API Change)
-
Test configuration validity
bashfarm build
3. Update Plugins
If you're using custom plugins:
- Rust plugins: Review the Rust Plugin API documentation for any hook signature changes
- JavaScript plugins: Review the JavaScript Plugin API documentation for any hook signature changes
For official plugins, ensure they're v2-compatible:
npm install @farmfe/plugin-{feature}@latest
4. Verify Development Server
Test that HMR is working correctly:
farm dev
If you encounter HMR connection errors:
- Check browser console for specific error messages
- Verify that
server.hmrsettings match your deployment environment - Ensure no origin-related proxies are interfering
5. Test Build Output
farm build
Verify that:
- All assets are generated correctly
- Code splitting is working as expected
- Source maps are generated (if enabled)
Configuration Migration Reference
| v1 Setting | v2 Location | Notes |
|---|---|---|
compilation.external | compilation.external | Still configured under compilation; review current compilation options. |
compilation.custom.* | compilation.custom.* | Still available for custom compiler/plugin metadata; avoid moving it to top-level config. |
devServer | server | Dev server config was renamed. |
devServer.hmr | server.hmr | Same purpose, but now validates Origin header and supports more sub-options. |
Troubleshooting Common Issues
"HMR connection rejected with origin check failed"
Cause: The server is rejecting your HMR client connection due to origin mismatch.
Solution:
- Check that your client and server are using the same host/domain
- Configure HMR explicitly if needed:
javascript
{ server: { hmr: { host: 'your-domain.com', port: 9801 } } }
Configuration errors for moved settings
Cause: You're still using the old config.custom.* structure.
Solution: Move settings to top-level config:
// Old (v1)
export default {
config: {
custom: {
myOption: value
}
}
}
// New (v2)
export default {
myOption: value
}
Plugin hooks not being called
Cause: Plugin hook signatures or names have changed.
Solution: Check the updated JavaScript Plugin API and Rust Plugin API for the latest hook specifications.
Getting Help
- Review the Configuration documentation
- Check the Plugin documentation
- Visit the Farm GitHub discussions
- Join the Discord community
Farm