How to properly serve the create-react-app index from the server? - javascript

I'm developing an application with create-react-app and all is going well, except for the fact that I would like to initially serve the index.html from the backend, and am running into trouble doing so.
The reason that I want to do this is so that I can inject some user-specific Javascript into the index.html page and also run various other queries when the user initially hits the page (similar to this person)
So, instead of connecting to localhost:3000 to view the app, I would instead connect to localhost:8080 and have the server serve this index.html file. (all other assets (js, css, images) would still be on localhost:3000)
One issue with doing this seems to be that the script tags are not included in the index.html file by default, and are instead generated by create-react-app. That is, say this is my index.html file:
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
</head>
<body>
<div id="root"></div>
</body>
</html>
If I run npm start, and then inspect the source, it will instead be this (due to CRA runtime injections I presume):
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="shortcut icon" href="/favicon.ico">
</head>
<body>
<div id="root"></div>
</body>
<script src="/static/js/bundle.js"></script><script src="/static/js/0.chunk.js"></script><script src="/static/js/main.chunk.js"></script>
</html>
As a result, on the server, I'm currently trying something like this:
#[get("/")]
fn handle_index() {
let scripts = r#"<script src="https://localhost:3000/static/js/bundle.js"></script>
<script src="https://localhost:3000/static/js/0.chunk.js"></script>
<script src="https://localhost:3000/static/js/main.chunk.js"></script>"#;
let index_html = include_str!("../frontend/public/index.html");
let document = format!(r#"<script type="application/javascript">
window.APP_GLOBALS = { user_id: 5, color: "red" };
</script> {}{}"#, data, index_html, scripts);
return document;
}
Because I'm not sure of any other way to inject those script tags. It looks like create-react-app only does it for my localhost:3000 page, and not the localhost:8080 page.
This seems to somewhat work. That is, the page loads, but there are two issues.
Many of the asset URLs are now wrong. They are instead pointing to localhost:8080 instead of localhost:3000, and %PUBLIC_URL% URL likewise doesn't work (I suppose this is another process that is no longer occurring)
The websocket autoreload dev server no longer works. It works when I navigate to localhost:3000, but not localhost:8080. When I edit a file and save, the page just turns white with no errors in the console.
I think all of these issues are due to the same cause: create-react-app normally preprocesses the index.html file in some way (converting %PUBLIC_URL%, adding those script tags, handling reload), but it is no longer doing this when the file is instead returned from the server.
What I'm wondering is how I can restore this functionality. Basically, have these script tags and %PUBLIC_URL% processes occur without my backend server having to attempt to do so.

When you run npm start, you are telling CRA to make a development build using webpack. Webpack does all of the processing you see like injecting scripts and replacing %PUBLIC_URL%. You don't want your backend to serve the index.html in the public folder because that file hasn't been processed by webpack. Instead you need the backend to serve webpack's build output.
The npm start configuration is a development build, which is good for development but not production. (Also it doesn't save its output to the file system, so you couldn't even serve it from your backend if you wanted to. See CRA issue #1070). If you run npm run build, you get a production build in the build folder, which you should serve from your backend (and then you can make whatever injections you need).
The downside of this is that it takes longer to build, it doesn't rebuild automatically when you change your frontend files, and I'm not sure if the errors it gives are as useful as npm start. Thus you might want to use npm start when developing the frontend and npm run build when testing your backend. There are also certain projects like patch-package that would allow you to make npm start's build output stay in the file system so you can serve it, but I haven't tried any of them.
BTW - be careful with injecting scripts into the html from your backend. Consider something like setting cookies in your backend and reading those cookies in your frontend instead. This is safer, easier to debug, etc.

Related

Facing problem while exporting static html with next js

I'm a newbie in react. I've done a project and for static HTML export, I used "next build && next export" in package.json, and npm run the build command. It also gives me an out folder. The problem is when I try to access HTML files from our folder locally and with a live server, It shows only HTML content without CSS and js.
I tried many ways but can't figure out the problem.
If anyone helps me with this, I'll be very very thankful to him.
Thanks in advance.
next export allows you to export your Next.js application to static HTML, which can be run standalone without the need of a Node.js server. It is recommended to only use next export if you don't need any of the unsupported features requiring a server.
If you're looking to build a hybrid site where only some pages are prerendered to static HTML, Next.js already does that automatically
I have faced same problem.
In my case, Changing src value solved the problem.
Here is the exact steps.
build your project
inside build folder there's index.html
change <script src="/static/js/12345.js"> to <script src="./static/js/12345.js"> (add "." before "/")
Do same thing to <link href="/static/css/main.b57f21b0.css" rel="stylesheet"> and <link rel="icon" href="/favicon.ico"/> and <link rel="manifest" href="/manifest.json"/> and other file structure string if exists.
You solved the problem.

Problem pubishing in JBOSS, links to files (images, subpages) HTML with aboslute path redirect to / instead APP

I got an EAR file, I try to deploy and It deploys fine, without error. The problem is the following:
All the ccs files, images, files, etc are using absolute paths in the HTML files, (the HTML files are being generated through an external program so change to relative paths is not an option), so the styles are not being loaded, the links to other pages don't work, etc.
An example to clarity:
I have the ear deployed in "localhost:8080/app, the index.html file loads but inside the file, I try to use the link to the page2.html, and the path is localhost:8080/page2.html instead "localhost:8080/app/page2.html".
The browser says "the page cannot be loaded"
How can I fix this without change the paths to relative? I have the context root of application.xml with "app" and the welcome file of web.xml inside the war file with "index.html".
the structure is the following:
file.ear
meta-inf
file.war
web-inf
index.html
css folder
pageX.html
I beg for help.
Thanks in advance.
First you need to know understand, how file system works in web.
<link rel="stylesheet" href="slick.css"> // file present in same folder
<link rel="stylesheet" href="css/slick-theme.css"> // file present in css folder of current folder
<link rel="stylesheet" href="/css/slick-theme.css"> // file present in the css folder at the root directory of the current web
<link rel="stylesheet" href="../slick-theme.css"> // file present at one level up the current folder
Since all your files path starts with /, server tries to find it relative to the root directory.
All you need is to deploy your app as root app without any context-root.
This will require 2 things:
1)
<context-root>/</context-root>
2) configuration change at server level, remove default content mapping, try to find
<location name="/" handler="welcome-content"/>
(may vary in your jboss version) and comment it.
Attaching screenshot of your working app:
PS: Delete your EAR from repo or make it private
Deploy your app as ROOT.war
You might also need to tweak your server config to allow this if you keep seeing the server welcome page
If you can't bind the app to / and you can't change the file paths referenced in the app, then the only option would be to use a proxy infront of the sever, something like nginx, so you make the requests to the proxy and it passes the request on to http://appserver/app/

