Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple instances on one server? #172

Closed
nicholas-c opened this issue Jun 20, 2014 · 20 comments
Closed

Multiple instances on one server? #172

nicholas-c opened this issue Jun 20, 2014 · 20 comments

Comments

@nicholas-c
Copy link

So, We have installed this on our development server got it working however if a second person runs a server it overwrites because; well, it's the same server I might be missing it however multiple instances would be sweet.

@shakyShane
Copy link
Contributor

Can you explain what you mean by this in more detail?

Are you using the server or proxy option?

@jimmykane
Copy link

This:

campaignGulp.setCampaignBrowserSyncTasks = function (campaign, port) {
        var taskName = campaign + ':browserSync';
        gulp.task(taskName, function () {
            browserSync({
                host: '192.168.33.22', //@todo is it needed?
                proxy: campaign + '.dev',
                port: port
            });
        });
        return taskName;
    };

if used more than 1 time opens multiple windows when started.

if called 4 times: It posts 4 times and the browser opens 3 times, really wierd

@shakyShane
Copy link
Contributor

Every time you call browserSync(), a new instance will be created - that's why the browser is opening multiple times.

You need to structure your tasks so that the one that wraps BrowserSync is only ever called once.

@jimmykane
Copy link

Is there the possibility though for multiple proxies and servers. I want to proxify several folders that are small apps in a bigger project.

@basham
Copy link

basham commented Sep 15, 2014

I'm likewise encountering this problem. At work, we're highly invested in Java, yet we're trying to transition much of our front-end to take advantage of Node and npm. I want to keep the two systems as independent from one another as possible. Ideally, I want two BrowserSync instances. The first is a proxy to the Java app, and the second is my front-end build system. I want the second to tell the proxy to reload when watching file changes.

I've resolved this by quickly creating browser-sync-instance. I don't intend to publish this npm module, assuming that this functionality will eventually be natively supported by BrowserSync.

@jimmykane
Copy link

@basham Thanks for the link. Might give it a try.

@shakyShane
Copy link
Contributor

@basham - thanks for your module, I've used it as inspiration for the upcoming feature in BrowserSync.

It's taken a while because I wanted to do this in a non-breaking-change way (which is trickier than it sounds!) & also I think the vast majority of users will still only use a single instance.

So the api will be as it was before for a singleton:

var browserSync = require("browserSync");

browserSync.emitter.on("file:changed", fileChangeFn); // Emitter access still works
browserSync.use(require("some-plugin")); // plugins still work
browserSync({server: true}); // run the instance

But, for multiple instances, you use the .create method.

var browserSync = require("browserSync");

var bs1 = browserSync.create("first server"); // Create a named instance
var bs2 = browserSync.create("proxy"); // Create a second named instance

bs1.use(require("some-plugin")); // Add a plugin to first instance only

bs1.init({
    port: 3000,
    server: "./app"
});

bs2.init({
    port: 3001,
    proxy: "mylocal.dev"
});

Finally, you can also retrieve any previously created instances from the main module. (useful if you cannot save the result of .create() in a local variable).

var browserSync = require("browserSync");

browserSync.create("first server"); // Create a named instance

// Somewhere else in your code
browserSync.get("first server").init({
    port: 3000,
    server: "./app"
});

Hopefully this will satisfy every use-case whilst also allowing the singleton pattern.

Check out the progress here https://github.com/shakyShane/browser-sync/blob/feature/multi-instance/index.js.

@lkraav
Copy link

lkraav commented Dec 29, 2014

Getting multiple sites handled within a single BS instance (daemonized, systemd unit) is very interesting to me, so I did some issue list research. Looks like #172 (issue at hand), #304, #284, #234 all seem to be related in one way or another.

This one, #172, seems to be the most comprehensive ticket towards taking the next step, so I'll post my findings and ideas here for now. But perhaps what I'm talking about needs a separate issue, let me know. Here goes.

I got a single instance BS 1.8.2 running across multiple domains / sites using Apache as a proxy in front of it, which takes care of all rewrites to localhost:3000. It is clear now though that BS does not differentiate between sites, contexts, rooms, namespaces or whatever we want to call it. If the browser connects to the same BS instance from meh.site.com and blah.site.com, two completely different sites, at the moment BS will share CSS and ghost these two completely different into happy oblivion.

Two things that came to mind immediately:

  1. http://www.browsersync.io/docs/options/#option-socket can separate single-instance comm channels be solved with socket.io namespacing, creating separate rooms? mozilla/togetherjs is a another browser sync technology and they have special configuration parameter for this, which I'm successfully using to host a single hub that multiple separate websites can connect to https://togetherjs.com/docs/#configuring-togetherjs TogetherJSConfig_findRoom
  2. ability to push BS client-side pre-configuration, which would tell the browser which room to connect to. I could output some pre-determined room or namespace names, on any of the pages I want to separate from each other, like this:
<script>
var _bs = _bs || [];
_bs.push('namespace', 'meh.site.com-feature-x');

