---
title: "Migrating from Farm v1 to v2"
locale: "en"
version: "current"
canonicalUrl: "https://farmfe.org/docs/migration/v1-to-v2"
publicationStatus: "prerelease"
---

<a id="migrating-from-farm-v1-to-v2"></a>
# 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.


<a id="overview-of-changes"></a>
## Overview of Changes


Farm v2 includes:


- **New Output Formats**: Added ` umd `, ` iife `, ` system `, ` amd ` formats (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 modules ` localsConversion `, ` minify.include `/` exclude `, ` persistentCache.envs `, ` persistentCache.globalBuiltinCacheKeyStrategy `
- **Build pipeline changes**: Updated bundling and plugin integration; measure your actual application and cache settings.


<a id="breaking-changes"></a>
## Breaking Changes


<a id="configuration-changes"></a>
### Configuration Changes


<a id="use-the-server-configuration-key"></a>
#### 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:**


```ts
// Check the API of your installed v1 release
export default {
  devServer: {
    port: 9000,
    hmr: true,
  }
}
```


**v2:**


```ts
// farm.config.ts (v2)
export default {
  server: {
    port: 9000,
    hmr: true,
  }
}
```


<a id="serverspa-replaced-by-serverapptype"></a>
#### ` server.spa ` replaced by ` server.appType `


The ` spa ` boolean option has been replaced with ` appType `:


```ts
// v1: spa: true/false
// v2: appType: 'spa' | 'mpa' | 'custom'
export default {
  server: {
    appType: 'spa', // default
  }
}
```


<a id="new-server-options-in-v2"></a>
#### New ` server ` options in v2


- ` origin ` — Set the origin of the dev server URLs
- ` allowedHosts ` — Restrict which hosts can access the server
- ` middlewareMode ` — 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


<a id="server-middleware-api-change"></a>
### Server Middleware API Change


**Breaking**: Farm v2 uses [connect](<https://github.com/senchalabs/connect>) middleware instead of Koa.


**v1 (Koa):**


```ts
import { Middleware } from 'koa';

function myMiddleware(server): Middleware {
  return async (ctx, next) => {
    ctx.set('X-Custom', 'value');
    await next();
  };
}
```


**v2 (connect):**


```ts
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 `).


<a id="hmr-origin-validation"></a>
### 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:**


1. Ensure your client and server use matching hostnames/domains
2. Update your HMR configuration if needed:


```ts
// farm.config.ts
export default {
  server: {
    hmr: {
      host: 'localhost',
      port: 9801,
    }
  }
}
```


<a id="hmr-new-sub-options"></a>
### 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 milliseconds
- ` overlay ` — Show/hide error overlay in browser (default: ` true `)
- ` protocol ` — WebSocket protocol (` ws ` or ` wss `)


<a id="plugin-api-changes"></a>
### Plugin API Changes


<a id="rust-plugin-api"></a>
#### Rust Plugin API


The Rust plugin trait has been enhanced with new hooks. See the [Rust Plugin API documentation](</docs/api/rust-plugin-api>) for detailed information.


New hooks in v2:


- ` freeze_module ` — Called after a module is frozen
- ` module_graph_build_end ` — Called when the module graph build is complete
- ` freeze_module_graph_meta ` — Freeze module graph metadata
- ` process_resource_pots ` — Process resource pots after bundling
- ` process_rendered_resource_pot ` — Process a resource pot after rendering
- ` augment_resource_pot_hash ` — Augment resource pot hash
- ` process_generated_resources ` — Process resources after generation
- ` handle_entry_resource ` — Handle entry resource processing
- ` module_graph_updated ` — Called after module graph is updated during HMR
- ` update_finished ` — Called when HMR update is finished
- ` handle_persistent_cached_module ` — Handle loading a module from persistent cache


<a id="javascript-plugin-api"></a>
#### JavaScript Plugin API


The JavaScript plugin interface has added new hooks. See the [JavaScript Plugin API documentation](</docs/api/js-plugin-api>) for detailed information.


New hooks in v2:


- ` freezeModule ` — Called after a module is frozen
- ` processRenderedResourcePot ` — Process a resource pot after rendering
- ` augmentResourcePotHash ` — Augment resource pot hash
- ` finalizeResources ` — Finalize all resources before output
- ` updateFinished ` — Called when HMR update is finished


<a id="step-by-step-migration-guide"></a>
## Step-by-Step Migration Guide


<a id="1-update-farm-version"></a>
### 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.


```bash
npm view @farmfe/core dist-tags --json
npm view @farmfe/cli dist-tags --json
```


<a id="2-update-configuration-file"></a>
### 2. Update Configuration File


Review your ` farm.config.ts ` or ` farm.config.js `:


1. **Rename ` devServer ` to ` server `**
   
   
   ```ts
   // Before (v1)
   export default { devServer: { port: 9000 } }
   // After (v2)
   export default { server: { port: 9000 } }
   ```
2. **Replace ` spa ` with ` appType `**
   
   
   ```ts
   // Before (v1)
   server: { spa: true }
   // After (v2)
   server: { appType: 'spa' }
   ```
3. **Update middleware to connect-style** (see [Server Middleware API Change](</docs/migration/v1-to-v2#server-middleware-api-change>))
4. **Test configuration validity**
   
   
   ```bash
   farm build
   ```


<a id="3-update-plugins"></a>
### 3. Update Plugins


If you're using custom plugins:


1. **Rust plugins**: Review the [Rust Plugin API documentation](</docs/api/rust-plugin-api>) for any hook signature changes
2. **JavaScript plugins**: Review the [JavaScript Plugin API documentation](</docs/api/js-plugin-api>) for any hook signature changes


For official plugins, ensure they're v2-compatible:


```bash
npm install @farmfe/plugin-{feature}@latest
```


<a id="4-verify-development-server"></a>
### 4. Verify Development Server


Test that HMR is working correctly:


```bash
farm dev
```


If you encounter HMR connection errors:


- Check browser console for specific error messages
- Verify that ` server.hmr ` settings match your deployment environment
- Ensure no origin-related proxies are interfering


<a id="5-test-build-output"></a>
### 5. Test Build Output


```bash
farm build
```


Verify that:


- All assets are generated correctly
- Code splitting is working as expected
- Source maps are generated (if enabled)


<a id="configuration-migration-reference"></a>
## Configuration Migration Reference


| v1 Setting | v2 Location | Notes |
| --- | --- | --- |
| ` compilation.external ` | ` compilation.external ` | Still configured under ` compilation `; review current [compilation options](</docs/config/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. |


<a id="troubleshooting-common-issues"></a>
## Troubleshooting Common Issues


<a id="hmr-connection-rejected-with-origin-check-failed"></a>
### "HMR connection rejected with origin check failed"


**Cause**: The server is rejecting your HMR client connection due to origin mismatch.


**Solution**:


1. Check that your client and server are using the same host/domain
2. Configure HMR explicitly if needed:
   ```javascript
   {
     server: {
       hmr: {
         host: 'your-domain.com',
         port: 9801
       }
     }
   }
   ```


<a id="configuration-errors-for-moved-settings"></a>
### Configuration errors for moved settings


**Cause**: You're still using the old ` config.custom.* ` structure.


**Solution**: Move settings to top-level ` config `:


```javascript
// Old (v1)
export default {
  config: {
    custom: {
      myOption: value
    }
  }
}

// New (v2)
export default {
  myOption: value
}
```


<a id="plugin-hooks-not-being-called"></a>
### Plugin hooks not being called


**Cause**: Plugin hook signatures or names have changed.


**Solution**: Check the updated [JavaScript Plugin API](</docs/api/js-plugin-api>) and [Rust Plugin API](</docs/api/rust-plugin-api>) for the latest hook specifications.


<a id="getting-help"></a>
## Getting Help


- Review the [Configuration documentation](</docs/config/configuring-farm>)
- Check the [Plugin documentation](</docs/plugins/official-plugins/overview>)
- Visit the [Farm GitHub discussions](<https://github.com/farm-fe/farm/discussions>)
- Join the [Discord community](<https://discord.com/invite/mDErq9aFnF>)


<a id="see-also"></a>
## See Also


- [Configuration Reference](</docs/config/configuring-farm>)
- [Rust Plugin API](</docs/api/rust-plugin-api>)
- [JavaScript Plugin API](</docs/api/js-plugin-api>)
