If you are engaged in frontend development, then you probably know the following stage scene: the project deadlines are rapidly shrinking, your management or customer, and both of them want to see the application running right now, even with fake data. At the same time, perhaps there is a back, but it is exactly api that the layer of interaction with front is completely absent from the word.
So, recently I encountered such a situation, and I am developing a frontend under the angular (people sitting around on chairs sluggishly slapped, someone nodded knowingly).
Now I will try seriously. On the one hand, the situation is not uncommon, and many solutions can be chosen.
')
Several solutions came to mind:
- Retrieve data at component level
- Zakhardkodit data at the level of the services resolver, pin them to the necessary routes
- Zakhardkodit data at the level of data providers services
- To file api, and, according to the stipulated contracts, to return zakarkozhenny data
But any of these options seemed an inelegant crutch, for each of which there were weighty flaws.
- The first option was dropped right away - an absolutely inconvenient unused solution, as the project progresses everything will have to be rewritten.
- This decision could have taken place, but again the structure of the project and the logic of the components will be rewritten.
- A possible option, you can even return the stub data asynchronously, simulating a call to the server, however, as in the previous solutions to the problem, our interceptors (if they are, but they are) would remain out of work, and it turns out that imitation of work with back becomes incomplete.
- The last option seemed to be quite acceptable, devoid of the problems that the previous options have, but I didn’t want to write hardcode to the backend simply because of hygienic considerations.
As a result, another option was chosen: to raise a separate web server that would return data according to routes and contracts, and set up a separate configuration of assembly and execution angular. Fortunately, both turned out to be easy to do.
Express was chosen to implement the mock server.
Let's start with it.
We select the place where we want to write code for the mok server, for example, in the mock-server directory next to the ng project.
Next, you need to initialize the project and add a package with express.
npm init
npm install --save express
Next, add the code that will return the data. We create the index.js file, we take the code from the first tutorial.
const express = require("express"); const app = express(); app.get("/url", (req, res, next) => { res.json(["Tony", "Lisa", "Michael", "Ginger", "Food"]); }); app.listen(3000, () => { console.log("Server running on port 3000"); });
Let's start the server
node index.js
Check with postman:

Everything is super, the server is working. Now let's configure one of the routes, as if we were requesting data from a real api. Suppose we need a list of all books, fill books with books.json
[ { "rn": 0, "id": "0", "name": "Jungle", "type": 0, "wells": 10042, "default": false, "hidden": false, "author": "Admin" }, { "rn": 1, "id": "1", "name": "Main", "type": 1, "wells": 156, "default": true, "hidden": false, "author": "User" } ]
And update the application file:
const express = require("express"); const app = express(); app.get("/api/book/", (req, res, next) => { const books = require('./books'); res.json(books); }); app.listen(3000, () => { console.log("Server running on port 3000"); });
And check:

Fine.
Now let's get down to the angular application.
Add a configuration to the environments / environment * .ts file that stores the address before the backup.
environment.ts:
export const environment = { production: false, backend: 'http://localhost:5000/' }
environment.prod.ts
export const environment = { production: true, backend: 'http://localhost:5000/' }
In the normal mode, both in the prode and in the development mode, we will search for the .net core api on port 5000, as described above. Next, we describe the configuration for a temporary backup.
environment.mock.ts
export const environment = { production: false, backend: 'http://localhost:3000/' }
Here, apparently, we are looking for api on port 3000, where we will run express.
Now we need an interceptor that will direct calls to the backend to the correct server, depending on the configuration.
@Injectable() export class RequestInterceptor implements HttpInterceptor { baseUrl: string; constructor() { this.baseUrl = environment.backend; } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(this.modifyRequest(req)); } private modifyRequest = (req: HttpRequest<any>): HttpRequest<any> => { if (req.url.startsWith('api/')) { const url = this.baseUrl; req = req.clone({ url: url + req.url }); } return req; } }
It remains to configure the new configuration of the assembly and launch the application to work with the mock server.
To do this, we need to tweak a bit angular.json.
In the section of your project, architect / build / configurations, we will add a new mock build configuration, and describe the replacement of environment files for this configuration. Also for the serve mode, create a mock configuration and specify the desired build option
{ "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "projects": { "your-project": { /*****/ "architect": { "build": { /*****/ "configurations": { "production": { /*****/ }, "mock": { "fileReplacements": [ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.mock.ts" } ] } } }, "serve": { "builder": "@angular-devkit/build-angular:dev-server", "options": { "browserTarget": "your-project:build" }, "configurations": { "production": { "browserTarget": "your-project:build:production" }, "mock": { "browserTarget": "your-project:build:mock" } } } }, /*****/ } } }
That's all, now it remains to run the project in the desired configuration
ng serve --configuration=mock
and check where the calls to the backup fly:

All perfectly.
In fact, this design will still help us a lot when we are going to fasten integration and e2e tests to the project. I will try to write about it in the near future.