Skip to content

Nuxt 3 Support #21

@silverbackdan

Description

@silverbackdan

I've taken the liberty of using this module as a basis and creating a Nuxt 3 compatible module:

import ngrok from "ngrok";
import type { Ngrok } from "ngrok";
import chalk from "chalk";
import { defineNuxtModule } from "@nuxt/kit";
import type { Server as HttpServer } from "http";
import type { Server as HttpsServer } from "https";
import consola from "consola";

// https://github.com/bubenshchykov/ngrok
export type ModuleOptions = Partial<Ngrok.Options>;
declare module "@nuxt/schema" {
  interface NuxtConfig {
    [CONFIG_KEY]?: ModuleOptions;
  }
}
const CONFIG_KEY = "ngrok";

export default defineNuxtModule({
  meta: {
    // Usually  npm package name of your module
    name: "ngrok",
    // The key in `nuxt.config` that holds your module options
    configKey: CONFIG_KEY,
    // Compatibility constraints
    compatibility: {
      nuxt: "^3.0.0",
    },
  },
  // Default configuration options for your module
  defaults: {
    authtoken: process.env.NGROK_TOKEN,
    auth: process.env.NGROK_AUTH,
  },
  hooks: {},
  async setup(moduleOptions, nuxt) {
    // Don't start NGROK in production mode
    if (nuxt.options.dev === false) {
      return;
    }
    if (!moduleOptions.auth) {
      // eslint-disable-next-line no-console
      consola.warn(
        "[ngrok] Dev server exposed to internet without password protection! Consider using `ngrok.auth` options"
      );
    }
    // Start NGROK when Nuxt server is listening
    let url: string;

    nuxt.hook(
      "listen",
      async (_server: HttpServer | HttpsServer, listener: any) => {
        if (moduleOptions.authtoken) {
          await ngrok.authtoken(moduleOptions.authtoken);
        }
        const { port } = new URL(listener.url);
        url = await ngrok.connect({
          ...moduleOptions,
          addr: port,
        } as Ngrok.Options);

        nuxt.options.publicRuntimeConfig.ngrok = { url };
        consola.success(chalk.underline.green(`ngrok connected: ${url}`));
      }
    );

    // Disconnect ngrok connection when closing nuxt
    nuxt.hook("close", () => {
      if (url) {
        ngrok.disconnect();
        consola.success(chalk.underline.yellow("ngrok disconnected"));
        url = null;
      }
    });
  },
});

There is a bug in Nuxt 3 where if we modify the nuxt config file, the listen hook is not called again after the close hook.

Additionally, right now I seem to have to use this config:

  vite: {
    server: {
      hmr: {
        protocol: "ws",
        host: "127.0.0.1",
      },
    }
  }

This prevents an infinite reload when accessing via the ngrok domain..

This is a WIP and no sure how to resolve the vite hmr issue in a more robust way right now. Happy for someone else to take over or if there's a solution I'm happy to implement and create a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions