Cannot resolve nested path with snowpack - reactjs

In my react project a hard refresh of a nested path does not work. Then snowpack config tries to load from the folder "dist" and cannot serve the page.
config like in snowpack docu:
{
mount: {
public: '/',
src: '/_dist_',
},
...
}
error
http://localhost:3000/myfolder/id
GET http://localhost:3000/myfolder/_dist_/index.js net::ERR_ABORTED 404 (Not Found)

Related

webpack-dev-server - Remove URI fragment from URL when live reloading

I'm dealing with an Angular 1 application that uses URI fragments for routing purposes.
For example:
http://localhost:3000/#/home
http://localhost:3000/#/menu
http://localhost:3000/#/list
Rather than:
http://localhost:3000/home
http://localhost:3000/menu
http://localhost:3000/list
When I'm using Webpack Dev Server to launch a local server with hot reloading, every time I apply some changes, Webpack reloads the URL but keeping the "/#/route" part.
Unfortunately, due to some code restrictions, I need to always reload the page from "/" because some redirections are applied internally when the app launches the first time and the app will crash if you try to start directly from any URI fragment.
I tried to use the "proxy" and "historyApiFallback" configurations in webpack.config.js like:
devServer: {
proxy: {
'/#': {
target: 'http://localhost:3000',
pathRewrite: { '^/#': '' }
}
}
And:
devServer: {
historyApiFallback: {
verbose: true,
rewrites: [{ from: /^\/#/, to: '/' }]
}
}
But so far, I didn't have any luck. The URL keeps the hash when reloading.
Any suggestions or ideas to configure Webpack Dev Server to always start from "/" and remove the hash URI?

Express/React app refresh issue on Heroku

My React app with Express backend is hosted on Heroku, and all of the routing works as expected until the page refreshes. Refreshing the page either programmatically, or with the refresh button the page returns:
Failed to load resource: the server responded with a status of 404 (Not Found)
The back and forward buttons (which work before refreshing) cease to work and the only way to get the app back is to navigate to the "/". Everything works correctly then until the next refresh.
My server routes :
router.use("/api/skus", skuRoutes);
router.use("/api/categories", categoryRoutes);
// serve static files if in production
if (process.env.NODE_ENV === "production") {
router.use(express.static("client/build"));
router.get("*", (req: Request, res: Response) => {
res.sendFile(
path.resolve(__dirname, "..", "client", "build", "index.html")
);
});
}
I have read many, many other similar questions on here and many tutorials on using react router on Heroku, but I haven't found a solution that works for me.
I have already tried the solutions that use a static.json file:
{
"root": "build/",
"clean_urls": false,
"routes": {
"/**": "index.html"
}
}
, and adding the create-react-app buildpack to Heroku, but these do not work for me.
GitHub repo here.
Current deployment here.
The issue was fixed by changing my BrowserRouter to a HashRouter. Now refreshes work perfectly.

Configuring a single page Create-React-App on Heroku

With Firebase Hosting, when you deploy an app you are asked whether to rewrite all urls to /index.html. This means react-router routes would be properly fired whether they are accessed directly or navigated to from the homepage.
We use Create-react-app and Create-react-app-buildpack to deploy to Heroku. How can we rewrite all the URLs to /index.html in the same manner?
Following this issue, explaining about the routes directive, I configured a static.json in the root to no avail:
{
"routes": {
"/images/*": "/images/",
"/legal/*": "/images/",
"/media/*": "/media/",
"/fav/*": "/fav/",
"/styles/*": "/styles/",
"/**": "index.html"
}
}
Create a static.json file in the project root with the following content:
{
"root": "build/",
"routes": {
"/**": "index.html"
}
}
More here.

Webpack Dev Server - favicon not showing on localhost but works on external URL

I have a strange problem, I was wondering if anyone has experienced this. I have webpack in my app to bundle, serve and everything in between. I have noticed that when I compile and run webpack-devserver from my gulp file everything goes as expected and in my terminal I get the following:
webpack: Compiled successfully.
2017-11-30T11:46:05.288Z - error:
[Browsersync] Proxying: http://localhost:3001
[Browsersync] Access URLs:
--------------------------------------
Local: http://localhost:3002
External: http://10.101.51.117:3002
--------------------------------------
UI: http://localhost:3003
UI External: http://10.101.51.117:3003
--------------------------------------
Now when I access my app via 'localhost' no Favicon is shown in the browser tab for that page, there is no 404 in the console and there is no request for the favicon in the Developer Tools Network Tab? Now should I use the external URL and type http://10.101.51.117:3002 into the browser the Favicon is there in the page tab however there is no request for the favicon in the Developer Tools Network Tab.
Now when I make a direct call in the browser to the favicon to http://localhost:3002/assets/favicon.ico the favicon is served in the browser window so it seems like server is bundling the Favicon?
In my HTML I have the tag <link rel="shortcut icon" href="assets/favicon.ico"> nothing strange there and in my webpack.common.js file I have the following (I have removed some items here for simplicity)
module.exports = {
// lots of things here..
module: {
rules: [
// stuff here has been removed
{
test: /\.html$/,
use: 'html-loader'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot)$/,
use: 'file-loader?name=assets/[name].[hash].[ext]'
},
{
test: /\.(ico)$/,
use: 'file-loader?name=assets/[name].[ext]'
},
I can't think what or why the favicon isn't being shown in the tab when I use the localhost URL? If anyone has experienced this and resolved the issue and advice would be appreciated.
Please note that the Favicon is not cached from before as I have changed the favicon name, location and I cleared the browser cache.
If you are using HtmlWebpackPlugin then you can include favicon: './src/assets/favicon.ico', property there.
plugins: [
new HtmlWebpackPlugin({
template: './src/template.html',
favicon: './src/assets/favicon.ico',
filename: './index.html',
}),
],
BTW - starting from Chrome 80 you can use favicon.svg favicons as well.
Apparently your favicon should work but doesn't. Two things you may want to try:
Favicon caching is VERY nasty. I suggest you to test your favicon with a browser you normally don't use (so it didn't cache your icon).
Run the favicon checker. As your site is hosted locally, you will have to use ngrok to make is accessible from outside.
Disclosure: I'm the author of RealFaviconGenerator
I would use the file loader like this:
Install the package
npm i --save-dev file-loader
Then add the following to your webpack config (default webpack.config.js)
{
test: /\.(png|svg|jpg|gif|ico)$/,
use: ['file-loader?name=[name].[ext]']
}
This should move the files to your dist folder.
How about copying favicon.ico by using copy-webpack-plugin.
// File: webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
...
plugins: [
new CopyPlugin({
patterns: [
{ from: "favicon.ico" },
],
}),
]
}
Don't forget to reload browser page ignoring caches.

Matching root route in webpack-dev-server's historyApiFallback`

Sample repo demonstrating the issue is here.
I'm trying to set up webpack dev server so that:
Requests to / are served by public/landing.html (a static landing page)
Requests to anything else are served by my React app
Using create-react-app, and based on webpack-dev-server's options, I've set up my webpackDevServer.config.js as follows:
historyApiFallback: {
// Paths with dots should still use the history fallback.
// See https://github.com/facebookincubator/create-react-app/issues/387.
disableDotRule: true,
rewrites: [
// shows views/landing.html as the landing page
{ from: /^\/$/, to: 'landing.html' },
// shows views/subpage.html for all routes starting with /subpage
{ from: /^\/subpage/, to: 'subpage.html' },
// shows views/404.html on all other pages
{ from: /./, to: '404.html' },
],
},
And when I start webpack here's what I see:
Requests to /subpage are routed correctly to subpage.html
Requests to /foo are routed correctly to 404.html. Eventually, these would be handled by my React app.
Requests to / are routed incorrectly to my React app.
How can I get landing.html to respond to requests at /?
I ended up opening a bug request with webpack-dev-middleware and discovered it was not a bug but a failure of configuration.
Specifically, the issue is using HtmlWebpackPlugin alongside historyApiFallback. I believe plugins are processed before the regex matching, and HtmlWebpackPlugin's default file output is index.html; this means that out of the box, / will always be routed to the HtmlWebpackPlugin output file.
The solution to this is to set a custom filename in HtmlWebpackPlugin, which allows you to control the matching again. Here's a sample repo demonstrating the fix and here's the webpack config:
module.exports = {
context: __dirname,
entry: [
'./app.js',
],
output: {
path: __dirname + "/dist",
filename: "bundle.js"
},
devServer: {
publicPath: "/",
// contentBase: "./public",
// hot: true,
historyApiFallback: {
// disableDotRule: true,
rewrites: [
{ from: /^\/$/, to: '/public/index.html' },
{ from: /^\/foo/, to: '/public/foo.html' },
{ from: /(.*)/, to: '/test.html' },
],
}
},
plugins: [
new HtmlWebpackPlugin({
title: "Html Webpack html",
hash: true,
filename: 'test.html',
template: 'public/plugin.html',
}),
],
};
Two thoughts come to mind:
What you want to do is not possible with Webpack Dev Server (as far as I'm aware)
And, once npm run build is run and deployed the deployed app would not follow the same rules as configured in Webpack Dev Server
Even if I'm mistaken on #1, #2 seems like a bigger issue if you ever plan to deploy the app. This leads me to recommend an alternate setup which will work on dev and production (or wherever it's deployed).
A few options:
setup the app as a single-page app (SPA) and use React Router to serve the static routes (/ and /subpage) and wildcards (everything else)
setup node (or another server) to serve the static routes (/ and /subpage) and wildcards (everything else)
An Attempt
In an attempt to setup the routes I was able to achieve this setup:
Display landing.html when / is requested
Display subpage.html when /subpage is requested
Display the React App at a specific path, like app.html
To do this make the following changes:
Move /public/index.html to /public/app.html
mv ./public/index.html ./public/app.html
In /config/webpackDevServer.config.js, update historyApiFallback to:
historyApiFallback: {
// Paths with dots should still use the history fallback.
// See https://github.com/facebookincubator/create-react-app/issues/387.
disableDotRule: true,
rewrites: [
// shows views/landing.html as the landing page
{ from: /^\/$/, to: "landing.html" },
// shows views/subpage.html for all routes starting with /subpage
{ from: /^\/subpage/, to: "subpage.html" },
// shows views/app.html on all other pages
// but doesn't work for routes other than app.html
{ from: /./, to: "app.html" }
]
}
In /config/paths.js update appHTML to:
appHtml: resolveApp("public/app.html")
In /config/webpack.config.dev.js, updateplugins` to include:
new HtmlWebpackPlugin({
filename: "app.html",
inject: true,
template: paths.appHtml
})
Requesting a random URL, like localhost:3000/foo will return a blank page but contains the HTML from the app.html page without the bundled <script> tags injected. So maybe you can find a solution to this final hurdle.

Resources