Express sending assets with wrong MIME type - javascript

Using Express to serve a Vue.js webpack app, I am receiving the following error after deploy:
Is my code for serving the app is the issue here?
app.use(helmet())
app.use(express.static(path.resolve(__dirname, '../client/dist/static')));
app.all('*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client/dist', 'index.html'));
})
Otherwise isn't express.static supposed to automatically assign content types to the static files?

You get this message also when the response status in 404 Not Found, so check carefully that the files actually exist from Network tab.
Network tab:
Console tab:
See a similar issue here: https://stackoverflow.com/a/48792698/258772

For some reason, had to now specify a mount path:
app.use('/static', express.static(path.resolve(__dirname, '../client/dist/static')));

Yes same problems over here.
I'm using ecstatic (still with express) now. I'm not sure if this is the solution (I'm not on the machine that made the error possible).
Will try it tommorow on the 'error' machine.
const express = require('express');
const ecstatic = require('ecstatic');
const http = require('http');
const app = express();
app.use(ecstatic({
root: `${__dirname}/public`,
showdir: false,
}));
http.createServer(app).listen(8080);
console.log('See if its cool on -> :8080');

Related

Problem with static routing in Node.js using express

I am having an issue with some custom routing code, it all works fine and is in sync with the client-side view routing I do, but as soon as I have a subpage, it doesn't route my static files correctly.
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.
Rather than giving me a file from the root directory, it'll serve it as if it were from the subfolder.
Example: i go to http://localhost/sign-up, and files loading in my index file from /scripts are loaded, but if i go to http://localhost/sign-up/2, it'll attempt to load the script from /sign-up/scripts
const express = require('express');
const path = require('path');
const app = express();
app.use('/views', express.static(path.resolve(__dirname, 'frontend', 'views')));
app.use('/styles', express.static(path.resolve(__dirname, 'frontend', 'styles')));
app.use('/scripts', express.static(path.resolve(__dirname, 'frontend', 'scripts')));
app.use('/media', express.static(path.resolve(__dirname, 'frontend', 'media')));
app.get('/*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'frontend', 'newSite.html'));
});
app.listen(process.env.PORT || 1234, () => console.log('Server is now running...'));
To manage this I have been following these tutorials by DCODE on youtube, but I can't see anything amiss:
https://www.youtube.com/watch?v=6BozpmSjk-Y
https://youtu.be/OstALBk-jTc
Resources loaded in the sign up folder should use URLs beginning with a '/' character, to make them relative to the site root, e.g.
src="/scripts/modulefile.js"
href="/css/stylesheet.css"
href="/media/image.png"
and not urls relative to the signup folder - which they will be if the leading '/' is omitted.
You don't need multiple routes to serve your static contents, and the static method of express do such kind of tasks for you:
// If your 'public' or 'static' directory is one of root directories
app.use(express.static(process.cwd() + '/public'));
// so all these requests will be served:
// -> /public/styles/custom.css
// -> /public/scripts/pollyfils.js
// -> /public/media/logo.png

How can I get my MERN app to refresh correctly on heroku?

I deployed my MERN app to heroku. It loads, and I can navigate between pages by clicking on the nav bar. But, if I refresh a page, it just comes up blank. There are no error messages on the screen or in the console. If I go back to a previous page that worked before, it also comes up blank. At this point, I don't know what to look for.
My problem stemmed from incorrectly defining the root react route in my server.js file. I got the home page to render and refresh, but then the app would not load any other pages. Here is the server.js file at that point:
const express = require("express");
const mongoose = require("mongoose");
const routes = require("./routes");
const app = express();
// set the port for mongo connection to 3001 in development mode
const PORT = process.env.PORT || 3001;
// Configure body parsing for AJAX requests
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
// Serve up static assets
if (process.env.NODE_ENV === "production") {
app.use(express.static("client/build"));
app.get("*", function (req, res) {
res.sendFile(path.join(__dirname, "./client/build/index.html"));
});
}
app.use(routes);
mongoose.connect(
process.env.MONGODB_URI || "mongodb://localhost/portfolio_db",
{
useCreateIndex: true,
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false,
}
);
// Start the API server on port 3001
app.listen(PORT, () =>
console.log(`🌎 ==> API Server now listening on PORT ${PORT}!`)
);
This sort of fixed my problem, but the app still wasn't routing properly, so I posted this: new issue
Basically, there where 3 problems:
'path' wasn't required at the top of the file, so the path to index.html wasn't defined (had to look at heroku logs to see this error).
The default react route (app.get('*'....)) should not be in the if statement, and
The default react route statement needed to be below the 'app.use(routes)' statement.
I also deleted a statement defining the default react route in /routes/index.js. Now the app deploys and routes correctly.
I was also getting same error "cannot get /page" whenever I did refresh or window.location() So after 3 days of trials and deploys I found this solution. Add this in your server.js file before deploying.
if(process.env.NODE_ENV === "production") {
app.use(express.static("client/build"));
app.get("/*", function(req, res) {
res.sendFile(path.join(__dirname, "./client/build/index.html"));
}); }
You can add this code snippet before app.listen. Remember the path says ./client/build/index.html which references to your build file in the production build in remote heroku master.
cannot get /page happens because the server is not able to find the route which was created using react-router or anything else in frontend so we need to direct the app to index.html in production build so that it starts the whole frontend process again and identifies the route...

Returning a page through HTTP with express