Jquery won't load

So hey guys, I'm trying run a html file for this angular 2 course I'm taking. After creating the dependancies for the app I downloaded them with npm. Now when I try to run the app, I get this error..
file:///Users/Rocky/Angular2-course/skeleton/node_modules/jquery/dist/jquery.min.js
Failed to load resource: net::ERR_FILE_NOT_FOUND
This is how I wrote the jquery script..
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script src="node_modules/tether/dist/js/tether.min.js"></script>
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
If your'e using Angular, you want to try and avoid using jQuery since Angular comes with jqLite.
Try to the version of Bootstrap made for Angular 2.
Check out https://ng-bootstrap.github.io/#/getting-started
Also, ever though of linking them?
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"></script>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
If your files are in "./node_modules/jquery/dist/". Then, the script tag in your pages just looks like this:
<script src="/scripts/jquery.min.js"></script>
If you were using express with nodejs, a static route is as simple as this:
app.use('/scripts', express.static(__dirname + '/node_modules/jquery/dist/'));
Then, any browser requests from /scripts/xxx.js will automatically be fetched from your dist directory.
Note: Newer versions of NPM put more things at the top level, not nested so deep so if you are using a newer version of NPM, then the path names will be different than indicated in the OP's question and in the current answer. But, the concept is still the same. You find out where the files are physically located on your server drive and you make an app.use() with express.static() to make a pseudo-path to those files so you aren't exposing the actual server file system organization to the client.