// or 

_bs.push('namespace', 'meh.site.com-hotfix-y');
</script>

When BS library loads itself, it should initialize itself with this connection info pre-configuration.

If the socket.io level namespacing perhaps already works for separating communications within a single instance, this would be world domination uber power. Wdyt?

EDIT I'm not sure at all that I'm not missing any other big architectural restrictions in BS current gut code, as related to the topic at hand. Enlightenment welcome.

@basham
Copy link

basham commented Jan 21, 2015

@shakyShane Glad the browser-sync-instance project was able to inspire this feature work. Like the additions to the API.

@SimenB
Copy link
Contributor

SimenB commented Feb 13, 2015

@shakyShane I'm not able to start this using Gulp. Just pasting in your example above fails, as (I'm guessing) both UIs tries to bind to the same port.

[10:50:20] Using gulpfile ~/repos/frontend-repo/code/gulpfile.js
[10:50:20] Starting 'browser-sync'...
[10:50:20] Finished 'browser-sync' after 21 ms
[BS] [info] Proxying: http://mylocal.dev
[BS] Access URLs:
 ------------------------------------
       Local: http://localhost:3003
    External: http://10.2.22.101:3003
 ------------------------------------
          UI: http://localhost:3001
 UI External: http://10.2.22.101:3001
 ------------------------------------
[BS] Access URLs:
 ------------------------------------
       Local: http://localhost:3000
    External: http://10.2.22.101:3000
 ------------------------------------
          UI: http://localhost:3001
 UI External: http://10.2.22.101:3001
 ------------------------------------
[BS] Serving files from: ./app

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: listen EADDRINUSE
    at errnoException (net.js:905:11)
    at Server._listen2 (net.js:1043:14)
    at listen (net.js:1065:10)
    at Server.listen (net.js:1139:5)
    at Object.module.exports.startServer [as fn] (/home/testyo/repos/frontend-repo/code/node_modules/browser-sync/node_modules/browser-sync-ui/lib/async.js:99:39)
    at /home/testyo/repos/frontend-repo/code/node_modules/browser-sync/node_modules/browser-sync-ui/lib/UI.js:126:14
    at iterate (/home/testyo/repos/frontend-repo/code/node_modules/browser-sync/node_modules/async-each-series/index.js:8:5)
    at /home/testyo/repos/frontend-repo/code/node_modules/browser-sync/node_modules/async-each-series/index.js:16:16
    at /home/testyo/repos/frontend-repo/code/node_modules/browser-sync/node_modules/browser-sync-ui/lib/UI.js:134:13
    at Object.module.exports.setUrlOptions [as fn] (/home/testyo/repos/frontend-repo/code/node_modules/browser-sync/node_modules/browser-sync-ui/lib/async.js:62:9)

Process finished with exit code 8

I can't find this in the docs on your website, that's why I ask here instead of making an issue 😄

Using 2.0.1 release

@shakyShane
Copy link
Contributor

@SimenB - yeah sorry, this hasn't been added to the docs yet, because of this reason (the race condition with the ports).

You could do this though, and it'll work fine

var browserSync = require("browser-sync");

var bs1 = browserSync.create("proxy1");
var bs2 = browserSync.create("proxy2");

bs1.init({
    proxy: "http://mylocal.dev"
}, function () {
    bs2.init({
        proxy: "http://mylocal2.dev"
    });
});

... In this case, the first proxy has already resolved 2 ports, 1 for BrowserSync core + 1 for the UI.

The alternative is to provide all ports ahead of time, if you know them.

var browserSync = require("browser-sync");

var bs1 = browserSync.create("proxy1");
var bs2 = browserSync.create("proxy2");

bs1.init({
    proxy: "http://mylocal.dev",
    port: 3010,
    ui: {
        port: 3011
    }
});
bs2.init({
    proxy: "http://mylocal.dev",
    port: 3012,
    ui: {
        port: 3013
    }
});

@SimenB
Copy link
Contributor

SimenB commented Feb 13, 2015

There we go, that works beautifully. Thanks for the quick response!

Additional question, can I serve a subdirectory at root?
E.g. proxying http://example.com/subdomain at http://localhost:3010 instead of http://localhost:3010/subdomain?

Or can I serve under a subdomain?

@shakyShane
Copy link
Contributor

@SimenB - that's not currently available I'm afraid - it would involve us having to re-write every single request before it hits your server - doable with middleware maybe? https://github.com/BrowserSync/browser-sync/blob/master/examples/proxy.middleware.js (need latest version for that)

@shakyShane
Copy link
Contributor

Closing this thread as this is now possible using the technique described #172 (comment)

@lkraav
Copy link

lkraav commented Feb 24, 2015

@shakyShane v2 didn't include any incremental provisions for client-side reconfiguration, for the context-separation idea comment or otherwise, right? Could you give me an indication on how you feel about the concept? I could determine the next step forward then.

EDIT or this is a browser-sync-client topic?

