choojs / nanorouter

🛤 - Small frontend router
MIT License
116 stars 20 forks source link

Mounting on a sub-path #14

Open tnguyen14 opened 6 years ago

tnguyen14 commented 6 years ago

When trying to use choo on a static site hosted by Github pages, the app lives on a subpath (like https://tnguyen14.github.io/projectname/my-app. This is breaking the router, as it doesn't match the route that I define in the app (which assumes the app lives at the root domain).

Is there a way to take this into account?

/cc @yoshuawuyts

yoshuawuyts commented 6 years ago

@tnguyen14 heya! - this sounds similar to what @finnp was running into recently.

There was a clever workaround which I forgot, but something simple would be:

var base = process.env.NODE_ENV === 'production' ? '/projectname' : ''

var app = choo()
app.route(`${base}/foo`, fooView)

Does this make sense?

tnguyen14 commented 6 years ago

@yoshuawuyts Thanks. I just tried this, but I am still seeing Route not found error.

tnguyen14 commented 6 years ago

After trying out a few different configurations, I figured out that

app.route(`${base}`, mainView)

works, but

app.route(`${base}/`, mainView)

does not.

Not sure why, perhaps with the way the path matches. The app's URL does contain the ending url, i.e. ...github.io/projectname/my-app/.

rook2pawn commented 6 years ago

tldr: "/" signifies the root but also the lack of a route. the navigator events state.route reflect this on the "root" of github pages app, i.e. if your repo is named myRepo then you navigate to the root, state.route == "myRepo", whereas on localhost, if you navigate to the root state.route == "/"

a github project named myRepo will put its url at https://yourname.github.io/myRepo so the choo app (when compiled with bankai build app.js --base="https://myUsername.github.io/myRepo") will look for /myRepo when the app loads in the browser and

app.route('myRepo', mainView)

will work without the prepended slash. Additionally, https://yourname.github.io/myRepo/baz one can simply have a route of

app.route('myRepo/baz', bazView)

This has symmetry with the navigator route events. Going to myRepo/baz in the browser results in -> state.route == "myRepo/baz" However there is an idiosyncracy on localhost (where there is no prepended "/myRepo")

so on localhost app.route("/", view) -> state.route == "/" but also app.route("", view) -> state.route = "/" and on github-pages app.route("myRepo", view) -> state.route == "myRepo"

so if root = "/" on localhost

path.join(root, 'baz') // yields "/baz"  
state.route !== "baz" // true

and root = "foo" on github-pages,

path.join(root, 'baz') // yields "foo/baz"
state.route === "foo/baz"

So let me outline the problem as I see it

  1. You want to develop an app and deploy it on github pages

  2. You can have simply prepend all your routes with "<repoName>/" i.e.

    app.mount('myRepo', mainView)
    app.mount('myRepo/bar', barView)
  3. and make sure to bankai build app.js --base="https://myUsername.github.io/myRepo"

  4. So you can make your code look like something like

    app.mount(getBase(), mainView)
    app.mount(path.join(getBase(), "bar"), barView)

    where

    function getBase () { return "" } // on localhost
    function getBase() { return "myRepo" } // on deployed github app
  5. But if you are wanting to check state.route you have to special case when you are looking for the root on localhost vs the root on githubpages.

    function getBaseStateRoute () { return "/" } // on localhost
    function getBaseStateRoute() { return "myRepo" } // on deployed github app

    I think this is a small issue, but I wanted to present what I found. I think its worth exploring the idea if the state.route on the root of localhost could be "" the empty string as that would mean you would only have to prepend one function or kind of check in either your app.mount code or when dealing with state.route.

@tnguyen14 @yoshuawuyts @goto-bus-stop