Rewrite URL in angular server before accessing local static file

Viewed 317

I'm developing an angular (v.10) application which serves a bunch of static files (like '/assets/').

In production, those static files will be served by the backend, but in development we need the ng serve to fill this gap.

Until now I had no special requirement for the filenames, so all I need to do declare a new entry in "assets" configuration (in angular.json).

But now my application need to access some files like "content.json?__locale=pt". It would be no problem on ext4 filesystems. But I'm the only one in my team working on linux; the others are working on Windows machines, with NTFS, which forbids the '?' character.

I was thinking of storing files as "content.json___locale=pt", but I need the ng serve to rewrite incoming url "content.json?__locale=pt" to "content.json___locale=pt".

Is there any way to do it?

1 Answers

My final solution is a bit hackish, but I stuck with it because it only affects local development, and not production code.

Since I don't want to ng eject, I opted to using @angular-builders/custom-webpack:

$ yarn add @angular-builders/custom-webpack --dev

Then configured serve target to use this custom builder (angular.json):

{
  ...
  "projects": {
    "myproject": {
      "projectType": "application",
      ...
      "architect": {
        ...
        "serve": {
          "builder": "@angular-builders/custom-webpack:dev-server",
          ...
        },
        ...
      }
    }
  },
  ...
}

Since the dev-server builder doesn't have its own customWebpackConfiguration (I reported this as a feature request), I had also configured the build target to use this custom builder:

{
  ...
  "projects": {
    "myproject": {
      "projectType": "application",
      ...
      "architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "customWebpackConfig": {
              "path": "./extra-webpack.config.ts"
            },
            ...
          },
          ...
        },
        ...
      }
    }
  },
  ...
}

And finally, in ./extra-webpack.config.ts I did a small express magic:

import { basename } from 'path';
import * as webpack from 'webpack';

export default {
  devServer: { before },
} as webpack.Configuration;

function before(app, server, compiler) {
  app.use('/cms', squash_question_mark);
}

function squash_question_mark(req, res, next) {
  const url = req.url.replace(/\?/g, '_');
  if (req.url !== url) {
    console.warn(`${basename(__filename)}: ${req.url} => ${url}`);
    req.url = url;
  }
  next();
}

Related