Deploy CRA to s3 and serve with express - reactjs

I want to deploy CRA bundles to s3 and serve from cloudfront. But index file should be express view (template, I want to add some data to it). All solutions I've found assume serverless or serve CRA index directly from node.
So, I need index to be template and contain cloudfront URLs to bundles. How can I achieve this?

If you need to create and index.html you could do that without template
app.get('/', function(req, res) {
res.type('text/html');
res.send('<html>...</html>');
});
Or with templates like
Jade
doctype html
html
head
title Jade Page
link(href='https://cloudf../css/main.css', rel='stylesheet')
body
h1 This page is produced by Jade engine
p some paragraph here..
Source : https://www.tutorialsteacher.com/nodejs/jade-template-engine
Pug
html
head
title= title
link(href='https://cloudf../css/main.css' rel='stylesheet')
body
h1= message
app.get('/', function (req, res) {
res.render('index', { title: 'Hey', message: 'Hello there!'});
});
https://scriptverse.academy/tutorials/nodejs-express-pug.html
https://stackoverflow.com/a/38047123/3957754

Related

How does express serve index.html for React App and how do I modify it?

I'm an express noob here and building a React App with server using express and client using create-react-app.
What I want to do
I want to update the title and meta tag in the index.html.
So browser requests url -> Server gets request and adds the title and tag to the index.html -> return it to the browser.
Listed my code here
...
app.use(bodyParser.json())
app.use(aMiddleware)
app.use("/api/foo", bar)
app.use(express.static('client/build'));
if (process.env.NODE_ENV === 'production') {
const path = require('path');
app.get('/*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client', 'build', 'index.html'))
})
}
Questions
Code is functioning, but I don't know how to replace the title/tag in the index.html
How do I update/replace index for environment that is not prod?
Fo prod environment, I use path.resolve(__dirname, '../client', 'build', 'index.html'), then where is index.html for dev environment? I see there is an index.html in public folder, is it the one that got rendered for dev environment?
I tried to add this code before app.use(express.static(...))
app.get('/', function(req, res) => {
// maybe replace string in the index.html (though I don't know where is it
// then res.send(...)?
})
but this never got triggered. Why?
Stuck on this for a while, tried many things, any help would be great.
You can use react-helmet for this... Or switch to Nextjs which is server side.
https://www.npmjs.com/package/react-helmet

How do I rewrite all urls to index.html in Heroku?

My Heroku app is using React with React Router. I use Switch to navigate through different components, so the URL changes as well (e.g. /room/4141). However, if I reload the page, it doesn't act like if it was a React app, but instead it searches for the mentioned .html file.
I used this Buildpack: https://github.com/mars/create-react-app-buildpack.git but it seems to do nothing in regards with pages being rewritten to index.html.
Is there a way to prevent this behaviour and rewrite all URLs to index.html?
**EDIT:
I'm not familiar enough with express, but here's how the index.html is served.
const express = require("../../node_modules/express");
const app = express();
const server = require("http").Server(app);
const io = module.exports.io = require('../../node_modules/socket.io/lib')(server)
const path = require("path")
app.use(express.static(path.join(__dirname, '../../build')));
if(process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, '../../build')));
console.log("DEBUG HERE", __dirname, path.join(__dirname+'../../build'));
//
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname+'../../build/index.html'));
})
}
//build mode
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname+'../../public/index.html'));
})
That buildpack can be configured via a JSON file:
You can configure different options for your static application by writing a static.json in the root folder of your application.
One of the sample routing configurations looks like it does exactly what you want:
When serving a single page app, it's useful to support wildcard URLs that serves the index.html file, while also continuing to serve JS and CSS files correctly. Route ordering allows you to do both:
{
"routes": {
"/assets/*": "/assets/",
"/**": "index.html"
}
}

File serving using ngRoute in Angular with NodeJS server

I am trying to run AngularJS, using Angular Router, with a NodeJS server. I do not plan on serving the various views in Node, but instead I want to use the angular router. This first page is served correctly with no errors but when I try to click on another link, the browser displays the following
error code. Below is the relevant code from the server script, the routing script, and where the link in the HTML is.
HTML Link
<li>Add Workout</li>
Server.js
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname + '/public/app/views/home.html'));
});
app.use(express.static('public'));
App.js
var app = angular.module("fitness2Uapp", ["ngRoute"]);
app.config(function($routeProvider) {
$routeProvider
.when("/", {
templateUrl : "./app/views/home.html"
})
.when("/browse", {
templateUrl : "./app/views/browse.html"
})
.when("/add", {
templateUrl : "./add.html"
})
.when("/workout", {
templateUrl : "./app/views/workout.html"
});
});
Try putting in a "catch all" route that just redirects back to the main page. This will in turn allow the angular routing mechanism to kick in. Right now the problem is that it's trying to find an endpoint path of '/add' on the node server, but nothing is found. This should be the very last route established on your server.
I personally use AngularJS and had to do this, and everything works great. Not sure if this will also perform the same way as Angular2+
// Catch all if all other routes fail to match.
app.get('*', (req, res) => {
res.sendFile(path.resolve(`${__dirname}/path/to/home.html`));
});

Render html in angular js app from express js

I am using angular on the front end and express js MongoDB on the backend, in server.js file of express application I am listening on port 3000
var server = app.listen(3000, function () {
console.log('Server listening at http://' + server.address().address + ':' + server.address().port);
});
What I want is when I hit localhost:3000 my HTML page in angular js application should get render, which I achieved using
app.get('/', function (req, res) {
res.sendfile(__dirname + '/app/userlogin/userlogin.html');
});
When I hit localhost:3000 my HTML page is getting render but it is not including bootstrap files I am getting error 404 for scripts and links which I am adding in head tag but intelligence of vs2015 providing those bootstrap script files when I am trying to add them in my HTML, Following is my project structure and I have placed my bootstrap js and CSS files respectively in app -> js and app -> CSS
You need a public_static folder containing all your frontend code.
The express app should serve it with express.static('')
server.js
app.use(express.static('public_static'));
Directory Structure
-- server.js
-- public_static
-- index.html ( Rename your userlogin.html )
-- css
-- JS ( Angular files )
--- controllers
--- directives
--- services

Can't get second level routes working in express

I'm sorry I'm reasonably new to node. I've been stuck on this for a couple hours.
server.js
app.use(express.static(__dirname + "/public"));
app.get('/', function(req, res){
res.sendFile(path.resolve(templatesPath + 'index.html'));
});
app.get('*', function(req, res){
res.sendFile(path.resolve(templatesPath + 'index.html'));
});
index.html is an Angular application. I have the first level of routes working fine using Angular's HTML5 routes eg. "http://lh:3000/staff" or "http://lh:3000"
but if I add another level or route parameters, e.g. "http://lh:3000/staff/" or "http://lh:3000/staff/test" Express seems to ignore express.static and instead uses the get wildcard to turn all my files into index.html so my page breaks.
Thanks for your help answerers
In secondary routes, it was loading assets referenced in index.html, relative to the secondary route. My temp solution is to add:
app.use('/files/',express.static(path.join(__dirname + "/public")));
but I realise now it is better to change my solution.
are staff/test, static assets sitting inside your assets folder?
If they are static assets, there must be a file in the path staff/test inside your assets folder.
if they are not static assets and they are dynamic content, consider using express.router,make a router for staff and add it as,
var staff = express.Router();
staff.use('/staff', staff)
//this is route handler for /staff/test
staff.post('/test', function(req, res, next){
res.json(some-json-content)
})
try this:
app.get('*/*', function(req, res){
res.sendFile(path.resolve(templatesPath + 'index.html'));
});

Resources