Originated from a failed project deployment
The project I deployed here is the one built in my previous article "Manually Setting Up a React Development Environment." Today, when trying to deploy the package to Tencent Cloud, I encountered some issues.
There is already a project deployed at the root path of this server. This time, the project being deployed is an independent one intended for embedding into other applications, so I planned to deploy it under the /a/b path.
I directly copied the existing path configuration and modified it as follows:
shell
By the way, for single-page applications using history routing, the above try_files needs to be configured so that nginx loads the entry file when the corresponding path resource cannot be found.
Create the directory for the corresponding project in nginx and upload the packaged files into it. Then access the project via /a/b.
As a result, the page rendered:
Unexpected Application Error!
404 Not Found
Opening the console, there were no errors, and resources loaded normally. To confirm it was a React error, I copied Unexpected Application Error! and searched in the build files — indeed, it could be found, confirming this was a front-end React error.
This kind of vague error message feels very hard to troubleshoot. Sure enough, both Baidu and GPT failed to provide strongly relevant answers for "React Unexpected Application Error!".
I vaguely suspected it was a routing issue but couldn’t figure out where the problem lay, since my nginx configuration seemed fine and the previous project was deployed the same way.
So I tried changing the project’s routing mode to hash mode, and after deploying to the server, the project worked correctly. Looking at the routing configuration, I suddenly realized that the single-page application internally determines which page to render based on URL matching, and my project running with React couldn’t find the path /a/b.
Actually, we already had a solution in the previous step: use hash routing (if you and your users can tolerate the #).
Since our project is deployed under /a/b, our React routing needs to parse URLs based on this path. Modify our createBrowserRouter function:
js
By configuring the basename property, we set a base path so that in production, React Router can correctly parse our URLs (React Router v6). At the same time, by checking the runtime environment, we only set basename in production, keeping the development environment unchanged.
Modifying the routing configuration only makes the project run correctly at runtime; we also need to adjust the webpack build configuration so the project can load resources properly.
Modify the output option in webpack.prod.js:
js
Now all relative-path resources will be loaded based on this publicPath (though since the final packaged paths are all relative, adding or omitting it here doesn’t matter much).
After repackaging and redeploying, the project can now load normally under /a/b.
If you also want to start the project under a path like /a/b in the development environment, you need to modify the following configurations:
basename in createBrowserRouteroutput publicPath in webpack.dev.js to /a/b, so that your build output is served under the local server’s /a/b path.historyApiFallback configuration in webpack.dev.js:js
The official explanation is that enabling this setting will make the local server return the project’s entry file for all 404 responses. Since our entry file address is based on the /a/b path, we need to configure the entry file path accordingly.
Now we can debug the project under the /a/b path.