Gulp browser-sync - redirect API request via proxy
I came across an issue, which I could not find solution for. I need both options:
browser-sync
running in SPA mode- there is middleware proxy at
/api
route
It appears that SPA mode intercepts the /api
and renders index.html
instead of proxying to backend.
The solution is in browser-sync
sources: single mode is implemented using that middleware
route, which has higher priority than the ones added manually:
if (bs.options.get("single")) {
defaultMiddlewares.unshift({
id: "Browsersync SPA support",
route: "",
handle: require("connect-history-api-fallback")()
});
}
Following configuration works as needed - SPA
route is at the end of middleware list:
const proxy = require('proxy-middleware');
...
server.init({
...
middleware: [ {
route: "/api",
handle: proxy(url.parse("http://api.host:4444/api"))
}, {
id: "SPA support",
route: "",
handle: require("connect-history-api-fallback")()
} ],
single: false,
...
})
I ran into the same issue with the gulp + browser-sync + proxy-middleware setup, while migrating from grunt to gulp.
Error: connect ECONNREFUSED
at errnoException (net.js:904:11)
at Object.afterConnect [as oncomplete] (net.js:895:19)
In my case something within the corporate network which didn't allow proxy-middleware to work. As soon I was on the public network, the issue was gone.
With grunt-connect + grunt-connect-proxy I could proxy files within the corporate network without any problems.
proxy-middleware implements its own proxy functionality, while grunt-connect-proxy uses http-proxy to do the actual proxy work.
I ended up writing a small middleware wrapper around http-proxy to be used in browser-sync and connect, which solved the proxy issues in the corporate network.
https://www.npmjs.com/package/http-proxy-middleware
var browserSync = require('browser-sync');
var proxyMiddleware = require('http-proxy-middleware');
var proxy = proxyMiddleware('/ajax', {target: 'http://cdnjs.cloudflare.com'});
browserSync({
server: {
baseDir: "./",
port: 3000,
middleware: [proxy]
}
});
Checkout the official documentation about using BrowserSync with Gulp. I was able to get BrowserSync up and running with a proxy on /api
with no issue.
Check to make sure nothing else is using port 8000
. You can change what port BrowserSync uses via the port
option when initializing BrowserSync.
Here is the gulpfile.js
I ended up with:
npm install gulp url proxy-middleware browser-sync --save-dev
// Include gulp
var gulp = require('gulp');
var url = require('url');
var proxy = require('proxy-middleware');
var browserSync = require('browser-sync');
var paths = {
css: ['./**/*.css', '!./node_modules/**/*']
};
// browser-sync task for starting the server.
gulp.task('browser-sync', function() {
var proxyOptions = url.parse('http://localhost:3000/secret-api');
proxyOptions.route = '/api';
// requests to `/api/x/y/z` are proxied to `http://localhost:3000/secret-api/x/y/z`
browserSync({
open: true,
port: 3000,
server: {
baseDir: "./",
middleware: [proxy(proxyOptions)]
}
});
});
// Stream the style changes to the page
gulp.task('reload-css', function() {
gulp.src(paths.css)
.pipe(browserSync.reload({stream: true}));
});
// Watch Files For Changes
gulp.task('watch', function() {
gulp.watch(paths.css, ['reload-css']);
});
// Default Task
gulp.task('default', ['browser-sync', 'watch']);
If you do not want to make a separate gulp task to reload/stream the changes, you can use the files
option:
browserSync({
open: true,
port: 3000,
server: {
baseDir: "./",
middleware: [proxy(proxyOptions)]
},
files: paths.css
});