359

I've reduced my code to the simplest express-js app I could make:

var express = require("express"),
    app = express.createServer();
app.use(express.static(__dirname + '/styles'));
app.listen(3001);

My directory look like this:

static_file.js
/styles
  default.css

Yet when I access http://localhost:3001/styles/default.css I get the following error:

Cannot GET / styles /
default.css

I'm using express 2.3.3 and node 0.4.7. What am I doing wrong?

MPelletier
  • 16,256
  • 15
  • 86
  • 137
Kit Sunde
  • 35,972
  • 25
  • 125
  • 179
  • check below link http://only4ututorials.blogspot.com/2017/05/how-to-serve-static-file-in-express-js.html – Dexter May 22 '17 at 15:46

26 Answers26

563

Try http://localhost:3001/default.css.

To have /styles in your request URL, use:

app.use("/styles", express.static(__dirname + '/styles'));

Look at the examples on this page:

//Serve static content for the app from the "public" directory in the application directory.

    // GET /style.css etc
    app.use(express.static(__dirname + '/public'));

// Mount the middleware at "/static" to serve static content only when their request path is prefixed with "/static".

    // GET /static/style.css etc.
    app.use('/static', express.static(__dirname + '/public'));
alex
  • 6,818
  • 9
  • 52
  • 103
Giacomo
  • 11,087
  • 5
  • 25
  • 25
  • In case of new install you should verify that your express module is properly installed (http://expressjs.com/en/starter/installing.html) then you should check the path and your directory name like Giacomo said ;) – Spl2nky Jan 19 '16 at 21:35
  • 4
    always use `path.join` to overcome cross platform directory separator issues. path.join(__dirname, '/') – Doug Chamberlain Nov 22 '16 at 15:43
  • I put that at my code, but the browser always redirect to "/static/myjs.js/", that last / give me an error of MIME Type – Guillermo Diaz Mar 10 '20 at 13:18
  • Does the mount path make sense in `Express` in `prod` or is it a testing issue for dev? Maybe it looks more ordered to have an url folder. – Timo Mar 28 '21 at 08:37
  • If anyone using TypeScript (or not) stumbles upon this comment and has the same problem: if your file is in a `src/` dir, use `path.join(__dirname, "../public")`. – deb Apr 10 '21 at 12:53
  • Shouldn't app.use() without a specified path handle all requests? Then why will `app.use(express.static(__dirname + '/public'));` not work for /static? – Robert Page Feb 05 '22 at 18:07
  • oh darn, app.get doesn't work, has to be app.use – Bernardo Dal Corno Sep 30 '22 at 17:45
54

I have the same problem. I have resolved the problem with following code:

app.use('/img',express.static(path.join(__dirname, 'public/images')));
app.use('/js',express.static(path.join(__dirname, 'public/javascripts')));
app.use('/css',express.static(path.join(__dirname, 'public/stylesheets')));

Static request example:

http://pruebaexpress.lite.c9.io/js/socket.io.js

I need a more simple solution. Does it exist?

Daniel Kmak
  • 18,164
  • 7
  • 66
  • 89
David Miró
  • 2,694
  • 20
  • 20
  • Thank you for sharing your solution regardless of whether it is optimal or not. If you want to reopen the issue for optimization, consider posting a new question detailing the new circumstances. If optimization is the sole purpose, the question may be better suited to [SO Code Review](http://stackoverflow.com/questions/tagged/code-review). –  Jan 15 '15 at 01:07
  • In my case, the only way to make static imports work with expressjs has been to use the "`path`" module. All other solutions without `path.join` or prepending the `__dirname` string have been fruitless. – Marco Faustinelli Sep 10 '21 at 12:59
22

This work for me:

app.use('*/css',express.static('public/css'));
app.use('*/js',express.static('public/js'));
app.use('*/images',express.static('public/images'));
Apichai
  • 315
  • 1
  • 4
  • 8
17

default.css should be available at http://localhost:3001/default.css

The styles in app.use(express.static(__dirname + '/styles')); just tells express to look in the styles directory for a static file to serve. It doesn't (confusingly) then form part of the path it is available on.

nbro
  • 15,395
  • 32
  • 113
  • 196
diff_sky
  • 561
  • 4
  • 8
  • 3
    Totally! Which is by convention in express.js you do it on `/public` which has `css`, `js`, `img` folders so you can `http://localhost:3001/css/default.css` :) – Kit Sunde Jun 20 '12 at 05:32
12

In your server.js :

var express   =     require("express");
var app       =     express();
app.use(express.static(__dirname + '/public'));

You have declared express and app separately, create a folder named 'public' or as you like, and yet you can access to these folder. In your template src, you have added the relative path from /public (or the name of your folder destiny to static files). Beware of the bars on the routes.

Basavaraj Hadimani
  • 1,094
  • 12
  • 21
Baurin Leza
  • 2,004
  • 1
  • 13
  • 15
10

I am using Bootstrap CSS, JS and Fonts in my application. I created a folder called asset in root directory of the app and place all these folder inside it. Then in server file added following line:

app.use("/asset",express.static("asset"));

This line enables me to load the files that are in the asset directory from the /asset path prefix like: http://localhost:3000/asset/css/bootstrap.min.css.

Now in the views I can simply include CSS and JS like below:

<link href="/asset/css/bootstrap.min.css" rel="stylesheet">
arshovon
  • 13,270
  • 9
  • 51
  • 69
  • 3
    This is the answer that is well explained that worked for me. +1 for taking the pain to elaborate and give an example that works. Last time this worked for me on a previous project it was just by fluke but today as I work on another new project I understand how it works from the good explanation in your answer. – Joseph Sep 26 '20 at 13:59
9

What worked for me is:

Instead of writing app.use(express.static(__dirname + 'public/images')); in your app.js

Simply write app.use(express.static('public/images'));

i.e remove the root directory name in the path. And then you can use the static path effectively in other js files, For example:

<img src="/images/misc/background.jpg">

Hope this helps :)

