Hello everyone Greetings of the day I need some h...
# javascript
s
Hello everyone Greetings of the day I need some help with figuring out how to get the
BrowserRouter
working on my codebase. So I have created a new Kotlin/JS app and the only change I have made in the code is instead of directly rendering the
welcome
screen, I am loading it inside a
BrowserRouter
Like this:
Copy code
createRoot(container).render(
    BrowserRouter.create {
        Routes {
            Route {
                path = "/login"
                element = welcome
            }
            Route {
                 path = "*"
                element = VFC { +"404 Not found!" }.create()
            }
        }
    }
)
Now, the problem with the output of this code is that if I type
<http://localhost:8080/login>
in my browser, it gives me the following error:
Cannot GET /login
. Following are the only two entries I see in the console:
Copy code
1. failed to load resource: the server responded with a status of 404 (Not Found)

2. DevTools failed to load source map: Could not load content for <chrome-extension://fjdmkanbdloodhegphphhklnjfngoffa/lib/browser-polyfill.min.js.map>: System error: net::ERR_BLOCKED_BY_CLIENT
Now the interesting thing is that, instead of a
BrowserRouter
, if I use a
HashRouter
and instead of entering
<http://localhost:8080/login>
, I enter
<http://localhost:8080/#/login>
in my browser, the same code starts working perfectly fine 👍 So I am not sure what changes do I need to make in order for the
BrowserRouter
to work fine. Any help would be greatly appreciated.
👀 1
m
I had the same issue... I assumed that I need to have an HTTP server that supports request rewriting etc, and that the devtools server doesn't do that. I wound up using HashRouter for that reason. Maybe there is a workaround, will watch this thread...
👍 2
s
@turansky could you please help?
t
I assumed that I need to have an HTTP server that supports request rewriting etc
Yes, backend support required in such cases
s
Yes, backend support required in such cases
Sorry for a basic question, can we do something in our case? Can we somehow try to make it work on our development machine as well?
t
Do you use
webpack-dev-server
?
s
I haven’t tried it yet Where can I find its resources?
t
Can we somehow try to make it work on our development machine as well?
How you run
localhost
?
./gradlew run -t
?
s
I directly use the
browserDevelopmentRun
gradle task
This
I’m sorry if I’m not able to provide you with the most appropriate information. Please treat me as a noob and ask for any particular detail that would help you identify the issue. I will try my best to provide it.
t
I directly use the
browserDevelopmentRun
gradle task
It means, that you use
webpack-dev-server
👍 1
s
Correct
t
Option 1. 1. Webpack is main 2. Ktor/your server - additional run 3. Webpack Dev Server has proxy configuration for backend Option 2. 1. Ktor/your server is main 2. JS is static and provided by task 3. No HMR :(
s
Option 1 seems more feasible for me
t
You will need 2 terminals in that case
🆗 1
You can check generated
webpack.config.d
folder if you want static webpack configuration
s
Understood So the main point to understand is that we need to give some custom configuration to the webpack in order for it to understand and treat our localhost as one of its proxies and allow development on it?
And one of the ways to do so is to use
Copy code
id "io.github.turansky.kfc.dev-server" version "5.71.0"
Thank you for your help @turansky 🌟 I will try this out and update my findings on this thread for someone else to go through in the future 🚀
Copy code
plugins {
    kotlin(Plugins.Kotlin.JS)
    id("io.github.turansky.kfc.webpack") version "5.71.0"
}

group = App.Group
version = App.VersionName

repositories {
    google()
    maven("<https://maven.pkg.jetbrains.space/public/p/compose/dev>")
}

fun kotlinw(target: String): String = "org.jetbrains.kotlin-wrappers:kotlin-$target"

dependencies {
    implementation(enforcedPlatform(kotlinw(Deps.Kotlin.JS.WrappersBOM)))
    implementation(project(":common"))
    implementation(kotlinw("react"))
    implementation(kotlinw("react-dom"))
    implementation(kotlinw("emotion"))
    implementation(kotlinw("react-router-dom"))
}

kotlin {
    js(IR) {
        binaries.executable()
        browser {
            commonWebpackConfig {
                cssSupport {
                    enabled = true
                }
                devServer = devServer?.copy(
                    open = false,
                    port = 3000
                )
            }
        }
    }
}

tasks {
    patchWebpackConfig {
        proxy("<http://localhost:3000/>")
    }
}
I tried the library out Maybe I’m doing something wrong Because with the code above, when I try to access the app, I get this error:
Copy code
<i> [webpack-dev-server] Content not from webpack is served from '/Users/shubhamsingh/IdeaProjects/play-together-kmp/web/build/processedResources/js/main' directory
<e> [webpack-dev-server] [HPM] Error occurred while proxying request localhost:3000/ to <http://localhost:3000/> [EAGAIN] (<https://nodejs.org/api/errors.html#errors_common_system_errors>)
<e> [webpack-dev-server] [HPM] Error occurred while proxying request localhost:3000/favicon.ico to <http://localhost:3000/> [ETIMEDOUT] (<https://nodejs.org/api/errors.html#errors_common_system_errors>)
I don’t know if this is helpful information or not, but this is part of a KMP project (so maybe I need to make some changes or include some plugins in the common gradle.kts as well?)
s
For future readers, here's the solution: https://kotlinlang.slack.com/archives/CL4C1SLKC/p1670366334063489?thread_ts=1670278850.356839&cid=CL4C1SLKC
TL;DR:
1. Create a package named
webpack.config.d
in your Kotlin/JS module (i.e. it should be on the same level as the
src
package), create a file inside it called
webpack.js
, and paste the following line in it:
config.devServer.historyApiFallback = true;
2. Paste the following code in your JS module's
build.gradle.kts
file:
Copy code
js(IR) {
        browser {
            runTask(
                Action {
                    devServer = KotlinWebpackConfig.DevServer(
                        open = false,
                        port = 3000,
                        static = mutableListOf("${layout.buildDirectory.asFile.get()}/processedResources/js/main")
                    )
                }
            )
        }
        binaries.executable()
    }
Here, only the
static
line of code is important, you can ignore the other values