How is this webpack devServer configured incorrectly? - reactjs

I am running into issues with my webpack-dev-server. When i try to load at a specified route such as "http://localhost:3000/login" I get the following message "Cannot GET /login".
I've read through the docs and seen many different solutions, but I don't see the flaws in my config. I have my webpack setup like this.
webpack.config.js
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'bundle.js',
},
module: [ rules... ],
devServer: {
contentBase: path.join(__dirname, 'build'),
compress: true,
port: 3000
},
}
My scripts for the app look like this:
"build": "webpack",
"dev": "webpack-dev-server --open"
If I run dev the app will open to the initial route - "/". If I click on a link to login - "/login" that will load fine. But if I refresh the page on login it will throw the "Cannot GET /login" error.
Is there something I'm missing or have wrong in my webpack configuration?

webpack-dev-server only serves two things: bundled assets, and whatever is in the directory you gave it as the value for contentBase. things work the way you want when you browse to / then navigate to /login since I assume you have some kind of client-side routing framework in your webapp. none of that applies when you refresh your browser and ask the server for a page at /login .
w-d-s is 404ing on you since you don't have a file named "login" in your build directory (and I doubt you have a compiled bundle or chunk with that name either). do you have an index.html file in that directory? is that what you're served when you visit localhost:3000/ ? does that file have a <script> tag which loads your webapp?
what were you expecting to happen when you visited /login ? I'm assuming you wanted to display your webapp's login screen when you visit localhost:3000/login ? if so you'll most likely need to use a separate server like express.js to server-side-render your webapp. this server can either be on a different port from the server launched by w-d-s, or it can actually use w-d-s as middleware so you only need one server with one port.
this seems like a decent resource at first glance: Server side rendering with react, react-router, and express . but if it doesn't work for you, there are dozens more on SO already which might.

Related

React/vite app with base URL that does not apply to static links in the main HTML file

