On mocking API endpoints for local development with Webpack

As you might’ve read in my blog post on integrating Vue in an existing product, at Uptrends we’re building a library of Vue components separate from the actual product. This allows us to develop components faster than when we’re developing them in the product source code. One downside of this is that the product API is not available when developing components separately. Luckily, we’ve found a way to mock our API without polluting our production code.

Product setup

A little background on the setup we’re currently using: Because we’re working with Vue, we’re building our component development suite via Webpack. The component library is built as a library, and that library is consumed in the product, where Vue components are mounted to specific DOM elements. We have precise control over what components are exported in the library.

Vue components use data from VueX store modules. These store modules roughly mirror API entities, so each store module contains data from one API endpoint. There’s a fetch helper function, imported from a separate file, that fetches the data from the API using Axios. A VueX store module calls the helper function with an endpoint url.

The magic: the NormalModuleReplacementPlugin

The way we’ve set our mocking up is this: there’s two fetch helper functions instead of one. The first is actually calling the product API via Axios - this is the one we’re using for production. The second one is returning mock responses based on the received endpoint url instead!

So far, so good. It’s just that we don’t want to pollute our production code with mock data. And that’s where Webpack’s NormalModuleReplacementPlugin comes in. Here’s how we’ve done it:

  1. All our code is written for production. That means the VueX store modules use the production-ready fetch helper function, and don’t know about the mocked one.

  2. The mocked fetch function lives in a subdirectory relative to the production version.

  3. We’ve set up our vue.config.js to use the NormalModuleReplacementPlugin as follows:

const normalModuleReplacementPlugin = require("webpack/lib/NormalModuleReplacementPlugin");

module.exports = {
    chainWebpack: config => {
        config.plugin("NormalModuleReplacementPlugin")
        .use(new normalModuleReplacementPlugin(/\/api\/fetch/,"@/api/mock/fetch"))
    }
}

Note that this example code is using the webpack-chain notation. Check out the plugin documentation for more examples.

What this code does is this: it tells Webpack to use the NormalModuleReplacementPlugin. What this plugin does is check all import statements in files. Next, we tell the plugin that when it encounters the exact string api/fetch in an import statement, it should instead import our mock fetch function. And that’s all!

Because we’re exporting components as a library, we can easily use the “default” Vue build process to suit our development needs. However, for this to work Vue is not even required - Webpack is, though, and so is using ES6 imports. Also, if your default build process is used for development and production builds, there’s probably a Webpack env property that tells you what type of build you’re running - and you could use the NormalModuleReplacementPlugin to mock your API endpoints only in the development build.

In conclusion

At Uptrends, we’re using a standard Webpack plugin to help us mock our API endpoints without polluting our production code. This allows us to develop Vue components faster and more maintainable. If you want to know more about the frontend development environment at Uptrends, read about how we’ve integrated Vue in our existing product.