Serving webpack generated CSS file via CDN in Heroku CI environment - node.js

I have an Node.JS Meteor app that I bundle with webpack, that generates a CSS file with a hash in the name: [hash].bundle.css. I can set the publicPath to the CDN domain:
output: {
publicPath: 'https://xxx.cloudfront.com/',
},
On Heroku the bundle will be generated in the staging-environment and the generated slug will then be moved to the live-environment (including the css file).
When there is a change in the CSS, there will be a new hash in the staging-environment. When the site is opened (testing...) cloudfront will be asking the live-environment for that file, but the Node.JS-server responses with the app-HTML, that is issuing a not-found error on the browser.
Idea: Making the CDN fallback to staging
This is recommended in ther heroku documentation. But since the app-server does not respond with a 404 http error, cloudfront will not look at the staging server.
Problem: serving a 404 http error for missing files
This sound's not to difficult. Meteor webapp uses connect and I use FlowRouter on the client side, so I can:
WebApp.connectHandlers.use('/', function(req, res, next) {
if(FlowRouter.matchPath(req.url).route.name == 'not-found') {
res.writeHead(404);
res.end('Not found.');
} else {
return next();
}
});
But: there is many other connectHandlers that I would need to know, and make FileSystem checks. I tried going down that road, but it seems endless, maintenance intensive and not fail-proof.
Idea: Using Meteor's ?meteor_css_resource=1
There is a Meteor specific treatment of a css file with a query parameter xx.css?meteor_css_resource=1, but that won't be counting as a 404 error for the CDN to make the request to staging again.

