started coding a couple of months ago and run into a problem I didn't find anything online. I have the following http requests
app.get("/courses", async (req, res) => {
const courses = await Course.find({});
res.render("courses/index", { courses, topic: "Μαθήματα" });
});
app.get("/about", (req, res) => {
res.render("courses/about", { topic: "Πληροφορίες" });
});
app.get("/courses/:id", async (req, res) => {
const { id } = req.params;
const course = await Course.findById(id);
return res.render("courses/show", { course, topic: course.title });
});
All of the rendered templates are in the same folder but when I try to render something from /courses/:id it can't find the appropriate css and js files. The problem appears only when I use /courses/something else. If I try the same thing with just /:id it loads fine, else I get these errors.
The paths I have in my include files are:
<link rel="stylesheet" href="static/stylesheets/footer.css" />
<link rel="stylesheet" href="static/stylesheets/navbar.css" />
<link rel="stylesheet" href="static/stylesheets/coursesIndex.css" />
I tried a ton of different possible paths by didn't have any luck. Thank you for your time
Try prefixing a / before the static paths, as follows:
<link rel="stylesheet" href="/static/stylesheets/footer.css" />
<link rel="stylesheet" href="/static/stylesheets/navbar.css" />
<link rel="stylesheet" href="/static/stylesheets/coursesIndex.css" />
It might work, because, the other 2 routes are root level routes. So, when rendered, browser would look for static/stylesheets/... in the root directory. So, it worked.
But, when you rendered the same on /courses/:id path, the browser would look for static/stylesheets/... inside /courses/:id(actual would be like /courses/1, for example). That directory(1 in the example) does not exists in your root directory.
So, if you use absolute paths(these are the paths that starts with /), browser would look for them from the root of your website always. So, this would work.
Everything is working fine locally. But when deployed to Azure, loading the css shows this error:
Resource interpreted as Stylesheet but transferred with MIME type text/plain
It happens in all the browsers.
The application loads a spa in react.
These are the middlewares I am using in this order.
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStatusCodePagesWithReExecute("/Home/Error", "?statusCode={0}");
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseOurCustomAuthenticate();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action}/{id?}");
routes.MapRoute(
name: "api",
template: "api/{controller}/{action}/{id?}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (Environment.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
The custom authenticate middleware that we are using checks if the path starts with "/styles" it will not do anything and let it load.
This is the cshtml file where I include the css file:
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="~/styles/notFound.css">
</head>
<body class="body-content">
This is where the styles and images are
The image is being loaded properly on the server, only the style have this problem.
So in my custom middleware I did this:
if (httpContext.Request.Path.StartsWithSegments("/styles"))
{
httpContext.Response.ContentType = "text/css";
}
Now the content-type is correct in the network tab, but the style is not still loading. When I click on the css file it is an empty file.
I have read a lot of posts regarding this issue, but couldn't still solve it.
At this point I had to see if the stylesheet is actually deployed.
To do so, I pulled the contianer and run it locally to see what files are copied there.
I found that the styleSheet is copied under a folder "Styles" with capital "S" instead of "styles" with small "s". We use git for our source control and git didn't catch the rename I made to this folder.
This is how to commit such a change with git case sensitive. Renaming the folder properly fixed the problem for me.
So I've built a site in my directory and it can call all the stylesheets I made up just fine but when I create a local host it posts the html without any of the stylesheet. So the node would look like this
app.listen(PORT, function() {
console.log("App listening on PORT " + PORT);
});
And my html like this
<head><link href="custome.css" rel="stylesheet"></head>
<body> /snip </body>
So when ever I open up the local host at PORT it's blank.
You should serve static files. You should give more detail about the issue.
If you're using something like express.js, you can do something like this;
const fs = require('fs');
app.get('/custome.css', function (req, res) {
res.send(fs.readFileSync(__dirname+'/custome.css'));
});
My dir looks like that :
|-project
-gulpfile.js
|-build
-index.html
|-js
-app.min.js
-vendors.min.js
|-styles
-all.css
-vendors.min.css
I inject the css file with:
gulp.task('index',function () {
return gulp.src('src/index.html')
.pipe(inject(gulp.src(['http://localhost:5000/styles/all.css'], {read: false})))
.pipe(gulp.dest('build'))
.pipe(livereload());
})
I set up a local server with Node.js, when I do the request , the HTML file loads up, but the .css file doesn't connect for some reason.
I use this task for setting the server :
gulp.task('connect', function() {
connect.server({
root: 'build',
livereload: true,
port: 5000
});
});
You can use express frame work to achieve this
Var express=require (express);
var app=express();
// Now here you can attach static files
app.use("../example.css",static("/..example"));
Hope it will work.
In order to serve up static files such as CSS, JS, or assets you will need to add them to your index.html, and your server will be responsible for serving up your assets. Gulp is a task runner, not a server, so you will need to set up a simple HTTP server to serve up your assets. You can certainty build an HTTP server with vanilla Nodejs, but the easiest way to do this is with Express. Your Express server
might look something like this:
const express = require('express');
const app = express();
// serve static files in public/build directory
app.use(express.static('./build'));
// start the server on port 3000
const server = app.listen(3000, function() {
console.log('Server started on http://localhost:3000');
});
Then in your index.html be sure to link your CSS files with the link tag.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simple HTTP Server</title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
<h1>Simple HTTP Server</h1>
</body>
</html>
To everyone that may encounter my problem,that would be the solution.
.pipe(inject(gulp.src(['build/styles/all.css'], {read: false}), {ignorePath: 'build'} ))
I'm trying to follow the instructions to https://stackoverflow.com/a/18633827/2063561, but I still can't get my styles.css to load.
From app.js
app.use(express.static(path.join(__dirname, 'public')));
In my .ejs, I have tried both of these lines
<link rel="stylesheet" type="text/css" href="/css/style.css" />
<link rel="stylesheet" type="text/css" href="/public/css/style.css" />
Neither loads the css. I've gone into the developer's console noticed the type is set to 'text/html' instead of 'text/css'.
My path looks like
.
./app.js
./public
/css
/style.css
Use this in your server.js file
app.use(express.static(__dirname + '/public'));
and add css like
<link rel="stylesheet" type="text/css" href="css/style.css" />
dont need / before css like
<link rel="stylesheet" type="text/css" href="/css/style.css" />
1.Create a new folder named 'public' if none exists.
2.Create a new folder named 'css' under the newly created 'public' folder
3.create your css file under the public/css path
4.On your html link css i.e
<link rel="stylesheet" type="text/css" href="/css/style.css">
// note the href uses a slash(/) before and you do not need to include the 'public'
5.On your app.js include :
app.use(express.static('public'));
Boom.It works!!
The custom style sheets that we have are static pages in our local file system. In order for server to serve static files, we have to use,
app.use(express.static("public"));
where,
public is a folder we have to create inside our root directory and it must have other folders like css, images.. etc
The directory structure would look like :
Then in your html file, refer to the style.css as
<link type="text/css" href="css/styles.css" rel="stylesheet">
For NodeJS I would get the file name from the res.url, write the header for the file by getting the extension of the file with path.extname, create a read stream for the file, and pipe the response.
const http = require('http');
const fs = require('fs');
const path = require('path');
const port = process.env.PORT || 3000;
const server = http.createServer((req, res) => {
let filePath = path.join(
__dirname,
"public",
req.url === "/" ? "index.html" : req.url
);
let extName = path.extname(filePath);
let contentType = 'text/html';
switch (extName) {
case '.css':
contentType = 'text/css';
break;
case '.js':
contentType = 'text/javascript';
break;
case '.json':
contentType = 'application/json';
break;
case '.png':
contentType = 'image/png';
break;
case '.jpg':
contentType = 'image/jpg';
break;
}
console.log(`File path: ${filePath}`);
console.log(`Content-Type: ${contentType}`)
res.writeHead(200, {'Content-Type': contentType});
const readStream = fs.createReadStream(filePath);
readStream.pipe(res);
});
server.listen(port, (err) => {
if (err) {
console.log(`Error: ${err}`)
} else {
console.log(`Server listening at port ${port}...`);
}
});
Use in your main .js file:
app.use('/css',express.static(__dirname +'/css'));
use in you main .html file:
<link rel="stylesheet" type="text/css" href="css/style.css" />
The reason you getting an error because you are using a comma instead of a concat + after __dirname.
In your app or server.js file include this line:
app.use(express.static('public'));
In your index.ejs, following line will help you:
<link rel="stylesheet" type="text/css" href="/css/style.css" />
I hope this helps, it did for me!
IMHO answering this question with the use of ExpressJS is to give a superficial answer. I am going to answer the best I can with out the use of any frameworks or modules. The reason this question is often answerd with the use of a framework is becuase it takes away the requirment of understanding 'Hypertext-Transfer-Protocall'.
The first thing that should be pointed out is that this is more a problem surrounding "Hypertext-Transfer-Protocol" than it is Javascript. When request are made the url is sent, aswell as the content-type that is expected.
The second thing to understand is where request come from. Iitialy a person will request a HTML document, but depending on what is written inside the document, the document itsself might make requests of the server, such as: Images, stylesheets and more. This question refers to CSS so we will keep our focus there. In a tag that links a CSS file to an HTML file there are 3 properties. rel="stylesheet" type="text/css" and href="http://localhost/..." for this example we are going to focus on type and href. Type sends a request to the server that lets the server know it is requesting 'text/css', and 'href' is telling it where the request is being made too.
so with that pointed out we now know what information is being sent to the server now we can now seperate css request from html request on our serverside using a bit of javascript.
var http = require('http');
var url = require('url');
var fs = require('fs');
function onRequest(request, response){
if(request.headers.accept.split(',')[0] == 'text/css') {
console.log('TRUE');
fs.readFile('index.css', (err, data)=>{
response.writeHeader(200, {'Content-Type': 'text/css'});
response.write(data);
response.end();
});
}
else {
console.log('FALSE');
fs.readFile('index.html', function(err, data){
response.writeHead(200, {'Content_type': 'text/html'});
response.write(data);
response.end();
});
};
};
http.createServer(onRequest).listen(8888);
console.log('[SERVER] - Started!');
Here is a quick sample of one way I might seperate request. Now remember this is a quick example that would typically be split accross severfiles, some of which would have functions as dependancys to others, but for the sack of 'all in a nutshell' this is the best I could do. I tested it and it worked. Remember that index.css and index.html can be swapped with any html/css files you want.
I have used the following steps to resolve this problem
create new folder (static) and move all js and css file into this folder.
then add app.use('/static', express.static('static'))
add css like <link rel="stylesheet" type="text/css" href="/static/style.css"/>
restart server to view impact after changes.
Use this in your server.js file
app.use(express.static('public'));
without the directory ( __dirname ) and then within your project folder create a new file and name it public then put all your static files inside it
Its simple if you are using express.static(__dirname + 'public') then don't forget to put a forward slash before public that is express.static(__dirname + '/public') or use express.static('public') its also going to work;
and don't change anything in CSS linking.
the order of registering routes is important . register 404 routes after static files.
correct order:
app.use("/admin", admin);
...
app.use(express.static(join(__dirname, "public")));
app.use((req, res) => {
res.status(404);
res.send("404");
});
otherwise everything which is not in routes , like css files etc.. , will become 404 .
The above responses half worked and I'm not why they didn't on my machine but I had to do the following for it work.
Created a directory at the root
/public/js/
Paste this into your server.js file with name matching the name of directory created above. Note adding /public as the first param
app.use('/public',express.static('public'));
Finally in the HTML page to which to import the javascript file into,
<script src="public/js/bundle.js"></script>