From 1bf0838991b4db9125ed2bc2bdbd12b7c284bb20 Mon Sep 17 00:00:00 2001 From: Nick Schot Date: Tue, 10 Mar 2026 11:48:59 +0100 Subject: [PATCH 01/10] Add ember-mirage blog post --- src/posts/2026-03-13-ember-mirage.md | 179 +++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 src/posts/2026-03-13-ember-mirage.md diff --git a/src/posts/2026-03-13-ember-mirage.md b/src/posts/2026-03-13-ember-mirage.md new file mode 100644 index 0000000000..6120be36f1 --- /dev/null +++ b/src/posts/2026-03-13-ember-mirage.md @@ -0,0 +1,179 @@ +--- +title: "Migrating to ember-mirage: Modern MirageJS for Vite and Embroider" +authorHandle: nickschot +tags: [ember, mirage, mainmatter] +bio: "Nick Schot" +description: "Nick Schot explains how to migrate from ember-cli-mirage to a miragejs + ember-mirage setup supported by Vite" +tagline: "If you've been developing Ember applications with API mocking, you're likely familiar with ember-cli-mirage. ember-cli-mirage has been a corner-stone for writing representative tests that rely on a backend API. It allows you to create focused test scenarios with exactly the data you need for that test. Additionally it can be used to develop frontend features before the API even exists. But there's a problem: ember-cli-mirage doesn't work with Vite! As the Ember ecosystem continues to move toward modern build tooling with Embroider and Vite, we need a solution that brings MirageJS along for the journey. This blog post outlines a path forward to setup MirageJS directly in modern Ember applications." +autoOg: true +--- + +# MirageJS & ember-mirage +MirageJS is the core library. At some point in the past this was extracted from ember-cli-mirage to its own library for framework independent use. Ember-mirage is a set of utilities that brings some of the benefits ember-cli-mirage provided. This means that for basic setup, you may not actually need it, but it provides some features that ember-cli-mirage used to provide that might make migrating a little easier. + +The first thing we'll do is add MirageJS and ember-mirage as dependencies. +``` +pnpm install -D miragejs ember-mirage +``` + +With ember-cli-mirage, all mirage related files lived in a top-level `/mirage` folder. This is still where we'll keep our MirageJS configuration, factories, models and other modules. + +In order to start our new setup we'll create a default server configuration which will serve as the entry point. + +```javascript +// mirage/servers/default.js +import { createServer } from 'miragejs'; + +export async function makeServer(config) { + return createServer({ + ...config, + }); +} +``` + +One of the features in which ember-cli-mirage followed ember.js is a lot of files were placed in certain spots by convention. In order to provide a similar setup, we can use the `createConfig` utility provided by ember-mirage to load all our Mirage factories, fixtures, models, serializers and identity managers. We can use Vite's `import.meta.glob` to import all of them at once from their folders. The generated config can then be splatted into the config passed to the `createServer` call. + +```javascript +// mirage/servers/default.js +import { createConfig } from 'ember-mirage'; + +const mirageConfig = await createConfig({ + factories: import.meta.glob('../factories/*'), + fixtures: import.meta.glob('../fixtures/*'), + models: import.meta.glob('../models/*'), + serializers: import.meta.glob('../serializers/*'), + identityManagers: import.meta.glob('../identity-managers/*'), +}); + +export async function makeServer(config) { + return createServer({ + ...mirageConfig, + ...config + }); +} +``` + +## Loading ember-data models +Another feature ember-cli-mirage provided was automatically inferring Mirage models from ember-data models, meaning MirageJS will infer model names and their relationships from the ember-data models. The configuration roughly matches the previous one. +```javascript +// mirage/servers/default.js +import { importEmberDataModels } from 'ember-mirage/ember-data'; +const emberDataModels = import.meta.glob('../../app/models/**/*'); + +export async function makeServer(config, _store) { + // Don't attempt to import from test-helpers when running in the app + let store = _store ?? + (await import('@ember/test-helpers')).getContext().owner.lookup('service:store'); + + return createServer({ + /* ... */ + + models: { + ...importEmberDataModels(store, emberDataModels), + ...config.models + } + }); +} +``` +If you want the ability to pass custom models, be sure to also splat `config.models` in the way the above config does. + +## Defining Mirage routes +Defining routes hasn't really changed. This happens within the `routes() { … }` function part of the `createServer` configuration object. In practice you'll likely want to define your routes in some folder structure for better manageability. + +```javascript +// mirage/servers/default.js +import { createServer } from 'miragejs'; + +export async function makeServer(config) { + /* ... */ + + return createServer({ + /* ... */ + routes() { + this.get('users', function (schema) { + return schema.users.all(); + }); + }, + }); +} +``` + +## Integrating with the test setup +We've added a lot of configuration, but we don't actually boot MirageJS anywhere. Let's add a test helper that uses our previously created `makeServer` function. We'll also set the `environment` to `test`. This [configuration option](https://miragejs.com/docs/testing/application-tests/#the-test-environment) defaults to `development` which adds a default delay of 50ms to every request. Not something we want for tests! The config is also written in a way that allows you to pass a custom `makeServer` when setting up Mirage in a test. + +```javascript +// /tests/helpers/setup-mirage.js +import { setupMirage as upstreamSetupMirage } from 'ember-mirage/test-support'; +import { makeServer } from 'my-app/mirage/servers/default'; +export function setupMirage(hooks, options) { + options = options || {}; + options.createServer = options.makeServer || makeServer; + upstreamSetupMirage(hooks, { + ...options, + config: { + ...options.config, + environment: 'test', + }, + }); +} +``` + +## Trying it out! +We have everything we need to test the basics. Below is a quick unit test to verify that everything is working as intended. + +```javascript +// tests/unit/example-test.js +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; +import { setupMirage } from '../helpers/setup-mirage'; + +module('Unit | Mirage | example tests', function (hooks) { + setupTest(hooks); + setupMirage(hooks); + test('it works!', async function (assert) { + let mirageUser = this.server.create('user', { name: 'Chris' }); + let store = this.owner.lookup('service:store'); + let emberDataUser = await store.findRecord('user', mirageUser.id); + assert.strictEqual(mirageUser.name, emberDataUser.name); + }); +}); +``` + +## What about using it in the app itself? +You may also want to use Mirage during development, for example to work on a feature before the backend API is ready. We can use `@embroider/macros` to conditionally start the Mirage server in a way that ensures it is completely excluded from production builds. + +```javascript +// app/routes/application.js +import Route from '@ember/routing/route'; +import { isDevelopingApp, isTesting, macroCondition } from '@embroider/macros'; +import { service } from '@ember/service'; +import config from '../config/environment'; + +export default class ApplicationRoute extends Route { + @service store; + + async beforeModel() { + if (macroCondition(isDevelopingApp() && !isTesting()) && config.useMirage) { + let { makeServer } = await import('../mirage/servers/default'); + let server = await makeServer({ + environment: 'development', + scenarios: await import('../mirage/scenarios'), + }, + this.store, + ); + server.logging = true; + } + } +} +``` +The `macroCondition` with `isDevelopingApp() && !isTesting()` ensures the entire block is tree-shaken from the production build. The dynamic `await import()` of the server configuration means none of your Mirage code will be bundled in production either. The additional `config.useMirage` flag gives you a way to toggle Mirage on and off during development via your environment configuration. + +We pass the ember-data `store` to `makeServer` so that Mirage can generate its models from your ember-data models. We also import a scenarios module, which is simply a function that seeds the Mirage database with development data. Finally, enabling `server.logging` will log all intercepted requests and responses to the browser console, which is useful for debugging. + +## Caveats +ember-mirage is still under active development. The setup described in this post is specific to Ember apps using Vite. If you're still on a classic build (without Vite), the setup will differ slightly. In particular, `import.meta.glob` is not available in classic builds. In that case you can use `ember-auto-import`'s `allowAppImports` combined with Webpack's `require.context` as an alternative for auto-importing your Mirage modules. + +## Wrapping up +Migrating from ember-cli-mirage to ember-mirage requires a bit more manual setup, but the result is a Vite and Embroider compatible MirageJS configuration that stays close to the native MirageJS experience, with ember-mirage providing utilities to make migration easier for situations where there was a reliance on ember-cli-mirage. + +For more details, check out the [ember-mirage repository](https://github.com/bgantzler/ember-mirage). From 314e8995ed1a88e5b3a1ce1070fd311d284323de Mon Sep 17 00:00:00 2001 From: Nick Schot Date: Tue, 10 Mar 2026 12:30:25 +0100 Subject: [PATCH 02/10] Format --- src/posts/2026-03-13-ember-mirage.md | 174 +++++++++++++++------------ 1 file changed, 95 insertions(+), 79 deletions(-) diff --git a/src/posts/2026-03-13-ember-mirage.md b/src/posts/2026-03-13-ember-mirage.md index 6120be36f1..645b7ac961 100644 --- a/src/posts/2026-03-13-ember-mirage.md +++ b/src/posts/2026-03-13-ember-mirage.md @@ -9,9 +9,11 @@ autoOg: true --- # MirageJS & ember-mirage + MirageJS is the core library. At some point in the past this was extracted from ember-cli-mirage to its own library for framework independent use. Ember-mirage is a set of utilities that brings some of the benefits ember-cli-mirage provided. This means that for basic setup, you may not actually need it, but it provides some features that ember-cli-mirage used to provide that might make migrating a little easier. The first thing we'll do is add MirageJS and ember-mirage as dependencies. + ``` pnpm install -D miragejs ember-mirage ``` @@ -22,12 +24,12 @@ In order to start our new setup we'll create a default server configuration whic ```javascript // mirage/servers/default.js -import { createServer } from 'miragejs'; +import { createServer } from "miragejs"; export async function makeServer(config) { - return createServer({ - ...config, - }); + return createServer({ + ...config, + }); } ``` @@ -35,145 +37,159 @@ One of the features in which ember-cli-mirage followed ember.js is a lot of file ```javascript // mirage/servers/default.js -import { createConfig } from 'ember-mirage'; +import { createConfig } from "ember-mirage"; const mirageConfig = await createConfig({ - factories: import.meta.glob('../factories/*'), - fixtures: import.meta.glob('../fixtures/*'), - models: import.meta.glob('../models/*'), - serializers: import.meta.glob('../serializers/*'), - identityManagers: import.meta.glob('../identity-managers/*'), + factories: import.meta.glob("../factories/*"), + fixtures: import.meta.glob("../fixtures/*"), + models: import.meta.glob("../models/*"), + serializers: import.meta.glob("../serializers/*"), + identityManagers: import.meta.glob("../identity-managers/*"), }); export async function makeServer(config) { - return createServer({ - ...mirageConfig, - ...config - }); + return createServer({ + ...mirageConfig, + ...config, + }); } ``` ## Loading ember-data models + Another feature ember-cli-mirage provided was automatically inferring Mirage models from ember-data models, meaning MirageJS will infer model names and their relationships from the ember-data models. The configuration roughly matches the previous one. + ```javascript // mirage/servers/default.js -import { importEmberDataModels } from 'ember-mirage/ember-data'; -const emberDataModels = import.meta.glob('../../app/models/**/*'); +import { importEmberDataModels } from "ember-mirage/ember-data"; +const emberDataModels = import.meta.glob("../../app/models/**/*"); export async function makeServer(config, _store) { - // Don't attempt to import from test-helpers when running in the app - let store = _store ?? - (await import('@ember/test-helpers')).getContext().owner.lookup('service:store'); - - return createServer({ - /* ... */ - - models: { - ...importEmberDataModels(store, emberDataModels), - ...config.models - } - }); + // Don't attempt to import from test-helpers when running in the app + let store = + _store ?? + (await import("@ember/test-helpers")) + .getContext() + .owner.lookup("service:store"); + + return createServer({ + /* ... */ + + models: { + ...importEmberDataModels(store, emberDataModels), + ...config.models, + }, + }); } ``` + If you want the ability to pass custom models, be sure to also splat `config.models` in the way the above config does. ## Defining Mirage routes + Defining routes hasn't really changed. This happens within the `routes() { … }` function part of the `createServer` configuration object. In practice you'll likely want to define your routes in some folder structure for better manageability. ```javascript // mirage/servers/default.js -import { createServer } from 'miragejs'; +import { createServer } from "miragejs"; export async function makeServer(config) { - /* ... */ + /* ... */ - return createServer({ - /* ... */ - routes() { - this.get('users', function (schema) { - return schema.users.all(); - }); - }, - }); + return createServer({ + /* ... */ + routes() { + this.get("users", function (schema) { + return schema.users.all(); + }); + }, + }); } ``` ## Integrating with the test setup + We've added a lot of configuration, but we don't actually boot MirageJS anywhere. Let's add a test helper that uses our previously created `makeServer` function. We'll also set the `environment` to `test`. This [configuration option](https://miragejs.com/docs/testing/application-tests/#the-test-environment) defaults to `development` which adds a default delay of 50ms to every request. Not something we want for tests! The config is also written in a way that allows you to pass a custom `makeServer` when setting up Mirage in a test. ```javascript // /tests/helpers/setup-mirage.js -import { setupMirage as upstreamSetupMirage } from 'ember-mirage/test-support'; -import { makeServer } from 'my-app/mirage/servers/default'; +import { setupMirage as upstreamSetupMirage } from "ember-mirage/test-support"; +import { makeServer } from "my-app/mirage/servers/default"; export function setupMirage(hooks, options) { - options = options || {}; - options.createServer = options.makeServer || makeServer; - upstreamSetupMirage(hooks, { - ...options, - config: { - ...options.config, - environment: 'test', - }, - }); + options = options || {}; + options.createServer = options.makeServer || makeServer; + upstreamSetupMirage(hooks, { + ...options, + config: { + ...options.config, + environment: "test", + }, + }); } ``` ## Trying it out! + We have everything we need to test the basics. Below is a quick unit test to verify that everything is working as intended. ```javascript // tests/unit/example-test.js -import { module, test } from 'qunit'; -import { setupTest } from 'ember-qunit'; -import { setupMirage } from '../helpers/setup-mirage'; - -module('Unit | Mirage | example tests', function (hooks) { - setupTest(hooks); - setupMirage(hooks); - test('it works!', async function (assert) { - let mirageUser = this.server.create('user', { name: 'Chris' }); - let store = this.owner.lookup('service:store'); - let emberDataUser = await store.findRecord('user', mirageUser.id); - assert.strictEqual(mirageUser.name, emberDataUser.name); - }); +import { module, test } from "qunit"; +import { setupTest } from "ember-qunit"; +import { setupMirage } from "../helpers/setup-mirage"; + +module("Unit | Mirage | example tests", function (hooks) { + setupTest(hooks); + setupMirage(hooks); + test("it works!", async function (assert) { + let mirageUser = this.server.create("user", { name: "Chris" }); + let store = this.owner.lookup("service:store"); + let emberDataUser = await store.findRecord("user", mirageUser.id); + assert.strictEqual(mirageUser.name, emberDataUser.name); + }); }); ``` ## What about using it in the app itself? + You may also want to use Mirage during development, for example to work on a feature before the backend API is ready. We can use `@embroider/macros` to conditionally start the Mirage server in a way that ensures it is completely excluded from production builds. ```javascript // app/routes/application.js -import Route from '@ember/routing/route'; -import { isDevelopingApp, isTesting, macroCondition } from '@embroider/macros'; -import { service } from '@ember/service'; -import config from '../config/environment'; +import Route from "@ember/routing/route"; +import { isDevelopingApp, isTesting, macroCondition } from "@embroider/macros"; +import { service } from "@ember/service"; +import config from "../config/environment"; export default class ApplicationRoute extends Route { - @service store; - - async beforeModel() { - if (macroCondition(isDevelopingApp() && !isTesting()) && config.useMirage) { - let { makeServer } = await import('../mirage/servers/default'); - let server = await makeServer({ - environment: 'development', - scenarios: await import('../mirage/scenarios'), - }, - this.store, - ); - server.logging = true; - } + @service store; + + async beforeModel() { + if (macroCondition(isDevelopingApp() && !isTesting()) && config.useMirage) { + let { makeServer } = await import("../mirage/servers/default"); + let server = await makeServer( + { + environment: "development", + scenarios: await import("../mirage/scenarios"), + }, + this.store + ); + server.logging = true; } + } } ``` + The `macroCondition` with `isDevelopingApp() && !isTesting()` ensures the entire block is tree-shaken from the production build. The dynamic `await import()` of the server configuration means none of your Mirage code will be bundled in production either. The additional `config.useMirage` flag gives you a way to toggle Mirage on and off during development via your environment configuration. We pass the ember-data `store` to `makeServer` so that Mirage can generate its models from your ember-data models. We also import a scenarios module, which is simply a function that seeds the Mirage database with development data. Finally, enabling `server.logging` will log all intercepted requests and responses to the browser console, which is useful for debugging. ## Caveats + ember-mirage is still under active development. The setup described in this post is specific to Ember apps using Vite. If you're still on a classic build (without Vite), the setup will differ slightly. In particular, `import.meta.glob` is not available in classic builds. In that case you can use `ember-auto-import`'s `allowAppImports` combined with Webpack's `require.context` as an alternative for auto-importing your Mirage modules. ## Wrapping up + Migrating from ember-cli-mirage to ember-mirage requires a bit more manual setup, but the result is a Vite and Embroider compatible MirageJS configuration that stays close to the native MirageJS experience, with ember-mirage providing utilities to make migration easier for situations where there was a reliance on ember-cli-mirage. For more details, check out the [ember-mirage repository](https://github.com/bgantzler/ember-mirage). From d465098a1b4aafe587d091ee8cf877d818120617 Mon Sep 17 00:00:00 2001 From: Nick Schot Date: Fri, 27 Mar 2026 11:14:06 +0100 Subject: [PATCH 03/10] Minor improvements --- src/posts/2026-03-13-ember-mirage.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/posts/2026-03-13-ember-mirage.md b/src/posts/2026-03-13-ember-mirage.md index 645b7ac961..1ca6eb7853 100644 --- a/src/posts/2026-03-13-ember-mirage.md +++ b/src/posts/2026-03-13-ember-mirage.md @@ -10,7 +10,7 @@ autoOg: true # MirageJS & ember-mirage -MirageJS is the core library. At some point in the past this was extracted from ember-cli-mirage to its own library for framework independent use. Ember-mirage is a set of utilities that brings some of the benefits ember-cli-mirage provided. This means that for basic setup, you may not actually need it, but it provides some features that ember-cli-mirage used to provide that might make migrating a little easier. +[MirageJS](https://miragejs.com) is the core library. At some point in the past this was extracted from ember-cli-mirage to its own library for framework independent use. [ember-mirage](https://github.com/bgantzler/ember-mirage) is a set of utilities that brings some of the benefits ember-cli-mirage provided. This means that for basic setup, you may not actually need it, but it provides some features that ember-cli-mirage used to provide that might make migrating a little easier. The first thing we'll do is add MirageJS and ember-mirage as dependencies. @@ -57,7 +57,7 @@ export async function makeServer(config) { ## Loading ember-data models -Another feature ember-cli-mirage provided was automatically inferring Mirage models from ember-data models, meaning MirageJS will infer model names and their relationships from the ember-data models. The configuration roughly matches the previous one. +Another feature ember-cli-mirage provided was automatically inferring Mirage models from ember-data models, meaning MirageJS will infer model names and their relationships from the ember-data models. The configuration roughly matches the previous one. Note that `makeServer` accepts an optional `store` parameter to pass an ember-data store instance. When called from the application route during development, we pass the store directly. In tests, the store is looked up automatically from the test context. ```javascript // mirage/servers/default.js @@ -65,7 +65,7 @@ import { importEmberDataModels } from "ember-mirage/ember-data"; const emberDataModels = import.meta.glob("../../app/models/**/*"); export async function makeServer(config, _store) { - // Don't attempt to import from test-helpers when running in the app + // Look up the store from the test context if not provided let store = _store ?? (await import("@ember/test-helpers")) From 22957c5200393f9bfd0c8eb39e19e88596019071 Mon Sep 17 00:00:00 2001 From: Nick Schot Date: Fri, 27 Mar 2026 11:42:50 +0100 Subject: [PATCH 04/10] Move caveats to prerequisites --- src/posts/2026-03-13-ember-mirage.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/posts/2026-03-13-ember-mirage.md b/src/posts/2026-03-13-ember-mirage.md index 1ca6eb7853..5256c959e2 100644 --- a/src/posts/2026-03-13-ember-mirage.md +++ b/src/posts/2026-03-13-ember-mirage.md @@ -12,6 +12,10 @@ autoOg: true [MirageJS](https://miragejs.com) is the core library. At some point in the past this was extracted from ember-cli-mirage to its own library for framework independent use. [ember-mirage](https://github.com/bgantzler/ember-mirage) is a set of utilities that brings some of the benefits ember-cli-mirage provided. This means that for basic setup, you may not actually need it, but it provides some features that ember-cli-mirage used to provide that might make migrating a little easier. +## Prerequisites +This blog post assumes you already have a working Vite setup as we'll make use of `import.meta.glob`. This is a feature provided by Vite to allow glob imports of files. If you're still on a Webpack/ember-auto-import based setup, you can use Webpack's [`require.context`](https://webpack.js.org/guides/dependency-management/#requirecontext) combined with [ember-auto-import's `allowAppImports`](https://github.com/embroider-build/ember-auto-import?tab=readme-ov-file#app-imports) feature instead. + +## Let's get going The first thing we'll do is add MirageJS and ember-mirage as dependencies. ``` @@ -184,10 +188,6 @@ The `macroCondition` with `isDevelopingApp() && !isTesting()` ensures the entire We pass the ember-data `store` to `makeServer` so that Mirage can generate its models from your ember-data models. We also import a scenarios module, which is simply a function that seeds the Mirage database with development data. Finally, enabling `server.logging` will log all intercepted requests and responses to the browser console, which is useful for debugging. -## Caveats - -ember-mirage is still under active development. The setup described in this post is specific to Ember apps using Vite. If you're still on a classic build (without Vite), the setup will differ slightly. In particular, `import.meta.glob` is not available in classic builds. In that case you can use `ember-auto-import`'s `allowAppImports` combined with Webpack's `require.context` as an alternative for auto-importing your Mirage modules. - ## Wrapping up Migrating from ember-cli-mirage to ember-mirage requires a bit more manual setup, but the result is a Vite and Embroider compatible MirageJS configuration that stays close to the native MirageJS experience, with ember-mirage providing utilities to make migration easier for situations where there was a reliance on ember-cli-mirage. From 55cfabb1e891a452597791186ff05019025fd824 Mon Sep 17 00:00:00 2001 From: Nick Schot Date: Fri, 27 Mar 2026 13:47:14 +0100 Subject: [PATCH 05/10] format MD --- src/posts/2026-03-13-ember-mirage.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/posts/2026-03-13-ember-mirage.md b/src/posts/2026-03-13-ember-mirage.md index 5256c959e2..b016dea8aa 100644 --- a/src/posts/2026-03-13-ember-mirage.md +++ b/src/posts/2026-03-13-ember-mirage.md @@ -13,9 +13,11 @@ autoOg: true [MirageJS](https://miragejs.com) is the core library. At some point in the past this was extracted from ember-cli-mirage to its own library for framework independent use. [ember-mirage](https://github.com/bgantzler/ember-mirage) is a set of utilities that brings some of the benefits ember-cli-mirage provided. This means that for basic setup, you may not actually need it, but it provides some features that ember-cli-mirage used to provide that might make migrating a little easier. ## Prerequisites + This blog post assumes you already have a working Vite setup as we'll make use of `import.meta.glob`. This is a feature provided by Vite to allow glob imports of files. If you're still on a Webpack/ember-auto-import based setup, you can use Webpack's [`require.context`](https://webpack.js.org/guides/dependency-management/#requirecontext) combined with [ember-auto-import's `allowAppImports`](https://github.com/embroider-build/ember-auto-import?tab=readme-ov-file#app-imports) feature instead. ## Let's get going + The first thing we'll do is add MirageJS and ember-mirage as dependencies. ``` From e294784a1e3a37cdee739a749fdaba23cfca582c Mon Sep 17 00:00:00 2001 From: Nick Schot Date: Fri, 3 Apr 2026 13:41:59 +0200 Subject: [PATCH 06/10] Add section about modern ember/emberisms --- src/posts/2026-03-13-ember-mirage.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/posts/2026-03-13-ember-mirage.md b/src/posts/2026-03-13-ember-mirage.md index b016dea8aa..18e793e736 100644 --- a/src/posts/2026-03-13-ember-mirage.md +++ b/src/posts/2026-03-13-ember-mirage.md @@ -194,4 +194,6 @@ We pass the ember-data `store` to `makeServer` so that Mirage can generate its m Migrating from ember-cli-mirage to ember-mirage requires a bit more manual setup, but the result is a Vite and Embroider compatible MirageJS configuration that stays close to the native MirageJS experience, with ember-mirage providing utilities to make migration easier for situations where there was a reliance on ember-cli-mirage. +It's worth stepping back and noticing what's happening here: we're using standard JavaScript features like dynamic `await import()`, top-level `await`, and Vite's `import.meta.glob` instead of legacy Ember-specific magic. The old ember-cli-mirage relied heavily on Ember conventions and build pipeline hooks to auto-discover files. The new setup replaces those "Emberisms" with vanilla JS and standard build tool features. This is only possible thanks to the significant progress the Ember ecosystem has made over the last couple of years with Embroider and the move to Vite. Modern Ember applications are much more aligned with the broader JavaScript ecosystem, making it easier to leverage standard tooling and reducing the framework-specific knowledge needed to be productive. + For more details, check out the [ember-mirage repository](https://github.com/bgantzler/ember-mirage). From f4bf4802c3ad0da407f8f87c68e064198cec2ded Mon Sep 17 00:00:00 2001 From: Nick Schot Date: Fri, 22 May 2026 16:35:57 +0200 Subject: [PATCH 07/10] Clarify prerequisites/migration path & webpack --- src/posts/2026-03-13-ember-mirage.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/posts/2026-03-13-ember-mirage.md b/src/posts/2026-03-13-ember-mirage.md index 18e793e736..29b7fcf742 100644 --- a/src/posts/2026-03-13-ember-mirage.md +++ b/src/posts/2026-03-13-ember-mirage.md @@ -14,7 +14,9 @@ autoOg: true ## Prerequisites -This blog post assumes you already have a working Vite setup as we'll make use of `import.meta.glob`. This is a feature provided by Vite to allow glob imports of files. If you're still on a Webpack/ember-auto-import based setup, you can use Webpack's [`require.context`](https://webpack.js.org/guides/dependency-management/#requirecontext) combined with [ember-auto-import's `allowAppImports`](https://github.com/embroider-build/ember-auto-import?tab=readme-ov-file#app-imports) feature instead. +The blog post is written from a fresh-app perspective to make it very clear what each part of the config does. Most of your actual Mirage related files can stay where they are and like they are. We're mostly going to rewrite the configuration. We do expect you already have a working Vite setup as we'll make use of `import.meta.glob`. This is a feature provided by Vite to allow glob imports of files. + +If you're still on a Webpack/ember-auto-import based setup, there is an alternative migration path you could take. This, however, does require you to move all mirage files into the `app` folder, rather than the location in `/mirage` where it used to be with ember-cli-mirage. Webpack also does not support `import.meta.glob`, you can use Webpack's [`require.context`](https://webpack.js.org/guides/dependency-management/#requirecontext) combined with [ember-auto-import's `allowAppImports`](https://github.com/embroider-build/ember-auto-import?tab=readme-ov-file#app-imports) feature instead. If your goal is to migrate to a Vite app, this could be a way to get your updated configuration done and in place before the Vite migration, but know that you do need to at least replace all `require.context` statements with `import.meta.glob` instead. ## Let's get going From 5bf30de2aaa042c9cf1b096ee89d0b1a35bb58a8 Mon Sep 17 00:00:00 2001 From: Nick Schot Date: Fri, 5 Jun 2026 14:01:29 +0200 Subject: [PATCH 08/10] Clarify that this is for migration in intro & update pre-requisites to clarify that this should be part of Vite migration. --- src/posts/2026-03-13-ember-mirage.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/posts/2026-03-13-ember-mirage.md b/src/posts/2026-03-13-ember-mirage.md index 29b7fcf742..3d430b1014 100644 --- a/src/posts/2026-03-13-ember-mirage.md +++ b/src/posts/2026-03-13-ember-mirage.md @@ -4,7 +4,7 @@ authorHandle: nickschot tags: [ember, mirage, mainmatter] bio: "Nick Schot" description: "Nick Schot explains how to migrate from ember-cli-mirage to a miragejs + ember-mirage setup supported by Vite" -tagline: "If you've been developing Ember applications with API mocking, you're likely familiar with ember-cli-mirage. ember-cli-mirage has been a corner-stone for writing representative tests that rely on a backend API. It allows you to create focused test scenarios with exactly the data you need for that test. Additionally it can be used to develop frontend features before the API even exists. But there's a problem: ember-cli-mirage doesn't work with Vite! As the Ember ecosystem continues to move toward modern build tooling with Embroider and Vite, we need a solution that brings MirageJS along for the journey. This blog post outlines a path forward to setup MirageJS directly in modern Ember applications." +tagline: "If you've been developing Ember applications with API mocking, you're likely familiar with ember-cli-mirage. ember-cli-mirage has been a corner-stone for writing representative tests that rely on a backend API. It allows you to create focused test scenarios with exactly the data you need for that test. Additionally it can be used to develop frontend features before the API even exists. But there's a problem: ember-cli-mirage doesn't work with Vite! As the Ember ecosystem continues to move toward modern build tooling with Embroider and Vite, we need a solution that brings MirageJS along for the journey. This blog post outlines a path forward to keep your MirageJS setup working in modern Ember applications." autoOg: true --- @@ -13,8 +13,9 @@ autoOg: true [MirageJS](https://miragejs.com) is the core library. At some point in the past this was extracted from ember-cli-mirage to its own library for framework independent use. [ember-mirage](https://github.com/bgantzler/ember-mirage) is a set of utilities that brings some of the benefits ember-cli-mirage provided. This means that for basic setup, you may not actually need it, but it provides some features that ember-cli-mirage used to provide that might make migrating a little easier. ## Prerequisites +This blog post is intended to be a step during a migration to Vite since we'll make use of `import.meta.glob`. This is a feature provided by Vite to allow glob imports of files. The steps can be taken at any point after, for example, running the [ember-vite-codemod](https://github.com/mainmatter/ember-vite-codemod), or after migrating to Vite manually. -The blog post is written from a fresh-app perspective to make it very clear what each part of the config does. Most of your actual Mirage related files can stay where they are and like they are. We're mostly going to rewrite the configuration. We do expect you already have a working Vite setup as we'll make use of `import.meta.glob`. This is a feature provided by Vite to allow glob imports of files. +The blog post is written from a fresh-app perspective to make it clear what each part of the config does. Most of your actual Mirage related files can stay where they are and like they are. We're mostly going to rewrite the configuration. If you're still on a Webpack/ember-auto-import based setup, there is an alternative migration path you could take. This, however, does require you to move all mirage files into the `app` folder, rather than the location in `/mirage` where it used to be with ember-cli-mirage. Webpack also does not support `import.meta.glob`, you can use Webpack's [`require.context`](https://webpack.js.org/guides/dependency-management/#requirecontext) combined with [ember-auto-import's `allowAppImports`](https://github.com/embroider-build/ember-auto-import?tab=readme-ov-file#app-imports) feature instead. If your goal is to migrate to a Vite app, this could be a way to get your updated configuration done and in place before the Vite migration, but know that you do need to at least replace all `require.context` statements with `import.meta.glob` instead. From 21f6915595a0a0ffb3e9eb75d3f7e7eb5c9b0a7c Mon Sep 17 00:00:00 2001 From: Nick Schot Date: Fri, 5 Jun 2026 14:02:01 +0200 Subject: [PATCH 09/10] Clarify that this is for migration in intro & update pre-requisites to clarify that this should be part of Vite migration. --- src/posts/2026-03-13-ember-mirage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/posts/2026-03-13-ember-mirage.md b/src/posts/2026-03-13-ember-mirage.md index 3d430b1014..9efa1c43c1 100644 --- a/src/posts/2026-03-13-ember-mirage.md +++ b/src/posts/2026-03-13-ember-mirage.md @@ -15,7 +15,7 @@ autoOg: true ## Prerequisites This blog post is intended to be a step during a migration to Vite since we'll make use of `import.meta.glob`. This is a feature provided by Vite to allow glob imports of files. The steps can be taken at any point after, for example, running the [ember-vite-codemod](https://github.com/mainmatter/ember-vite-codemod), or after migrating to Vite manually. -The blog post is written from a fresh-app perspective to make it clear what each part of the config does. Most of your actual Mirage related files can stay where they are and like they are. We're mostly going to rewrite the configuration. +The steps are outlined from a fresh-app perspective to make it clear what each part of the config does. Most of your actual Mirage related files can stay where they are and like they are. We're mostly going to rewrite the configuration. If you're still on a Webpack/ember-auto-import based setup, there is an alternative migration path you could take. This, however, does require you to move all mirage files into the `app` folder, rather than the location in `/mirage` where it used to be with ember-cli-mirage. Webpack also does not support `import.meta.glob`, you can use Webpack's [`require.context`](https://webpack.js.org/guides/dependency-management/#requirecontext) combined with [ember-auto-import's `allowAppImports`](https://github.com/embroider-build/ember-auto-import?tab=readme-ov-file#app-imports) feature instead. If your goal is to migrate to a Vite app, this could be a way to get your updated configuration done and in place before the Vite migration, but know that you do need to at least replace all `require.context` statements with `import.meta.glob` instead. From ae313634bd66e0d26c094394ade9bdb60243bd28 Mon Sep 17 00:00:00 2001 From: Nick Schot Date: Fri, 26 Jun 2026 13:18:01 +0200 Subject: [PATCH 10/10] Replace paragraph about Webpack/Classic with reference to ember-import-meta-glob polyfill --- src/posts/2026-03-13-ember-mirage.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/posts/2026-03-13-ember-mirage.md b/src/posts/2026-03-13-ember-mirage.md index 9efa1c43c1..c64555cd32 100644 --- a/src/posts/2026-03-13-ember-mirage.md +++ b/src/posts/2026-03-13-ember-mirage.md @@ -13,11 +13,12 @@ autoOg: true [MirageJS](https://miragejs.com) is the core library. At some point in the past this was extracted from ember-cli-mirage to its own library for framework independent use. [ember-mirage](https://github.com/bgantzler/ember-mirage) is a set of utilities that brings some of the benefits ember-cli-mirage provided. This means that for basic setup, you may not actually need it, but it provides some features that ember-cli-mirage used to provide that might make migrating a little easier. ## Prerequisites + This blog post is intended to be a step during a migration to Vite since we'll make use of `import.meta.glob`. This is a feature provided by Vite to allow glob imports of files. The steps can be taken at any point after, for example, running the [ember-vite-codemod](https://github.com/mainmatter/ember-vite-codemod), or after migrating to Vite manually. The steps are outlined from a fresh-app perspective to make it clear what each part of the config does. Most of your actual Mirage related files can stay where they are and like they are. We're mostly going to rewrite the configuration. -If you're still on a Webpack/ember-auto-import based setup, there is an alternative migration path you could take. This, however, does require you to move all mirage files into the `app` folder, rather than the location in `/mirage` where it used to be with ember-cli-mirage. Webpack also does not support `import.meta.glob`, you can use Webpack's [`require.context`](https://webpack.js.org/guides/dependency-management/#requirecontext) combined with [ember-auto-import's `allowAppImports`](https://github.com/embroider-build/ember-auto-import?tab=readme-ov-file#app-imports) feature instead. If your goal is to migrate to a Vite app, this could be a way to get your updated configuration done and in place before the Vite migration, but know that you do need to at least replace all `require.context` statements with `import.meta.glob` instead. +If you're still on a classic build, you can make use of the [ember-import-meta-glob](https://github.com/mainmatter/ember-import-meta-glob) polyfill. This does require that all mirage files are within the `app` folder, rather than the root of the project where it used to be with ember-cli-mirage. Vite can work with either location, so once you're ready to upgrade to Vite you won't need to move things around. ## Let's get going