netlify / cli

Netlify Command Line Interface
http://cli.netlify.com
MIT License
1.58k stars 359 forks source link

Make live url accessible to underlying build command #1623

Open lukaskurz opened 3 years ago

lukaskurz commented 3 years ago

Is your feature request related to a problem? Please describe.

I am currently trying to set up a shop using hugo as a SSG and stripcart for all payment related things. It is possible to test the payment functionalities locally, by exposing my env with something like ngrok, which basically does something similar to netlify dev --live, and then whitelisting that "live url" in stripcart. I really like your tooling so far, so I wanted to see, if I could use netlify dev --live instead of ngrok.

This is when i noticed that hugo overrides the baseurl, that is set in the hugo configs, with whatever url the hugo server command gets passed(or if nothing gets passed, it uses the default "localhost:1313"). This results in the content being rendered with baseurl="localhost:1313", even if it is accessed over the "live url". This is problematic, because i need to render a publicly available url for stripcart to crawl and fetch data from, and this will now read "localhost:1313" which is obviously useless to stripcart.

Describe the solution you'd like

We can already modify the command netlify dev uses. I would simple make some sort of variable accessible to the command, or do some string templating, like this: netlify.toml

[dev]
  command = "hugo server --baseURL=$LIVE_URL_VARIABLE_I_WAS_TALKING_ABOUT

I found some other online discussions, that needed something like this, so maybe you already made this possible, but I was unable to find any mentions about it in your documentation.

Describe alternatives you've considered

An alternative solution for me, would to hack some custom building script together, instead of hugo server, that does live rebuilding and web hosting, so basically a hugo server without the implicit baseurl overriding. Or just using ngrok and then restarting the hugo server with ngrok url.

Another, more complex alternative, but probably even better solution, would be to run 2 instances of the hugo server. One instance would be running with, say "localhost:1313", as baseurl, so that baseurl rendering works as intended locally, while the other instance runs with the live url as baseurl. This second instance would then also be the one, that is exposed and renders the baseurl as the live url.

Can you submit a pull request?

This really doesn't seem too difficult, depending on how/when the cli has access to the live url. I'd definitely be able to do this myself, I've got plenty of time right now, and also some enthusiasm on contributing to cool projects :smile:

Pull requests are welcome! If you would like to help us add this feature, please check our contributions guidelines.

lukaskurz commented 3 years ago

For now, I'm running a modified version of the cli, where I hacked this functionality together. I basically started the liveTunnel before starting the framework server, so the framework server has access to the liveUrl. Then i just replace this pattern {{BASE_URL}} with the url in the args. Works pretty neat.

src/commands/dev/index.js:194

    let settings = {}
    try {
      settings = await serverSettings(devConfig, flags, site.root, log)
    } catch (error) {
      log(NETLIFYDEVERR, error.message)
      exit(1)
    }

    let url = await startProxyServer({ flags, settings, site, log, exit, addonsUrls })

    const liveTunnelUrl = await handleLiveTunnel({ flags, site, api, settings, log })
    url = liveTunnelUrl || url

    // replacing the base url slug
   settings.args = settings.args.map(a => a.replace("{{BASE_URL}}", url))

    // this section was moved below the `handleLiveTunnel` call, to have access to the liveTunnelUrl
    await startFunctionsServer({
      settings,
      site,
      log,
      warn,
      errorExit,
      siteUrl,
      capabilities,
    })
    await startFrameworkServer({ settings, log, exit })

then i can just edit the netlify.toml config like this

[dev]
  command = "hugo server --baseURL {{BASE_URL}}"

This way the netlify dev command works properly in live and "not-live" mode. Only thing is, when running in live mode, and accessing the site via localhost, then urls would not match up, but I'd argue this is intended behaviour for running in live mode.

I am not sure whether the order of starting framework-server and livetunnel is very important, or if there is some deeper thought process behind it, but it didn't seem to break anything on first sight.

lukaskurz commented 3 years ago

I'm going to attach some additional information here, in case somebody else stumbles upon the same problem. I still had issues with hugo server attaching a port to my baseurl, so I had to do a hacky little workaround:

I set up a makefile that would build my hugo file with --watch, which does not attach a port number to your baseurl. Parallel to that, I have a python web server running, to serve the file via http.

makefile

BASE_URL=http://localhost:1313

test-live: proxy watch serve

watch:
    hugo --watch --baseURL $(BASE_URL)

serve:
    cd public &&\
    python -m http.server 1313

BASE_URL gets overridden by the command called from netlify dev.

netlify.toml

[dev]
  framework = "#custom"
  command = "make -j2 test-live BASE_URL={{BASE_URL}}"
  targetPort = 1313

The -j2 is there so that make can run 2 processes in parallel, instead of waiting for the first to exit, before it starts the second.

It's not beautiful, but it does it's job, I can now finally test the snipcart API, while developing from my local machine, instead of rebuilding a dev environment in netlify everytime I change something.

jasikpark commented 3 years ago

This has been the main thing preventing me from using netlify dev for my Hugo website -- it's unusable when all of the links generate with the wrong port.

I've tried simply using:

[dev]
command = "hugo server --baseUrl='http://localhost:8888' --appendPort=false --cleanDestinationDir --disableFastRender"
framework = "#custom"
port = 8888
targetPort = 1313

but when I run netlify dev, hugo doesn't like having colons in the baseUrl, so it doesn't seem to work.