I have a folder called "Public" which contains an index.html file a long with some JavaScript and library files. When someone tries to access the products path (mydomain.com/products) I want to display that index.html file, but the client also needs to receive all the JavaScript and libraries. Here is the code for how I initially handle the HTTP request.
const express = require('express')
const app = express()
const bodyParse = require('body-parser')
const productRoutes = require('./api/routes/products')
const orderRoutes = require('./api/routes/orders')
app.use(bodyParse.urlencoded({extended: false}))
app.use(bodyParse.json())
// Routes which handle requests
app.use('/products', productRoutes)
app.use('/orders', orderRoutes)
In the products.js file, I continue the routing like this:
const express = require('express')
const router = express.Router()
router.get('/', (req, res, next) => {
/*res.status(200).json({
message: 'Handling GET requests to /products'
})*/
res.status(200).render("../../public")
})
The code I've commented out works perfectly fine, but I'm struggling to respond with the "public" folder page. I can't remember everything I've tried, but using .render or .sendFile on the "public" directory has not worked for me.
When I try to access the /products route, I'm hit with an empty error message. As it fails to return anything in the /products route, in continues down the file to an error handler. The error message is empty.
Any ideas on how to display the page with all the folder contents would be great!
Try: app.use('/products', express.static('public'))
This makes your "public" directory viewable from the /products route.
express.static() docs
You must config path for express static by :
//app.js | server.js
app.use(express.static(__dirname + '/public'));
Then, in example you have a file as : /public/you.html
In your app, you can use that file as path /you.html
And the same with all files type *.js, *.css,...
Fix error cannot view error
Run cmd npm install ejs
Att to app.js:
app.set('view engine', 'ejs');
After that, you create 1 file error.ejs at folder views :
//error.ejs
<%=error%>
Goodluck

Prerender Angular app on an already existing Node.js server

My goal is to have dynamic og: tags, that can be seen by the facebook crawler. By doing some research I figured the best (and probably the only) approach is to prerender my app on the server. However I'm having problems with doing that.
I already have an existing Node.js server which looks a little different from the servers in most online guides.
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const http = require('http');
const app = express();
// Api for retrieving data from DB
const api = require('./server/api');
// Parsers
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// Angular DIST folder
app.use(express.static(path.join(__dirname, 'dist')));
// Api location
app.use('/api', api);
// Send all other requests to the Angular app
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'))
})
// Set Port
const port = process.env.PORT || '3040';
app.set('port', port);
const server = http.createServer(app)
server.listen(port, () => console.log('Magic happens on localhost:' + port));
I've tried using prerender.io. I got an API key, installed prerender-node and put this right before redirecting the request to index.html:
app.use(require('prerender-node').set('prerenderToken', 'my-token'));
// Send all other requests to the Angular app
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'))
})
I also added this to my index.html:
<meta name="fragment" content="!">
Nothing changed. Perhaps there's something else I need to do to get it working? Again, my goal is to have dynamic og: tags, that can be seen by the facebook crawler.
Additional info: For now, I'm setting the meta tags using the Meta serivce that comes with Angular 4, if it matters.
EDIT:
Demo link if someone wants to test: http://aramet.demo.cdots.bg/news-preview/1
Can you try moving the:
app.use(require('prerender-node').set('prerenderToken', 'my-token'));
above the static file line like:
app.use(require('prerender-node').set('prerenderToken', 'my-token'));
// Angular DIST folder
app.use(express.static(path.join(__dirname, 'dist')));
Since your index.html file is in your dist folder and you're serving static files from the dist folder, I'm wondering if the static call is serving your index.html file somehow.

How can I serve my web app with Node/Express?

I'm probably going to ask a huge noob question, one of the worst I've ever had asked here, but I'm lost as hell with Node/Express. I've only used Apache servers (typical WAMP/XAMP for testing purposes), so I have absolutely no idea on what I have to do to serve my web app.
My folder tree is the following:
www
nodeserver.js
(more things)
Liteconomy (my web app)
js
css
plugins
templates
index.html
sublime_project
Pretty typical, huh? Well, I've been searching how to serve this app with a simple access like localhost:8080/Liteconomy, or localhost:8080/Liteconomy.html. After that, my angular routing would do the rest, but I just can't serve the app.
I've got this written in nodeserver.js:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(8080, function () {
console.log('Example app listening on port 8080!');
});
app.get('/Liteconomy', function (req, res) {
res.send('Liteconomy/index.html');
});
When I execute it and access to localhost:8080, I get the "Hello world", but when I go to localhost:8080/Liteconomy, I get the following plain text: "Liteconomy/index.html". If I try to access to the index resource directly, I get a "Cannot GET /Liteconomy/index.html" error.
I also tried using the static thingy, but didn't work either.
What am I doing wrong here? I guess I'm just missing something very important.
Do the following, it will resolve your issue.
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
// uncomment following if you want to access your app from /liteconomy
//app.use('/liteconomy', express.static(__dirname + '/Liteconomy', {index: "index.html"}));
//This will enable you to access it form '/'
app.use('/', express.static(__dirname + '/Liteconomy', {index: "index.html"}));
// Rest of the stuff
Then if you will visit your URL that you set and port, you'll be able to access.
Using express.static is recommended way of serving static content.
Hope it helps!
You get a plain text answer because you actually ask to do it with the :
app.get('/Liteconomy', function (req, res) {
res.send('Liteconomy/index.html');
});
If you want to send a simple html file like your index.html file, you should use the "sendfile " function :
app.get('/Liteconomy', function (req, res) {
res.sendfile(__dirname + '/Liteconomy/index.html');
});
"__dirname" represents your root directory path and then you simply put your file path.
Hope that helps !
PS : by default express come with jade and ejs template support instead of just using html. I would advise you to take a look at one of them, it can be a great help to construct your application web pages.

Categories