I have a question, around base urls. I have a React/Vite application that will get deployed into a webserver that hosts many other web-properties, and as part of this, all web-properties include shared JS and CSS. These shared JS/CSS are all served off the root do the domain (ex. https://www.my-domain.com/assets/shared.js). These includes are just hard coded into my main HTML file (usually index.html, but in my case root.html)
My React app however is served from https://www.my-domain.com/apps/catalog/root.html.
If i run my app locally with just npm run dev, everything works - but but my app is served off the root. I thought the right way to have this all run off my /apps/catalog/ based URL was to run all my vite commands with --base=/apps/catalog which seems to almost work; the problem is it rewrites thee static shared includes, which break them, since theyre expected to be served off the root.
I think, i need to figure out how to mark specific includes as not being effected by the base URL rewrite? Or, is there a better way to approach this?
My HTML file w/ the static includes of the "shared" assets. I dont want to hardcode the "real" domain in the src URLs since then my local proxy can't trap them and grab them serverside preventing CORS issues.
// /src/root.html
<html>
<head>
<!-- served from: https://www.my-domain.com/assets/shared.js -->
<script src="/assets/shared.js"/>
<!-- served from: https://www.my-domain.com/api/shared.js -->
<script src="/api/shared.js"/>
.. etc ..
</head>
<div id="app"></div>
</html>
My vite.config.js where i start to try to introduce the notion of a base url (and a non-index.html named "main" file)
The local proxy so these static includes resolved without CORS issues, for local dev (it proxies these static assets out to the Shared host, and everything works well locally).
// src/vite.config.js
export default defineConfig({
plugins: [react()],
build: {
assetsDir: 'static-assets',
rollupOptions: {
input: {
app: './root.html',
},
},
},
base: '/apps/catalog/',
server: {
open: '/root.html',
proxy: {
'^/assets/.*|^/api/.*': {
target: 'https://www.my-domain.com',
changeOrigin: true
}
}
}
})
And my package.json where i tried to also set the base URL.
// package.json scripts
"dev": "vite --base=/apps/catalog/",
"build": "vite build --base=/apps/catalog/"
I had the same problem with Laravel 9 + vite v3.2.5.
I fixed it (after hours) with the experimental renderBuiltUrl:
import {defineConfig, loadEnv} from 'vite';
// load env variables to get base url
process.env = Object.assign(process.env, loadEnv('production', process.cwd(), ''));
export default defineConfig({
// ...
experimental: {
renderBuiltUrl(filename) {
// here we set the base url. You might have to change this for react:
return process.env.APP_URL + '/build/' + filename;
}
}
}
Note the warning in the documentation:
This feature is experimental, the API may change in a future minor without following semver. Please always pin Vite's version to a minor when using it.

Serve multiple entry points with webpack dev server

I've got multiple entry points being generated with outputs successfully but what I'm not too sure on is if there is a way with the webpack dev server to serve these multiple entry points and somehow be able to work on them all at the same time?
Here is my basic setup right now, is there a way I can get webpack dev server to somehow serve these on different ports maybe or by changing the URL serve the different entry points?
I've tried changing the port number on one of the apps but it doesn't seem to run a server with that port, which I kind of figured it wouldn't
entry: {
dashboard: [
"webpack-dev-server/client?http://localhost:3000",
"webpack/hot/only-dev-server",
paths.appIndexJs
],
display: [
"webpack-dev-server/client?http://localhost:3000",
"webpack/hot/only-dev-server",
paths.displayJs
]
},
output: {
pathinfo: true,
filename: "static/js/[name].js",
chunkFilename: "static/js/[name].chunk.js",
publicPath: publicPath,
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath).replace(/\\/g, "/")
},

Webpack Dev Server Issues

I am building a web application using Express + React.
I am dealing with a issue with WEbpack Dev Server.
My Webpack Dev Server builds the bundles just fine!
But, I have an issue with the way the files are served.
Usually , we name the root html file as index.html, but because of my Web application architecture , I cannot use index.html and have instead name it client.html.
This brings me to the problem that I am facing, the webpack dev server looks for the index.html when I go to localhost:8080, as I am using client.html the webpack dev serves asks me to select my file.
Webpack Static file select screen
So , is there a way to load client.html directly when I access localhost:8080(Webpack Dev Server).
Thanks in Advance!
In your webpack.config.js file you can add the configurations for the webpack dev server
devServer: {
historyApiFallback: {
rewrites : [
{from: /^\/$/, to: './client.html'}
]
}
}
This will redirect your default index.html to the client.html
For more details see the DevServer documentation

Web-pack successfully compiled but does not show output in browser

Browser http://localhost:8080 still says
This page isn’t working
localhost didn’t send any data.
ERR_EMPTY_RESPONSE
As you are using webpack, please check what parameters you have used in devserver tag of your webpack.config.js file.
It should be as below:
devServer: {
inline: true,
contentBase: './src',
port: 3000
},
Hope this will resolve your issue.

Webpack dev server cannot get `http://localhost/8080/bundle.js`

Given this config:
var webpack = require('webpack');
const path = require('path')
module.exports = {
entry: "./src/index.js",
output: {
path: path.join(__dirname, 'dist'),
publicPath: path.join(__dirname, 'dist'),
filename: "bundle.js"
},
devServer: {
contentBase: "./dist",
// hot: true,
}
}
Why won't webpack-dev-server server my app properly? I have 0% understanding of localhost, vs localhost/webpack-dev-server, vs publicPath, vs contentBase, etc.. I know all of these paths, and configuration keys are important to setting up my project properly but despite hours of reading about them, they remain as confusing as when I started.
If I go to localhost:8080/webpack-dev-server I see Get http://localhost:8080/bundle.js net:ERR_ABORTED` in the console.
Below are simple and straight forward rules for webpack & webpack-dev-server :
output.path : It needs to be an absolute path or /. You can get it easily using path.join
output.filename : This needs to be the name of output file without any extra file path.
devServer.contentBase : It is the physical location on the disk which is served as the root directory of webpack-dev-server when you open http://localhost:8080
By convention, we keep both output.path and devServer.contentBase same.
The tricky part is when you run webpack cmd, it generates the physical bundle.js file.
But when you run webpack-dev-server, NO PHYSICAL OUTPUT file is generated, rather it keeps the generated output in memory to avoid File-Write operate which in turn helps in faster development/debugging cycle.
So any change you make in src.js or main.js file, it will generate the output but won't write that to disk and wepack-dev-server reads that directly from the memory.
output.publicPath : This is used by webpack, webpack-dev-server & other plug-in to generate the output or serve the generated bundle.
The default value is /.
It is VIRTUAL PATH and need not be present on the physical
disk. Example : final application name if multiple apps are
hosted on the same server like /app1, /app2, or some external CDN path
/CDN-Path.
It is also helpful for React-Router <BrowserRouter basename='/app1'>
Now to refer the bundle output file that is generated & kept in the memory , you need to append the output.publicPath i.e. Virtual Path in the browser's URL.
The final URL for webpack-dev-server will be :
http://localhost:8080/<output.publicPath>/<output.filename>
In your case, either you change the
publicPath: path.join(__dirname, 'dist')
to
publicPath: '/dist' if it contains any spaces.
You can check it by printing the value of path.join(__dirname, 'dist') which returns the absolve path [different on MacOS & Window system].
http://localhost:8080/dist/bundle.js
If you want to dig further deeper, then here is the URL
https://medium.com/p/webpack-understanding-the-publicpath-mystery-aeb96d9effb1

Resources