We do quite a bit of Shopify App development around here. Most of our apps use a Rails backend using webpacker with a Polaris embedded app. When developing, it’s nice to have livereload setup even when the app you’re working on is embedded.

A van driving through a mountain tunnel.
Photo by Mitul Shah from Burst

ngrok Tunnels

ngrok is the best developer tool you’re missing out on. No more waiting for deploys, instantly get a public URL for any local web server to demo websites, handle webhooks, and more. I copied that from the suggested text on the ngrok site and it’s entirely true.

You’ll need to expose two tunnels: one for your web server and one for the web socket. No problems here since ngrok handles those with ease. I start these all the time, so I’ve got these in my ngrok.yml config file.

tunnels:
  kd-rails:
    addr: 3000
    proto: http
    bind_tls: true
    subdomain: my-rails-server
  kd-webpack:
    addr: 3035
    proto: http
    bind_tls: true
    subdomain: my-webpack-server
    host-header: localhost:3035

Running ngrok start kd-rails kd-webpack will start up a new ngrok instance and expose those two internal servers using those subdomains using SSL only.

Webpacker Config

You can’t set this in the webpacker.yml file that ships with Rails. We’ll have to drop down in to the config/webpack/development.js file to handle this.

You can hard code your tunnel name in the config file. This is fine if you’re a solo dev and your tunnel name doesn’t change.

process.env.NODE_ENV = process.env.NODE_ENV || "development";

const environment = require("./environment");

environment.config.merge({
  devServer: {
    public: 'my-webpack-tunnel.ngrok.io'
  }
});

module.exports = environment.toWebpackConfig();

Alternatively, you can load your tunnel from .env. This is helpful if you’re on a team and everyone has different tunnel names. I use dotenv to make this easier. First, run yarn add --dev dotenv. Then, update config/webpack/development.js to pull the tunnel name from the config.

process.env.NODE_ENV = process.env.NODE_ENV || "development";

const environment = require("./environment");
const dotenv = require("dotenv");
dotenv.config({ path: ".env", silent: true });

const ngrokTunnel = process.env.NGROK_WEBPACK_TUNNEL;

environment.config.merge({
  devServer: {
    public: ngrokTunnel
  }
});

module.exports = environment.toWebpackConfig();

That’s it. Start your servers and your tunnels and you’re ready for development.