Instead of checking all available connectHandlers, we filter just the .css files.
WebApp.connectHandlers.use('/', function(req, res, next) {
const urlParts = url.parse(req.url)
if(urlParts.pathname.endsWith('.css')) {
res.writeHead(404)
res.end('CSS file not found.')
} else {
return next()
}
}

Related

Heroku Node/React Deployment Routes Everything to index.html

I have an app.js node main file where I define my api path as the following
app.get('/api/users', UserController.get);
Below in the same file I have the following
app.use(express.static(path.resolve(__dirname, "./front/build")));
app.get("*", function (request, response) {
response.sendFile(path.resolve(__dirname, "./front/build", "index.html"));
});
The index.html successfully serves React App.
If I open my heroku app somewhere at my-app.herokuapp.com it will open the React app which is intended but the Problem is my-app.herokuapp.com/api/users also serves index.html file instead of JSON that the endpoint is supposed to return.
I tried
I replaced endpoint route definition to come before the "" definition (didn't suffice)
EVEN more, I removed redirection to index.html but heroku still opens the index.html page with any type of request (the "" redirection still works). So, it might have cached something?
Is it about cache (how to clean?) or any other suggestions?
You should create routes and work in a proper flow for each functionality,
For Example:
//app.js
app.use("/api/user",userRoutes);
//UserRoutes
router.post("/signup",UserController.signup);
//UserController
exports.signup = async (req,res,next) => {
//Signup function to add a new user when the user provides required info
}
In this way, you code will be easily accessible and much efficient

sending COOP and COEP headers in reactnode app

I have a deployed app that is built on Express (Node) and uses a built React frontend for app rendering.
Currently, I'm facing SharedArrayBuffer issues and need to pass these headers to make my code work:
To opt in to a cross-origin isolated state, you need to send the following HTTP headers on the main document:
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
Where and how would I go about doing this? New to full stack development haha.
I'm currently working on a project where I also encountered the SharedArrayBuffer issue when integrating ffmpeg-wasm.
This first snippet from cross origin resource policy issue when playing files from s3 on deployed app solved my problem. This would go in your server.js (note that the sequence is important, set headers before express.static):
app.use((req, res, next) => {
res.header("Cross-Origin-Embedder-Policy", "require-corp");
res.header("Cross-Origin-Opener-Policy", "same-origin");
next();
});
app.use(express.static(...));
Alternatively:
const customHeaders = (res, path, stat) => {
res.append("Cross-Origin-Embedder-Policy", "require-corp");
res.append("Cross-Origin-Opener-Policy", "same-origin");
}
app.use(express.static(...), {
setHeaders: customHeaders
});
Note that there are some issues with this approach:
SharedArrayBuffer is not supported in Safari and some other browsers, see https://caniuse.com/sharedarraybuffer
All cross-origin loads from the browser will fail, for example external scripts (e.g. Analytics) or image loads from other domains

How to enable URL routing in Node and Elm application (Heroku)?

I have an elm application running on Heroku.
I didn't want to use a third party elm buildpack, so I compiled the elm files locally and pushed elm.js onto the Heroku server.
My application is using Node.js backend so I'm using this code in expresss to
serve index.html:
if(process.env.NODE_ENV === 'production') {
app.use(express.static('client'));
app.get('*', (res:any) => {
res.sendFile(path.resolve(__dirname, 'client', 'index.html'));
});
}
I can go to the heroku URL and everything works perfectly. If I click on the internal /login link, I'm redirected to the login page and my url changes to ww.mywebsite.com/login. Internal routing is not my problem.
This is my problem: Although internal routing works, if I were to manually write www.mywebsite.com/login in the navigation bar, instead of seeing the login page, I see Internal Server Error
How do I fix this? Would I need a heroku buildback to accomplish this?
As #kaskelotti from the comments pointed out, Internal Server Error was printing because the files were being found, but another error was happening once they were found. If the files had not been found I would have received a 404 error.
This was a syntax error in my express code that matched all requests with my static index.html file.
The code posted in my question is wrong, THIS is how it should look:
if(process.env.NODE_ENV === 'production') {
app.use(express.static('client'));
app.get('*', (req , res) => {
res.sendFile(path.resolve(__dirname, 'client', 'index.html'));
});
}
The difference is the argument to the callback function in app.get. Originally it was (res) instead of (req, res), so the res variable was mistaken for an object of type Request and not Response, since it was the first argument.
Also as #kaskelotti pointed out, Heroku is irrelevant to this problem.

Express app not firing proxy

I'm currently building an express app that uses webpack and in order to avoid duplicate files being created (multiple indexes etc.) I'm sending bundled webpack assets through a proxy.
I have the following route:
app.all('/assets/*', function (req, res) {
console.log('foo');
proxy.web(req, res, {
target: 'http://127.0.0.1:3001'
});
});
The foostatement is triggered when I visit http://localhost:3000/assets/ but NOT when I visit http://localhost:3000/assets/styles.css
Even weirder, when I change my SASS files to generate a new styles.css and visit http://localhost:3001/assets/styles.css the updated CSS is present but not when visiting the same file on :3000 (which I guess kinda makes sense if the proxy isn't being fired...)
I'm not gonna lie, this is seriously freaking me out and some hair is about to get pulled out :)

transmission rpc with expressjs

i currently have transmission-daemon web ui served by nginx
server {
listen 2324;
server_name torrent.example.com;
location /rpc {
proxy_pass http://127.0.0.1:9091/transmission/rpc;
}
location /transmission {
proxy_pass http://127.0.0.1:9091/transmission;
}
location / {
proxy_pass http://127.0.0.1:9091/transmission/web/;
}
}
i am trying to display this page via https://github.com/stormpath/stormpath-express-sample this dashboard/user interface
in routes/index.js i have
router.get('/torrent', function (req, res, next) {
if (!req.user || req.user.status !== 'ENABLED') {
return res.redirect('/login');
}
var newurl = 'http://127.0.0.1:2324'
request(newurl).pipe(res)
});
i see the html when i goto /torrent but no images/css/js i am thinking the request is not the right tool for this purpose could some one offer a better solution
many thanks
Your HTML probably refers to CSS/images/etc using URLs such as /index.css. The browser makes these into fully-qualified URLs that look like http://torrent.example.com/index.css, which is not proxied by ngnix the way you have it set up.
You probably want to either use URLs such as /transmission/index.css for your CSS (when specified in the HTML), or alternatively have a <base> tag in your HTML for that.
ok so i have made progress with html/css i moved the transmission interface into the express root and imported the html into jade but now i am having a new problem
when i load the /torrent page i can seen in the web console it makes a request to /rpc which i have made a route for
router.get('/rpc|/rpc/', function (req, res) {
var newurl = 'http://127.0.0.1:9091/torrent/rpc/'
request(newurl).pipe(res)
});
but this comes up with a 404 when i change router.get to router.post i get a 405 error
i have removed the 409 error from transmission so this should work
i have solved the issue
i imported the transmission index.html into a jade template
i routed /torrent to render that template
then i made a new route for /rpc|/rpc/ made that do a post request to the backend transmission-daemon
i also changed /js/remote.js to look for the RPC._Root at the atchual domain

Resources