Amir Aslam
  • 383
  • 4
  • 9
  • This solved my issue. In my code, path to CSS was working fine even with the __dirname concatenation (using path.join), while fetching js was failing. – Chim Mar 16 '20 at 08:47
6

to serve static files (css,images,js files)just two steps:

  1. pass the directory of css files to built in middleware express.static

    var express = require('express');
    var app = express();
    /*public is folder in my project directory contains three folders
    css,image,js
    */
    //css  =>folder contains css file
    //image=>folder contains images
    //js   =>folder contains javascript files
    app.use(express.static( 'public/css'));
    
  2. to access css files or images just type in url http://localhost:port/filename.css ex:http://localhost:8081/bootstrap.css

note: to link css files to html just type<link href="file_name.css" rel="stylesheet">

if i write this code

var express = require('express');
var app = express();
app.use('/css',express.static( 'public/css'));

to access the static files just type in url:localhost:port/css/filename.css ex:http://localhost:8081/css/bootstrap.css

note to link css files with html just add the following line

<link href="css/file_name.css" rel="stylesheet">    
Ahmed Mahmoud
  • 1,724
  • 1
  • 17
  • 21
5

this one worked for me

app.use(express.static(path.join(__dirname, 'public')));

app.use('/img',express.static(path.join(__dirname, 'public/images')));

app.use('/shopping-cart/javascripts',express.static(path.join(__dirname, 'public/javascripts')));

app.use('/shopping-cart/stylesheets',express.static(path.join(__dirname, 'public/stylesheets')));

app.use('/user/stylesheets',express.static(path.join(__dirname, 'public/stylesheets')));

app.use('/user/javascripts',express.static(path.join(__dirname, 'public/javascripts')));
krishan
  • 1,141
  • 1
  • 12
  • 24
james gicharu
  • 99
  • 2
  • 7
2

Webpack makes things awkward

As a supplement to all the other already existing solutions:

