An application I'm working with has a large amount of static files (path starting with '/files/'
) deployed on a mounted volume in Docker. They are subsequently served via nginx. for local development, I thought of two options:
- Add files to the local dev server (e.g. copy assets)
- Build a proxy to pipe the request to the nginx-served site
The first option is somewhat restrictive:
- I'd have to make sure the files are kept in sync with the latest version.
- I'd have to integrate the syncing process with the build scripts.
- Just mounting the volume is not a solution as the data would need to be shareable on the remote machine.
Therefore, only the second option seems to be viable, with the following conditions:
- The web server needs to be running at all times
- It needs to be accessible locally without authentication
Configure the Dev Server
Webpack has a development server one can use locally. Normally, it only serves resources from contentBase
:
config.devServer = {
contentBase: path.join(__dirname, 'dist')
// ...
}
Fortunately, it also offers pre- and post-processing via the before
and after
. In our case, implementing before
would allow us to replace the default process for the request to '/files/'
with a custom implementation:
var request = require('request')
const before = function before(app) {
app.get('/files/*', (req, res) => {
request('http://<nginx.server.address>:<port>' + req.path).pipe(res)
})
}
if (config.devServer.before) {
const proxy = config.devServer.before
config.devServer.before = function replace(app) {
before(app)
proxy(app)
}
} else {
config.devServer.before = before
}
Our function before(app)
is intercepting requests to '/files/'
:
const before = function before(app) {
app.get('/files/*', (req, res) => {
We perform a request via prepending the nginx server's address and port:
request('http://<nginx.server.address>:<port>' + req.path)
Then we just pipe the response from the server to our local dev server:
.pipe(res)
});
};
Once the behaviour is fixed, we chain the behaviour:
if (config.devServer.before) {
const proxy = config.devServer.before
config.devServer.before = function replace(app) {
before(app)
proxy(app)
}
} else {
config.devServer.before = before
}
At this point, all requests to '/files/*'
will be tunnelled to the remote server transparently.
Few Notes
Note: You might want to perform different transformations (instead of just prepending the server details) or add some environment variables (e.g. proxy).
Note: If you can get away with copying assets locally (or even including them in your project), you can do so. I personally find the idea of having static project assets in a separate location as a necessary evil in this particular case.
HTH,
Member discussion: