How to Merge React App into existing Website with existing HTML structure - html

We have a <html> file stored on AWS S3. The file contains header and footer information.
This file has it's own build pipeline, we collect some data from a database and generate the HTML and upload to S3.
We would now like to include a bundled React App into this HTML page. I.e. within the body of the page will be the bundled react application.
The React App is built on the latest create-react-app setup and therefore, babel and webpack are pre-configured. The react build creates all the relevant files if the app was hosted without the above setup.
Is there a way to merge the two pages?
**Notes: Specifically looking for a merge as part of the build process. **
We have one project that generates a header html and publishes it onto an S3.
We have triggers that might trigger this to regenerate at specific times/after changes etc.
We have a React App that is bundled with babel/webpack in a production build and produces the output HTML/bundle js etc. All minified and hashed, so the file names are bundle.randomhash.js etc.
We need to merge the two outputs. The html file from S3 needs to include the React App within its body/html.
Ideally in a pipeline/build process. So if one changes, the merge is re-compiled/re-run.

I think you are looking for an automatic way of merging two outputs, one being your existing HTML with header and footer generated from your existing build process and triggered via a database.
The second being your react app which is a well finished final output that comes out of your create-react-app build infrastructure.
In such a case, I would recommend to use this very popular tool called gulp-inject. gulp-inject takes a stream of source files, transforms each file to a string and injects each transformed string into placeholders in the target stream files.
An example is given below:
Let's say your target file is called index.html like this
<!DOCTYPE html>
<html>
<head>
<title>My index</title>
<!-- inject:css -->
<!-- endinject -->
</head>
<body>
<!-- inject:js -->
<!-- endinject -->
</body>
</html>
Your gulpfile.js script would look like this to achieve a new index.html with new insertions automatically based on this script.
var gulp = require('gulp');
var inject = require('gulp-inject');
gulp.task('index', function () {
var target = gulp.src('./src/index.html');
// It's not necessary to read the files (will speed up things), we're only after their paths:
var sources = gulp.src(['./src/**/*.js', './src/**/*.css'], {read: false});
return target.pipe(inject(sources))
.pipe(gulp.dest('./src'));
});
Your final output of your index.html would look like this after running gulp index:
<!DOCTYPE html>
<html>
<head>
<title>My index</title>
<!-- inject:css -->
<link rel="stylesheet" href="/src/style1.css">
<link rel="stylesheet" href="/src/style2.css">
<!-- endinject -->
</head>
<body>
<!-- inject:js -->
<script src="/src/lib1.js"></script>
<script src="/src/lib2.js"></script>
<!-- endinject -->
</body>
</html>
The basics of converting an existing HTML file and inserting it with ReactJS code is given below. I think if you apply these principles and use the gulp-inject tool, you can achieve wonders.
https://reactjs.org/docs/add-react-to-a-website.html
Your exact build automation maybe driven by your own tool such as Jenkins or such similar tools where you could chain one event with the other. For example, you could check whenever a new HTML file is automatically generated by your Database Triggering on AWS and once that event is received, you could trigger either the Gulp-Inject script if you already have the React Component(s) ready or trigger the Create-React-App to freshly build the React Component and then apply the Gulp-Inject script to inject your React Component or React Code into the index.html or whatever the name of your html page.
The npm package for gulp-inject can be found here.
https://www.npmjs.com/package/gulp-inject
Hope this helps. Let me know.
If you like the answer, you can accept it.