First things first: If you base the paths of your files and directories on the cwd (current working directory), things should work as usual, as the cwd is the folder where you were when you started node (or npm start, yarn run etc).

However...

If you are using webpack, __dirname behavior will be very different, depending on your node.__dirname settings, and your webpack version:

  1. In Webpack v4, the default behavior for __dirname is just /, as documented here.
    • In this case, you usually want to add this to your config which makes it act like the default in v5, that is __filename and __dirname now behave as-is but for the output file:
      module.exports = {
         // ...
         node: {
           // generate actual output file information
           // see: https://webpack.js.org/configuration/node/#node__filename
           __dirname: false,
           __filename: false,
         }
      };
      
    • This has also been discussed here.
  2. In Webpack v5, per the documentation here, the default is already for __filename and __dirname to behave as-is but for the output file, thereby achieving the same result as the config change for v4.

Example

For example, let's say:

  • you want to add the static public folder
  • it is located next to your output (usually dist) folder, and you have no sub-folders in dist, it's probably going to look like this
const ServerRoot = path.resolve(__dirname /** dist */, '..');
// ...
app.use(express.static(path.join(ServerRoot, 'public'))

(important: again, this is independent of where your source file is, only looks at where your output files are!)

More advanced Webpack scenarios

Things get more complicated if you have multiple entry points in different output directories, as the __dirname for the same file might be different for output file (that is each file in entry), depending on the location of the output file that this source file was merged into, and what's worse, the same source file might be merged into multiple different output files.

You probably want to avoid this kind of scenario scenario, or, if you cannot avoid it, use Webpack to manage and infuse the correct paths for you, possibly via the DefinePlugin or the EnvironmentPlugin.

Domi
  • 22,151
  • 15
  • 92
  • 122
2

The problem with serving __dirname is that __dirname returns the path of the current file, not the project's file. Also, if you use a dynamic header, each page will look for the static files in a different path and it won't work. The best, for me, is to substitute __dirname for process.cwd() which ALWAYS donates the path to the project file.

app.use(express.static(process.cwd() + '/public'));

And in your project:

link rel="stylesheet" href="/styles/default.css"

See: What's the difference between process.cwd() vs __dirname?

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
2

I was using

app.use(express.static('public'))

When there was no file in the public folder with name index.html.

I was getting the following error in the browser:

"Cannot GET /"

When I renamed the file to 'index.html', it works fine.

Tyler2P
  • 2,324
  • 26
  • 22
  • 31
1

I find my css file and add a route to it:

app.get('/css/MyCSS.css', function(req, res){
  res.sendFile(__dirname + '/public/css/MyCSS.css');
});

Then it seems to work.

Ahmed Mahmoud
  • 1,724
  • 1
  • 17
  • 21
Bren
  • 3,516
  • 11
  • 41
  • 73
  • 1
    I wouldn't recommend this approach as you should be using ExpressJS's `.use()` and `express.static()` methods to send where you are serving your files. Otherwise you'll have one of these router per file in your public directory and that's a lot of overhead to maintain. – Sgnl Jan 01 '17 at 01:01
  • This is a work around but I do not think it is appropriate. If you have many CSS and JS files, how can you maintain it? – arshovon Jan 12 '17 at 11:39
1

Try accessing it with http://localhost:3001/default.css.

   app.use(express.static(__dirname + '/styles'));

You are actually giving it the name of folder i.e. styles not your suburl.

Sunil Lulla
  • 797
  • 10
  • 18
1

if your setup

myApp
  |
  |__ public
  |     |
  |     |__  stylesheets
  |     |     |
  |     |     |__ style.css
  |     |
  |     |___ img
  |           |
  |           |__ logo.png
  |
  |__ app.js

then,
put in app.js

app.use('/static', express.static('public'));

and refer to your style.css: (in some .pug file):

link(rel='stylesheet', href='/static/stylesheets/style.css')
Bar Horing
  • 5,337
  • 3
  • 30
  • 26
  • Why would you introduce a renaming step public -> static? I would say that is just more confusing extra information. But then again indirection is usually a good thing... – masterxilo Jan 05 '20 at 16:02
1

Try './public' instead of __dirname + '/public'. Similarly, try process.cwd() + '/public'.

Sometimes we lose track of the directories we are working with, its good to avoid assuming that files are located where we are telling express where they are.

Similarly, avoid assuming that in the depths of dependencies the path is being interpreted the same way at every level.

Ray
  • 142
  • 1
  • 5
  • 100%. Always try to use `__dirname`, unless you have a case where you don't need to access the project files all the time. – asciidude Oct 30 '22 at 20:10
1
app.use(express.static(__dirname+'/'));

This worked for me, I tried using a public directory but it didn't work. But in this case, we give access to the whole static files in the directory, hope it helps!

0

In addition to above, make sure the static file path begins with / (ex... /assets/css)... to serve static files in any directory above the main directory (/main)

  • 2
    Addition to what above? State it in your answer (give credit to the person who posted it, if you have to). SO often changes the order of the answers so that all answers get seen and not the the first few. We don't know what you are talking about. – Zachary Kniebel Apr 11 '13 at 17:22
0
  1. Create a folder with 'public' name in Nodejs project
    folder.
  2. Put index.html file into of Nodejs project folder.
  3. Put all script and css file into public folder.
  4. Use app.use( express.static('public'));

  5. and in index.html correct path of scripts to <script type="text/javascript" src="/javasrc/example.js"></script>

And Now all things work fine.

0

static directory

check the above image(static directory) for dir structure

const publicDirectoryPath = path.join(__dirname,'../public')
app.use(express.static(publicDirectoryPath))


//  or

app.use("/", express.static(publicDirectoryPath))
app.use((req, res, next) => {
res.sendFile(path.join(publicDirectoryPath,'index.html'))
helloJT
  • 3
  • 4
0

In your nodejs file

const express = require('express');
const app = express();

app.use('/static', express.static('path_to_static_folder'));

In your pug file

...
script(type="text/javascript", src="static/your_javascript_filename")
...

Note the "static" word. It must be same in nodejs file and pug file.

0

This is worked for me:

Server:

app.use(express.static("public"));

Client:

<link href="css/styles.css" rel="stylesheet">
<img src="images/210504.png">
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
0

Just encountered (and solved) a variation on this (node v16.16.0).

folder structure:

    project
      apidoc
      src
        index.js (aka server.js, app.js)
        public
          images
          css

I am serving static content from 'public':

    app.use(express.static('src/public'))

and wanted to also serve the api docs from apidocs (one folder above the current folder). This wouldn't work:

    app.use('/apidoc', express.static('../apidoc')))
    // this didn't work either
    app.use('/apidoc', express.static('/absolute/path/to/apidoc')))

This was the solution:

    import path from 'path'
    import { fileURLToPath } from 'url';
    const __filename = fileURLToPath(import.meta.url);
    const __dirname = path.dirname(__filename);

    app.use('/apidoc', express.static(path.join(__dirname, '../apidoc')))
    app.use(express.static('src/public'))

I suspect a path separator issue.

marktaff
  • 81
  • 4
0

If your folder structure looks like this

myApp
  |
  |__ public
  |     |
  |     |__  stylesheets
  |     |     |
  |     |     |__ style.css
  |     |
  |     |___ img
  |           |
  |           |__ logo.png
  |
  |__ src
        |
        |__ app.js
    

use the line below:

app.use('/public', express.static(path.resolve('public')))
Johnson Fashanu
  • 897
  • 8
  • 6
-1
app.use('/public/',express.static(path.join('./public')));

I find this solution after finding it for hours it works for me!!

Tyler2P
  • 2,324
  • 26
  • 22
  • 31
-11

i just try this code and working

const exp = require('express');
const app = exp();

app.use(exp.static("public"));

and working,

before (not working) :

const express = require('express');
const app = express();
app.use(express.static("public"));

just try