How to link script file in footer.ejs? - node.js

I want to link script.js to my project.
I write folowing code on
footer.ejs:
<script src="../static/js/script.js"></script>
But I got error:
Cannot GET /static/js/script.js
How can I fix it?

This is most likely due to a path typo somewhere.
For example, if in your app.js you use app.use(express.static(__dirname + '/static/')); Then in your script tag you would need to use <script src="js/script.js">
If you changed your app.js to app.use(express.static(__dirname + '/static'));
Then you would need to use <script src="/js/script.js"></script>
Check everywhere that you reference that file and make sure you have the correct filepath.

Related

js file not found on Heroku

My socket.js file can not be found when my Node.js server runs on Heroku, however when it runs on localhost, it is found. In addition, although the app.js file is in the same directory with socket.js file, it can not be found. I've seen some posts suggesting to use
app.use('/', express.static(__dirname));
but i guess it is not the case here.
my index.html file :
<script src="/angular-socket-io/socket.js"></script>
<script src="/socket.js"></script>
<script src="/socket.io/socket.io.js"></script>
Amongst them, the only one couldnt be found is the second directory(/socket.js) which contains the 'socket factory'inside.
My folder tree is as follows;
-app
--assets
---app.js
---socket.js
Any help please?
Just add app.use(express.static(path.join(__dirname, 'app/assets'))); to your main code and after that you can use <script src="/socket.js"></script>
My JavaScript file didn't initialize because of how I imported the JQuery script inside of my index.html.
If your JavaScript file that contains JQuery is not initialized. Make sure to import it with HTTPS not HTTP.
WRONG :
<script src="http://code.jquery.com/jquery-3.5.1.js"></script>
CORRECT :
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
This solved my problem of missing the JavaScript file on Heroku.

Node JS not sending file with res.sendFile()

My file structure is shown above, but I am unable to find the file with error: Undefined is not a function.
The app path is set, which I can get via a console.log:
/Users/myname/Desktop/myproject/client
If I navigate to localhost:3000 for example, the page is rendered correctly. I can then click to navigate to localhost:3000/login and everything is still all good. But if I go directly to localhost:3000/login, i.e. the index page is never loaded, then this route: '/*' is hit and the undefined error occurs. No HTML is loaded.
I set the app path like so:
app.use(express.static(path.join(__dirname, '/client')));
app.set('appPath', path.join(__dirname, '/client'));
I am using Express:
"~4.0.0"
Try to set the root for relative file path, this way:
app.set('base', __dirname);
and then:
app.use(express.static('client'));
Make sure not to include /client twice, so you don't get something like .../client/client... in your path.
http://expressjs.com/api.html#res.sendFile
res.sendFile() is supported from Express v4.8.0 onwards
You were close.
app.use(express.static(__dirname + '/client'));
Regards

How to include scripts located inside the node_modules folder?

I have a question concerning best practice for including node_modules into a HTML website.
Imagine I have Bootstrap inside my node_modules folder. Now for the production version of the website, how would I include the Bootstrap script and CSS files located inside the node_modules folder? Does it make sense to leave Bootstrap inside that folder and do something like the following?
<script src="./node_modules/bootstrap/dist/bootstrap.min.js"></script>
Or would I have to add rules to my gulp file which then copy those files into my dist folder? Or would it be best to let gulp somehow completely remove the local bootstrap from my HTML file and replace it with the CDN version?
Usually, you don't want to expose any of your internal paths for how your server is structured to the outside world. What you can is make a /scripts static route in your server that fetches its files from whatever directory they happen to reside in. So, if your files are in "./node_modules/bootstrap/dist/". Then, the script tag in your pages just looks like this:
<script src="/scripts/bootstrap.min.js"></script>
If you were using express with nodejs, a static route is as simple as this:
app.use('/scripts', express.static(__dirname + '/node_modules/bootstrap/dist/'));
Then, any browser requests from /scripts/xxx.js will automatically be fetched from your dist directory at __dirname + /node_modules/bootstrap/dist/xxx.js.
Note: Newer versions of NPM put more things at the top level, not nested so deep so if you are using a newer version of NPM, then the path names will be different than indicated in the OP's question and in the current answer. But, the concept is still the same. You find out where the files are physically located on your server drive and you make an app.use() with express.static() to make a pseudo-path to those files so you aren't exposing the actual server file system organization to the client.
If you don't want to make a static route like this, then you're probably better off just copying the public scripts to a path that your web server does treat as /scripts or whatever top level designation you want to use. Usually, you can make this copying part of your build/deployment process.
If you want to make just one particular file public in a directory and not everything found in that directory with it, then you can manually create individual routes for each file rather than use express.static() such as:
<script src="/bootstrap.min.js"></script>
And the code to create a route for that
app.get('/bootstrap.min.js', function(req, res) {
res.sendFile(__dirname + '/node_modules/bootstrap/dist/bootstrap.min.js');
});
Or, if you want to still delineate routes for scripts with /scripts, you could do this:
<script src="/scripts/bootstrap.min.js"></script>
And the code to create a route for that
app.get('/scripts/bootstrap.min.js', function(req, res) {
res.sendFile(__dirname + '/node_modules/bootstrap/dist/bootstrap.min.js');
});
I would use the path npm module and then do something like this:
var path = require('path');
app.use('/scripts', express.static(path.join(__dirname, 'node_modules/bootstrap/dist')));
IMPORTANT: we use path.join to make paths joining using system agnostic way, i.e. on windows and unix we have different path separators (/ and \)
As mentioned by jfriend00 you should not expose your server structure. You could copy your project dependency files to something like public/scripts. You can do this very easily with dep-linker like this:
var DepLinker = require('dep-linker');
DepLinker.copyDependenciesTo('./public/scripts')
// Done
If you want a quick and easy solution (and you have gulp installed).
In my gulpfile.js I run a simple copy paste task that puts any files I might need into ./public/modules/ directory.
gulp.task('modules', function() {
sources = [
'./node_modules/prismjs/prism.js',
'./node_modules/prismjs/themes/prism-dark.css',
]
gulp.src( sources ).pipe(gulp.dest('./public/modules/'));
});
gulp.task('copy-modules', ['modules']);
The downside to this is that it isn't automated. However, if all you need is a few scripts and styles copied over (and kept in a list), this should do the job.
The directory 'node_modules' may not be in current directory, so you should resolve the path dynamically.
var bootstrap_dir = require.resolve('bootstrap')
.match(/.*\/node_modules\/[^/]+\//)[0];
app.use('/scripts', express.static(bootstrap_dir + 'dist/'));
This is what I have setup on my express server:
// app.js
const path = require('path');
const express = require('express');
const expressApp = express();
const nm_dependencies = ['bootstrap', 'jquery', 'popper.js']; // keep adding required node_modules to this array.
nm_dependencies.forEach(dep => {
expressApp.use(`/${dep}`, express.static(path.resolve(`node_modules/${dep}`)));
});
<!-- somewhere inside head tag -->
<link rel="stylesheet" href="bootstrap/dist/css/bootstrap.css" />
<!-- somewhere near ending body tag -->
<script src="jquery/dist/jquery.js" charset="utf-8"></script>
<script src="popper.js/dist/popper.js" charset="utf-8"></script>
<script src="bootstrap/dist/js/bootstrap.js" charset="utf-8"></script>
Good Luck...
I didn't find any clean solutions (I don't want to expose the source of all my node_modules) so I just wrote a Powershell script to copy them:
$deps = "leaflet", "leaflet-search", "material-components-web"
foreach ($dep in $deps) {
Copy-Item "node_modules/$dep/dist" "static/$dep" -Recurse
}
I want to update this question with an easier solution. Create a symbolic link to node_modules.
The easiest way to grant public access to node_modules is to create a symbolic link pointing to your node_modules from within your public directory. The symlink will make it as if the files exist wherever the link is created.
For example, if the node server has code for serving static files
app.use(serveStatic(path.join(__dirname, 'dist')));
and __dirname refers to /path/to/app so that your static files are served from /path/to/app/dist
and node_modules is at /path/to/app/node_modules, then create a symlink like this on mac/linux:
ln -s /path/to/app/node_modules /path/to/app/dist/node_modules
or like this on windows:
mklink /path/to/app/node_modules /path/to/app/dist/node_modules
Now a get request for:
node_modules/some/path
will receive a response with the file at
/path/to/app/dist/node_modules/some/path
which is really the file at
/path/to/app/node_modules/some/path
If your directory at /path/to/app/dist is not a safe location, perhaps because of interference from a build process with gulp or grunt, then you could add a separate directory for the link and add a new serveStatic call such as:
ln -s /path/to/app/node_modules /path/to/app/newDirectoryName/node_modules
and in node add:
app.use(serveStatic(path.join(__dirname, 'newDirectoryName')));
I did the below changes to AUTO-INCLUDE the files in the index html. So that when you add a file in the folder it will automatically be picked up from the folder, without you having to include the file in index.html
//// THIS WORKS FOR ME
///// in app.js or server.js
var app = express();
app.use("/", express.static(__dirname));
var fs = require("fs"),
function getFiles (dir, files_){
files_ = files_ || [];
var files = fs.readdirSync(dir);
for (var i in files){
var name = dir + '/' + files[i];
if (fs.statSync(name).isDirectory()){
getFiles(name, files_);
} else {
files_.push(name);
}
}
return files_;
}
//// send the files in js folder as variable/array
ejs = require('ejs');
res.render('index', {
'something':'something'...........
jsfiles: jsfiles,
});
///--------------------------------------------------
///////// in views/index.ejs --- the below code will list the files in index.ejs
<% for(var i=0; i < jsfiles.length; i++) { %>
<script src="<%= jsfiles[i] %>"></script>
<% } %>
To use multiple files from node_modules in html, the best way I've found is to put them to an array and then loop on them to make them visible for web clients, for example to use filepond modules from node_modules:
const filePondModules = ['filepond-plugin-file-encode', 'filepond-plugin-image-preview', 'filepond-plugin-image-resize', 'filepond']
filePondModules.forEach(currentModule => {
let module_dir = require.resolve(currentModule)
.match(/.*\/node_modules\/[^/]+\//)[0];
app.use('/' + currentModule, express.static(module_dir + 'dist/'));
})
And then in the html (or layout) file, just call them like this :
<link rel="stylesheet" href="/filepond/filepond.css">
<link rel="stylesheet" href="/filepond-plugin-image-preview/filepond-plugin-image-preview.css">
...
<script src="/filepond-plugin-image-preview/filepond-plugin-image-preview.js" ></script>
<script src="/filepond-plugin-file-encode/filepond-plugin-file-encode.js"></script>
<script src="/filepond-plugin-image-resize/filepond-plugin-image-resize.js"></script>
<script src="/filepond/filepond.js"></script>
If you are linking to many files, create a whitelist, and then use sendFile():
app.get('/npm/:pkg/:file', (req, res) => {
const ok = ['jquery','bootstrap','interactjs'];
if (!ok.includes(req.params.pkg)) res.status(503).send("Not Permitted.");
res.sendFile(__dirname + `/node_modules/${req.params.pkg}/dist/${req.params.file}`);
});
For example, You can then safely link to /npm/bootstrap/bootsrap.js, /npm/bootstrap/bootsrap.css, etc.
As an aside, I would love to know if there was a way to whitelist using express.static

Socket IO, in which directory should i save my static javascript files

I am trying to include jquery in my socket io served file which is served like this -
app.get('/:file', function(req, res){
res.set('Content-Type', 'text/html');
res.sendfile('shrib.html');
});
Now in shrib.html when i try to send -
<script type="text/javascript" src="/jquery-1.11.0.min.js"></script>
or
<script type="text/javascript" src="jquery-1.11.0.min.js"></script>
I get the error of jquery not found, but when i try to use the CDN version of jquery it runs fine. In my directory structure i have the jquery-1.11.0.min.js in both the main directory and also in the node_modules directory yet i don't see it and get error like this -
Uncaught SyntaxError: Unexpected token < jquery-1.11.0.min.js:1
Uncaught ReferenceError: $ is not defined
did You mistaken socket.io with express?
Because Your problem looks like its related to express, not socketio, and i see no sockets here...
If yes, You should set static files like this:
app.use('/js', express.static(__dirname + '/js'));
put all js files in your project/js folder, and then do:
<script type="text/javascript" src="/js/jquery-1.11.0.min.js"></script>

Express-js can't GET my static files, why?

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?
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'));
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?
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'));
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.
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.
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">
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 :)
to serve static files (css,images,js files)just two steps:
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'));
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">
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')));
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:
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.
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.
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?
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.
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.
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.
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')
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.
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!
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)
Create a folder with 'public' name in Nodejs project
folder.
Put index.html file into of Nodejs project folder.
Put all script and css file into public
folder.
Use app.use( express.static('public'));
and in index.html correct path of scripts to <script type="text/javascript" src="/javasrc/example.js"></script>
And Now all things work fine.
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'))
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.
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

Resources