@tkrotoff
Copy link

Here my happy experience with this feature.

I can have in parallel 1 BrowserSync instance for my 'regular' coding and 1 BrowserSync instance on another port for Protractor so they don't interfere with each other. gulpfile.js snippet:

var browserSync = require('browser-sync');

function browserSyncInit(port, baseDir) {
  var browser = browserSync.create();
  browser.init({
    port: port,
    server: {
      baseDir: baseDir
    },
    ...
  });
  return browser;
}

gulp.task('serve', ['styles', 'scripts'], function() {
  var browser = browserSyncInit(9000, ['.tmp/app', 'app']);
  gulp.watch(['app/*.html'], browser.reload);
  gulp.watch(['app/**/*.scss'], ['styles', browser.reload]);
  gulp.watch(['app/**/*.ts', 'lib/**/*.ts'], ['scripts', browser.reload]);
});

function runProtractor() {
  var browser = browserSyncInit(9001, ['.tmp/app', 'app']);

  gulp.src('.tmp/test/e2e/all.js')
    .pipe($.protractor.protractor({
      configFile: 'protractor.conf.js'
    }))
    .on('error', function(e) {
      // Make sure failed tests cause gulp to exit non-zero
      throw e;
    })
    .on('end', function() {
      browser.exit();
    });
}

gulp.task('test:e2e', ['build:test:e2e', 'webdriver-update'], runProtractor);

@singhmohancs
Copy link

I am facing the same issue. Everything is working perfect on window and mac. But when i run the application on ubuntu 12.4+. gives the following error:

[09:03:54] all files 272.87 kB
[09:03:54] Finished 'scripts' after 4.38 s
[09:03:54] Starting 'inject'...
[09:03:54] gulp-inject 1 files into 404.html.
[09:03:54] gulp-inject 1 files into index.html.
[09:03:54] gulp-inject 77 files into 404.html.
[09:03:54] gulp-inject 77 files into index.html.
[09:03:54] Finished 'inject' after 522 ms
[09:03:54] Starting 'watch'...
[09:03:55] Finished 'watch' after 214 ms
[09:03:55] Starting 'serve'...
[09:03:55] Finished 'serve' after 25 ms
[BS] [BrowserSync SPA] Running...
[BS] Access URLs:


   Local: http://localhost:8080/
External: http://192.168.1.4:8080/

      UI: http://localhost:3001

UI External: http://192.168.1.4:3001


[BS] Serving files from: .tmp/serve
[BS] Serving files from: app

events.js:72
throw er; // Unhandled 'error' event
^
Error: spawn ENOENT
at errnoException (child_process.js:1011:11)
at Process.ChildProcess._handle.onexit (child_process.js:802:34)
bhagat:/var/www/smart-dms/dms/client_side$

My code snippet is as below :
'use strict';

var gulp = require('gulp');
var browserSync = require('browser-sync');
var browserSyncSpa = require('browser-sync-spa');

var util = require('util');

var middleware = require('./proxy');

module.exports = function(options) {

function browserSyncInit(baseDir, browser) {
browser = browser === undefined ? 'default' : browser;

var routes = null;
if(baseDir === options.src || (util.isArray(baseDir) && baseDir.indexOf(options.src) !== -1)) {
  routes = {
    '/bower_components': 'bower_components'
  };
}

var server = {
  baseDir: baseDir,
  routes: routes,
  port:8080
};

if(middleware.length > 0) {
  server.middleware = middleware;
}

browserSync.instance = browserSync.init({
  startPath: '/',
  server: server,
  browser: browser,
  port:8080
});

}

browserSync.use(browserSyncSpa({
selector: '[ng-app]'// Only needed for angular apps
}));

gulp.task('serve', ['watch'], function () {
browserSyncInit([options.tmp + '/serve', options.src],'Google Chrome');
});

gulp.task('serve:dist', ['build'], function () {
browserSyncInit(options.dist, 'Google Chrome');
});

gulp.task('serve:e2e', ['inject'], function () {
browserSyncInit([options.tmp + '/serve', options.src], []);
});

gulp.task('serve:e2e-dist', ['build'], function () {
browserSyncInit(options.dist, []);
});
};

@HiZhaoxiaoyang
Copy link

-_- if create different browserSync with diff port,it still a 'cross origin' url, front-end still invoke it by jsonp and post method won't work.

@asuh
Copy link

asuh commented Feb 8, 2018

This thread gives me the closest to using multiple subdomains with Browsersync, via this comment.

Is there a way that each BS init can do rewrites when one or the other references each other?

For example, in his example above, bs1 used for http://mylocal.dev translates into http://localhost:3010. However, there are several links in bs1 that are the same as bs2 init, but they are not rewritten in bs1 instance to http://localhost:3012. The opposite is also true.

Any solutions to fix this?

@mobiledeevloper
Copy link

How we can restrict browser-sync to run on the same port as the backend is running using react gulp and asp.net core.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests