Reputation: 332
My React app throws 404 errors
in production when accessing static files (stylesheets, utilities, and more). The development environment works fine. After debugging for several days and further research I believe it's a webpack pathing issue as my understanding of build path and webpack.output
is still lacking despite my research on webpack.js.org. After referencing other posts, I still can't grasp this final concept for bundling applications. All help is appreciated. See below for Things tried, and Posts referenced, and Notes for my process. Thank you.
Things tried:
Added "homepage" property in package.json pointing to "https://my_ghub_username.github.io/project_repo/"
Changed "homepage"
property to "."
Changing React router to <HashRouter/>
ensuring it imported correctly.
Pushed my latest changes to main before deploying my app to GH pages again
Added package.json
scripts to pre-deploy
, deploy
, && build
Posts/Guides Referenced
I attached snippets of relevant code package.json
(I), webpack.dev/prod/common.js
(II), index.html
(III), file tree(IV), and errors(V) in chrome tools.
(I)
{
"name": "digital-nomad",
"version": "1.2.2",
"description": "An immersive experience to experience life in major cities!",
"main": "index.jsx",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"predeploy": "npm run build",
"deploy": "gh-pages -d dist",
"build": "webpack --config webpack.prod.js",
"start": "webpack serve --config webpack.dev.js"
},
"homepage": ".",
"dependencies": {
"@babel/core": "^7.12.3",
"@babel/preset-env": "^7.12.1",
"@babel/preset-react": "^7.12.1",
"babel-loader": "^8.1.0",
"clean-webpack-plugin": "^3.0.0",
"gh-pages": "^3.1.0",
"googleapis": "^64.0.0",
"inline-source-map": "^0.6.2",
"mini-css-extract-plugin": "^1.3.2",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"react-redux": "^7.2.1",
"react-router-dom": "^5.2.0",
"redux": "^4.0.5",
"webpack-cli": "^4.1.0",
"webpack-merge": "^5.4.1"
},
"devDependencies": {
"css-loader": "^5.0.0",
"eslint-plugin-react-hooks": "^4.2.0",
"html-webpack-plugin": "^4.5.0",
"style-loader": "^2.0.0",
"webpack": "^5.2.0",
"webpack-dev-server": "^3.11.0"
}
}
(IIA)
const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
contentBase: './',
compress: true,
open: true,
port: 8080,
watchContentBase: true,
historyApiFallback: true,
}
})
(IIB)
const { merge } = require('webpack-merge')
const common = require('./webpack.common.js')
module.exports = merge(common, {
mode: "production",
devtool: "source-map",
})
(IIC)
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const HTMLWebpackPluginConfig = new HTMLWebpackPlugin({
title: 'Production',
template: __dirname + '/index.html',
filename: 'index.html',
inject: 'body',
favicon: "favicon.png"
})
module.exports = {
entry: path.resolve(__dirname, "src", "index.jsx" ),
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
publicPath: './'
},
module: {
rules: [
{ test: /\.jsx?$/, exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
options: { presets: ['@babel/env', '@babel/react'] }
},
},
{ test: /\.css$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: { publicPath: '../' }
},
'css-loader'
],
}
]
},
plugins: [
new CleanWebpackPlugin(),
new MiniCssExtractPlugin(),
HTMLWebpackPluginConfig
],
resolve: {
extensions: [".js", ".jsx", ".css", "*"]
},
performance: {
hints: false
},
stats: {
errorDetails: true,
warnings: true,
colors: true,
},
};
(III)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="favicon.png">
<!-- youtube video API -->
<script rel='preload' src="https://www.youtube.com/iframe_api"></script>
<!-- youtube data API -->
<script rel='preload' src="https://apis.google.com/js/api.js"></script>
<script defer src="./src/utils/YTVideoAPI.js"></script>
<script defer src="./src/utils/YTDataAPI.js"></script>
<script src="/dist/bundle.js"></script>
<link rel="stylesheet" type="text/css" href="./src/stylesheets/player.css">
<link rel="stylesheet" type="text/css" href="./src/stylesheets/root.css">
<link rel="stylesheet" type="text/css" href="./src/stylesheets/controls.css">
<title>Digital Nomad</title>
</head>
<body>.
<div id="root"></div>
</body>
</html>
(IV)
(V)
GET https://username.github.io/project_name/src/stylesheets/player.css net::ERR_ABORTED 404
Note
I tried my hand over the past couple of days with alternative solutions like utilizing a 404 page to redirect to my app while still using Browser router
as a potential solution but not understanding this last aspect of webpack is killing me since I know I can use webpack to my advantage. ( I really want to better conceptualize webpack pathing to improve existing apps ).
Lastly, any feedback on code quality, convention, and implementation is extremely welcome.
Upvotes: 2
Views: 1278