Failed to load resource error when loading external scripts

I'm trying to load external scripts from a folder into my createnew.html file and I keep getting this error saying it cannot be found:
Failed to load resource: the server responded with a status of 404 (Not found)
I'm trying to load the scripts in the head of my code, like this:
<head>
<!--C3 CSS script-->
<link href="./scripts/c3.css" rel="stylesheet" type="text/css">
<!--C3 JS script-->
<script src="./scripts/c3.min.js"></script>
</head>
My files are arranged like this:
->public
->views
-createnew.html
->scripts
-c3.css
-c3.min.js
Please help me understand why this doesn't work.
As this question became more popular than expected, I decided to point other problem-havers in the right direction:
Let's say you have organized your files like this:
- server.js
-> MyWebsite(folder)
- index.html
-> js(folder)
- myscript.js
The paths you use are relative to the "working directory" you are in.
When not using a server, and only developing websites locally on your computer, this working directory will be the relative path from your index.html file to your scripts. In this case it would be ./js/mysript.js.
When using a server you need to tell it where this working directory is. In the case of Node.js you would do something like this app.use(express.static('./MyWebsite')) and your js files would be referenced by /js/myscript.js
Notice that when loading from a server you prefix with / instead of ./ since the / really is just a part of the URL to your file hosted by your server, while ./ is specific to the file system.
Change
"./scripts/c3.css"
to
"scripts/c3.css"
You can refer to this question about the relative path of files in HTML.
To refer to the current folder,
./ works only in non-strict doctype mode, while . works in both modes.
So you may try "scripts/c3.css" instead of "./scripts/c3.css"

How can I correct the Meteor base-url in a NginX reverse-proxy configuration?

I have installed both Apache and Meteor behind NginX through reverse-proxy (on an Ubuntu server). Apache is mapped directly as baseURL (www.mydomain.com/) and Meteor is mapped as a subfolder (www.mydomain.com/live/).
The problem I encounter is that my Meteor test (which works as expected at port 3000) stops working behind NginX since every single references (CSS, Javascript, template) are absolute to baseURL.
<html>
<head>
<link rel="stylesheet" href="/live.css?abc">
<script type="text/javascript" src="/packages/underscore/underscore.js?efg"></script>
...
<script type="text/javascript" src="/template.live.js?hij"></script>
<script type="text/javascript" src="/live.js?klm"></script>
</head>
Obviously, since Apache is mapped at baseURL, these files are not found when testing through NginX.
What would be the best way to resolve to problem? System Administration is not my forte, and Meteor is my first incursion at server-side javascript. So I don't even know if this can be fixed, and if so, if it's done through a server configuration, Meteor configuration or programmatically.
EDIT: The new "absolute-url" package in Meteor 0.4.0 fixed the problem!
http://docs.meteor.com/#absoluteurl
The new "absolute-url" package in Meteor 0.4.0 fixed the problem.
http://docs.meteor.com/#absoluteurl
Why are you including scripts and styles in your <head> with Meteor? Anything included within your meteor project directory, be it js, html or css, will get bundled up and served to the client without being included in your HTML with <link> and <script>.
If you must include things in your <head>, why not just use the absolute path including the subfolder?
<html>
<head>
<link rel="stylesheet" href="/live/live.css?abc">
<script type="text/javascript" src="/live/packages/underscore/underscore.js?efg"></script>
...
<script type="text/javascript" src="/live/template.live.js?hij"></script>
<script type="text/javascript" src="/live/live.js?klm"></script>
</head>
Forgive me if I'm misunderstanding the problem.

Categories

Resources