Using the original URL, not proxy, with browser-sync

Recently switched from Grunt.js to Gulp.js as multiple people told me how much better and faster it wa (it's true!). I have added BrowserSync to my Gulpfile.js, making it easier to test on multiple devices. It works great and was simple to setup. For context, I develop WordPress sites for 95% of my working time, and run them on an Apache Virtual Host, with Multisite enabled, and have lots of local sub-domains set up for each client, e.g site1.domain.dev, site2.domain.dev, etc. This works great, and I have been doing it this way for a couple of years now. However, because BrowserSync needs to create a proxy to my site so it's able to sync and inject the CSS, the site currently running through BrowserSync is routed to http://localhost:3000. This is fine and I understand why it needs to happen, but it messes with WordPress a bit (as the URL isn't the same etc), plus I'm a big TypeKit/Cloud fonts user, which means that because the site is being routed through to localhost, none of the fonts are loaded. Of course, I could just add http://localhost:3000 to the list of domains for each site on TypeKit, but this feels like a bit of a workaround and was wondering if there's a better way to do it.

I have added in the BrowserSync part of my Gulpfile.js:

gulp.task('serve', function() {
    browserSync({
        proxy: 'site1.domain.dev'
    });

    gulp.watch('assets/styles/source/**/*.scss', ['styles']);
    gulp.watch('*.php', reload);
    gulp.watch('assets/js/source/*.js', ['scripts']);
    gulp.watch('assets/js/plugins/**/*.js', ['plugins']);
});

So my question is, would it be possible for BrowserSync to go directly to my URL (http://site1.domain.dev) instead of routing it though http://localhost:3000? As an added bonus, it would be awesome if the domain could be removed from the BrowserSync proxy property, as I use an automation script to set up a new site on my WP Multisite installation and don't really want to have to edit my gulpfile everytime I set up a new site.

Thanks for the help! :)


Solution 1:

For me, it worked by specifying host and then open: 'external', like this:

browserSync.init({
  proxy: 'http://myproject.dev/',
  host: 'myproject.dev',
  open: 'external'
});

Solution 2:

Check if it will help you. My gulpfile.js looks like this:

gulp.task('browser-sync', function () {
  browserSync({
    logPrefix: 'Your Project',
    host: 'site1.domain.dev',
    port: 3060,
    open: false,
    notify: false,
    ghost: false,

    // Change this property with files of your project
    // that you want to refresh the page on changes.
    files: [
      'public/css/**.min.css',
      'public/js/**.min.js',
      'app/**/*.php',
      'index.php',
      '.htaccess'
    ]
  });
});

After you run Gulp, the console will show a snippet of code that you need to put in your HTML before the </body>. The version of browser-sync-client and the port you are using may be different. Note: after you insert the snippet in your code, the message will still appear. From version 1.5.2 of BrowserSync, you can disable the log snippet with logSnippet: false in your configuration.

[Your Project] Copy the following snippet into your website, just before the closing </body> tag
<script type='text/javascript' id="__bs_script__">//<![CDATA[
    document.write("<script async src='http://HOST:3060/browser-sync/browser-sync-client.X.X.X.js'><\/script>".replace("HOST", location.hostname));
//]]></script>

[Your Project] Access URLs:
----------------------------------
UI: http://localhost:3060
----------------------------------
UI External: http://site1.domain.dev:3060
----------------------------------
[Your Project] Watching files...

After you insert the generated snippet in your file, save the file and open the address http://site1.domain.dev without port in your browser. If everything is correct, the site will update on changes from browserSync.files.

You can add a verification to only include this snippet in development environments. For example, I using PHP and CodeIgniter in my projects, so, to include only in development environments, I do this:

<?php
if (ENVIRONMENT === 'development') {
    $browserSync = rtrim(base_url(), '/') . ':3060/';
    $fileHeaders = @get_headers($browserSync);

    if ($fileHeaders) { ?>
        <script id="__bs_script__">
            document.write("<script async src='http://HOST:3060/browser-sync/browser-sync-client.X.X.X.js'><\/script>".replace("HOST", location.hostname));
        </script>
    <?php }
} ?>

Solution 3:

Good question - I'm on WordPress too and had a similar issue. The documentation on the BrowserSync site doesn't really make this clear, but I came across a solution to my problem on the Overview page of the BrowserSync UI that runs at http://localhost:3001/. The message comes up when you run BrowserSync without a mode flag like --proxy.

If you paste this snippet somewhere before your closing </body> tag

<script type='text/javascript' id="__bs_script__">//<![CDATA[
    document.write("<script async src='http://HOST:3000/browser-sync/browser-sync-client.2.6.1.js'><\/script>".replace("HOST", location.hostname));
//]]></script>

and run BrowserSync without the --proxy flag, for example

browser-sync start  --files "css/*.css"

It will refresh your site at its normal address. I'm going to wrap the snippet in a condition so it only gets included on my dev environments - in the future maybe some kind person could write a LiveReload-style Chrome extension to do the job. Not sure if this fits your particular case with Gulp, but it works with command line.

Solution 4:

Using Varying-Vagrant-Vagrants I follow the solutions already mentioned but I kept getting a net::ERR_CONNECTION_REFUSED when polling from Browser Sync, to solve that I did the following:

gulpfile.js

const gulp = require("gulp");
const browserSync = require("browser-sync").create();

gulp.task("serve", () => {
    browserSync.init({
        socket: {
            domain: "localhost:3000"
        }
    });

    gulp.watch("**/*.php").on("change", browserSync.reload);
});

Running gulp serve on your terminal will log a snippet, from that snippet take the version of the browser-sync-client and replace it in:

functions.php

<?php

add_action( 'wp_footer', function () { ?>
    <script type='text/javascript' id="__bs_script__">//<![CDATA[
        document.write("<script async src='http://localhost:3000/browser-sync/browser-sync-client.X.X.X.js'><\/script>");
    //]]></script>
<?php }, 999);

?>

Note that the host name of the script is the same as the socket domain localhost:3000 and that at this point you should be able to enter from your domain name and have Browser Sync reloading your site when any php file is changed.


If you want to get rid of the snippet that Browser Sync logs:

browserSync.init({
    logSnippet: false,
    socket: {
        domain: "localhost:3000"
    }
});

Solution 5:

Here's what worked for me, because when I deploy my app it needs to listen on all addresses by using 0.0.0.0:5000 - just like Heroku does. I use dokku, and open source option for a Heroku-like PaaS.

gulp.task('serve', () => {
  browserSync.init({
    port: process.env.PORT || 5000,
    server: { baseDir: root }, // you may not need this
    domain: '0.0.0.0'
 });
});

It still opens on localhost:5000 when I run the gulp task, but as I usually only need gulp for development and not production this has been working fine for me.