To do this you need to host your js, css, and media files from your react build folder in an S3 bucket and add the following to the code.
<html>
..... your static html code
<div id="the id used to bootstrap your react app (from the index.html file in the public folder)"></div>
......
links to all the files in your JS, CSS And media files from the react build folder
</html>
I would suggest to use hosted images (you can host them on S3 as well) and assets as much as possible so you don't need to add the media file links on by one in the html file.
You may want to look at this link on how to bundle all files into one file when building your react app (I haven't tried this part).

Related

How to consume css in index.html from the endpoint path that returns the css file?

My frontend app is running at port http://localhost:3000.
I have an endpoint that returns the css file for specific id(i.e. 88871) as following:
http://localhost:8080/api/getCssFile/88871
I need to add this css file dynamically to head of the index.html file as follows:
let cssUrl = "http://localhost:8080/api/getCssFile/" + id;
let link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.setAttribute('type', 'text/css');
link.setAttribute('href', cssUrl);
document.head.appendChild(link);
This will add following code to head of the index.html file.
<link rel="stylesheet" type="text/css" href="http://localhost:8080/api/getCssFile/88871" />
All looks good. However, Css is not being reflected in the webpage. Css file will be downloaded when this link is clicked instead.
http://localhost:8080/api/getCssFile/88871
Am I missing anything here?
I tried loading css from the api however, the css is not being reflected in the webpage.
The reason your approach is not working is that you are loading the CSS file through JavaScript which runs after your document has already been loaded, so the document does not know about the link as it has already been "painted" by the browser.
I'm not sure why you've chosen the path of having a backend service return a CSS file, but my advice would be to avoid that. If you want shared styling that updates periodically consider creating a NPM library that exposes the stylesheet and consume that within your app.

How to add static resources in spring with thymeleaf

I am new to Spring and I am trying to make a beautiful Web Application, and so far I set up everything, and if I run my page on the browser it shows as it is supposed. But if I run it with tomcat on port 8080 (I am using Intelijj) it doesn't load css and js files not even pictures.
I have literally searched this problem and open all the StackOverflow similar questions, I tried to write a configuration file, but it doesn't do anything, and I am uncertain about this approach because I have seen examples of people that did not write any configuration, but still they managed to make all their static resources load, and so on. Is it some secret application properties that need to write? Or there is a config code that has to write?
My resources folder looks like this:
-resources
-static
-CSS
-things.css
-JS
-datepicker.js
-Images
-many pictures
-templates
-Home.html and other pages
And the code that I used to refer to static-CSS-things.css is like this:
link href="../static/CSS/things.css" th:href="#{/CSS/things.css}" rel="stylesheet" media="all" type="text/css"
I thought this would make my css file to load, but it doesn't. Same for the js and the pictures. Thank you!
Ensure your css and js files are in the following structure:
src/main/resources/static/css/things.css
src/main/resources/static/js/things.js
Ensure you are calling your static resources from pages that are under the spring boot template folder, which is in src/main/resources/templates
Always refer to your resources using the thymeleaf tag, because this way no matter the port you are running your application, it will always load properly.
src/main/resources/templates/example.html
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<!-- CSS -->
<link th:href="#{/css/things.css}" rel="stylesheet"></link>
<!-- JS -->
<script th:src="#{/js/things.js}" type="text/javascript"></script>
</head>
<body>
</body>
</html>
If still not working, try to use the inspect from Google Chrome, go to Network tab and check what error is returning from your css and js files, then comment here.
Assuming you have css and js folder under static folder then use it like this -
<link href="css/custom.css" rel="stylesheet">
<script src="js/custom.js"></script>
you might wanna take a look at these too -
https://www.springboottutorial.com/spring-boot-with-static-content-css-and-javascript-js
https://www.baeldung.com/spring-mvc-static-resources
Worth noting, make sure you have thymeleaf dependency(ies) and tags appropriately.

How to render a React component with a express router?

So I have began my project as a React single page application. But it turns out it would be more convenient to have a basic back-end for rendering the pages and have a real routing.
Plus I have some variables that need to be accessible from all pages, and putting them as props to all the components is really heavy. So sending them with the pages could be a solution.
So I added Express, and I can now render a basic HTML page with it.
But I don't know how I am going to link my react component to this html file. Or pass it the needed variables.
I used react-router-dom but it doesn't support page refreshing. And it doesn't help with having global variables needing to be accessible from all components.
Here in my index.js you can see how I render my basic html file, and also at the end and commented, how my react component was rendered before adding express.
app.use(express.static('public'));
router.get('/', function(req, res, next) {
res.sendFile('./public/views/loginView.html' , { root : __dirname});
});
app.use(router);
app.listen('8080');
// const wrapper = document.getElementById("app");
// wrapper ? ReactDOM.render(<App />, wrapper) : false;
Here my loginView.html
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<!-- links and scripts -->
<title>The login page</title>
</head>
<body>
<div id="app">
content
</div>
</body>
</html>
Is there a simple way to link my html file with its react component and render it ?
If not, is there another way to make some variables (which are not constants) accessible from every react component (maybe react-redux) ?
So with React you want to create a production ready bundle. This normally involves splitting the bundle up so you aren't serving a 5+Mb file to the user to download (using 4G for example with poor connection would take too long) and minifying and uglifying the code (so no one steals your code). These bundled javascript files would then be hosted on your server with reference to them in the HTML file.
The express app would then go along the lines off any route just display the HTML file e.g. router.get('*', (req, res) => res.send('index.html)).
I would recommend using webpack to create the bundle as it helps with the splitting and minifying etc. Take a look at webpack for development and production aswell as create-react-app for quick project setup.

Bootstrap minified css only loads if I import it in index.js

So, I was using the BootstrapCDN loader up until now, but I would like to just download the files and use them locally without relying on my internet connection, but the styles won't load. I only need the grid by the way.
I am using reactjs with material ui and bootstrap's grid -> project structure
I changed the stylesheet link and script to point to my files and I also changed the jQuery and Popper.js tags accordingly.
CSS
from
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"...>
to
<link rel="stylesheet" href="../src/bootstrap/sources/css/bootstrap.min.css">
JS
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"
now:
<script src="../src/bootstrap/sources/js/bootstrap.min.js"></script>
and the same thing with
<script src="../src/bootstrap/jquery-3.2.1.slim.min.js"></script>
<script src="../src/bootstrap/popper.min.js"></script>
while the link to bootstrap.min.css is in the <header> and all the others being in the <body> tag.
The grid doesn't work and everything is messed up. But if I include an import './bootstrap/sources/css/bootstrap.min.css'; in my /src/index.js file - the file where I have my private routes to certain pages - the grid actually works.
If I changed it back to cash bootstrap's css from the BootstrapCDN and specify the link as it was before, I don't have to include that import and the grid works flawlessly.
Am I doing something wrong?
EDIT: chrome shows the css file and all the js file being loaded with code 304 - not modified in the network tab
First of all: there's nothing wrong in keeping the CSS import in your JS file... what's wrong with it?
This is a common way to go in React.
About your specific issue: You are referring to a not existent file like ../src/bootstrap/jquery-3.2.1.slim.min.js. This because this path is valid in your source, but not in the final bundle.
If you are using create-react-app for example, you should put your resources (the bootstrap folder) in the public folder instead, so the used URL should be something like "/bootstrap/jquery-3.2.1.slim.min.js".
Even better: use the %PUBLIC_URL% variable.
See https://facebook.github.io/create-react-app/docs/using-the-public-folder

Local References to CSS and JS files for Leaflet MarkerCluster plugin not loading

Currently, I'm using the cdnjs from cloudflare to reference the MarkerCluster plugin js and css files for leaflet, and it works fine. However, when I try and reference the local version I downloaded from the github page and reload my html page, the markerclusters go away. Here are my references:
<link rel="stylesheet" type="text/css" href="Leaflet.markercluster-master/Leaflet.markercluster-master/dist/MarkerCluster.css" />
<link rel="stylesheet" type="text/css" href="Leaflet.markercluster-master/Leaflet.markercluster-master/dist/MarkerCluster.Default.css" />
<script src="Leaflet.markercluster-master/Leaflet.markercluster-master/src/MarkerCluster.js"></script>
I have checked and rechecked the file paths and I can confirm they are correct. I've referenced both MarkerCluster.css and MarkerCluster.Default.css because that was recommended when I reference through cdnjs. I've made sure to redownload the latest version from github, still to no avail.
I've added and deleted type="text/javascript" from the script that runs the js file, but that didn't help either:
<script type="text/javascript" src="Leaflet.markercluster-master/Leaflet.markercluster-master/src/MarkerCluster.js"></script>
I am referencing these files within the <head> of the html file. Any help would be greatly appreciated!
Reasoning:
I would like to reference the local files so that it can act as a backup in case the cdnjs goes down. I know that this has very rarely happened, if ever. But for this project, we are concerned with maintaining this site for a long time and want to ensure the maximum amount of protection against plugins breaking/becoming incompatible.
The MarkerCluster.js file you have downloaded is just a part of the source code of the plugin.
It is concatenated with other source files to produce the dist file that is available on public CDN's.
See the disclaimer on the repository: https://github.com/Leaflet/Leaflet.markercluster/blob/master/dist/WhereAreTheJavascriptFiles.txt
We don't ship the .js files in the git master branch.
They are only present in version tags and in npm.
See how to get the JS files here: https://github.com/Leaflet/Leaflet.markercluster#using-the-plugin
Or how to build them: https://github.com/Leaflet/Leaflet.markercluster#building-testing-and-linting-scripts
A very simple mean to retrieve this dist JS file is to download what you get from the CDN. E.g. paste the URL in your browser address bar; this should display the raw content of the file. Then right click anywhere on the code and select "Save as..."
If you look in dist/WhereAreTheJavascriptFiles.txt you'll see that if you download the source you need to build the dist js files with jake. Or just use the CDN. The js file you've included is part of the source codebase.