Other than a nice way to require all files in a directory (node.js require all files in a folder?), what is index.js used for mainly?
When you pass a folder to Node's require(), it will check for a package.json for an endpoint. If that isn't defined, it checks for index.js, and finally index.node (a c++ extension format). So the index.js is most likely the entry point for requiring a module.
See the official Docs here: http://nodejs.org/api/modules.html#modules_folders_as_modules.
Also, you ask how to require all the files in a directory. Usually, you require a directory with an index.js that exposes some encapsulated interface to those files; the way to do this will be different for ever module. But suppose you wanted to include a folder's contents when you include the folder (note, this is not a best practice and comes up less often than you would think). Then, you could use an index.js that loads all the files in the directory synchronously (setting exports asynchronously is usually asking for terrible bugs) and attaches them to module.exports like so:
var path = require('path'),
dir = require('fs').readdirSync(__dirname + path.sep);
dir.forEach(function(filename){
if(path.extname(filename) === '.js' && filename !== 'index.js'){
var exportAsName = path.basename(filename);
module.exports[exportAsName] = require( path.join( __dirname, filename) );
}
});
I hardly ever see people wanting to use that pattern though - most of the time you want your index.js to go something like
var part1 = require('./something-in-the-directory'),
part2 = require('./something-else');
....
module.exports = myCoolInterfaceThatUsesPart1AndPart2UnderTheHood;
Typically in other languages the web server looks for certain files to load first when visiting a directory like / in priority, traditionally this is either: index or default. In php it would be index.php or just plain HTML it would be index.html
In Node.js, Node itself is the web server so you don't need to name anything index.js but it's easier for people to understand which file to run first.
index.js typically handles your app startup, routing and other functions of your application and does require other modules to add functionality. If you're running a website or web app it would also handle become a basic HTTP web server replacing the role of something more traditional like Apache.
Here is a good article explaining how Node.js looks for required module https://medium.freecodecamp.org/requiring-modules-in-node-js-everything-you-need-to-know-e7fbd119be8, with folder and index.js file
Modules don’t have to be files. We can also create a find-me folder
under node_modules and place an index.js file in there. The same
require('find-me') line will use that folder’s index.js file:
~/learn-node $ mkdir -p node_modules/find-me
~/learn-node $ echo "console.log('Found again.');" > node_modules/find-me/index.js
~/learn-node $ node
> require('find-me');
Found again.
{}
>
Late to the party but the answer is simply to allow a developer to specify the public api of the folder!
When you have a bunch of JavaScript files in a folder, only a small subset of the functions and values exported from these files should exportable outside of the folder. These carefully selected functions are the public apis of the folder and should be explicitly exported (or re-exported) from the index.js file. Thus, it serves an architectural purpose.
Related
I have a project by Three.js.
Like below pic, i have an index.html that uses js codes from scripts.js (in sub-Directory of js).
also, this scripts.js , uses three and OrbitControls libs of package of three.js.
PROBLEM:
after running my project, browser, shows HTML and CSS fine, but it do not works by javascript and gives this error:
i can't find any solution, after half a Day searching & manipulating!
can any one help please?
1)project structure:
root
|------server.js
|------/public
| |---index.html
| |---/js/scripts.js
| |---/css/index.css
2)root/public/index.html:
3)root/public/js/scripts.js:
4)root/server.js:
const express = require("express");
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, '/public')));
app.get('/',function(req,res) {
res.sendFile("public/index.html")
});
app.listen(3000, () => {console.log("listening on port 3000");});
Multiple things going on here. First, require() is nodejs ONLY, is not present in the browser. You are trying to load and run js/scripts.js in the browser and thus cannot use require() in that script.
Separately, when you use type="module" in a script tag, that means the module is an ESM module which can use import to load other modules, but import needs to specify a URL that your express server will handle and serve the right file with.
I'm also guessing that you will have a problem loading the script files because they need to be served by express.static() in your server and need to have the appropriate URL paths in your web page so that express.static() will work. You don't show the server-side file structure for all those scripts so it's hard for us to know exactly what the URLs should be.
And, in the future, please don't ever post screen shots of code. That makes it a lot harder for us to use your code in tests or in answers (because we have to retype it all from scratch) and it can't be searched, is harder to read on mobile, etc... Don't put code in images.
I'm trying to serve static file uploaded using ExpressJS and NodeJS with Typescript but getting 404 error.
the file I want to read is ./src/data/uploads/test.txt and I'm trying to access it from web browser directly.
Note: When I do it in Javascript it worked but not in Typscript.
index.ts file (app entry point)
import express from 'express';
import bodyParser from 'body-parser';
import helmet from 'helmet';
import {cdg, config} from './utils';
import {Mongoose} from './db/monogdb';
import { setRoutes } from './routes/route.decorators';
import cors from 'cors';
import './routes';
const app = express();
app.use(helmet());
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use('/ftp', express.static('data/uploads'));
setRoutes(app);
app.listen(config.server.port, () => {
cdg.konsole("Server connected! :: " + config.server.port + "!");
});
Is there a specific way to serve static file with Typescript ?
Here's how express.static() works. You are apparently missing one of these steps, but your question is short of the details to identify exactly which step is not correct.
First, you define an express.static() middleware that contains some parameters. In your case, you've defined this:
app.use('/ftp', express.static('data/uploads'));
There are four elements that determine how this works:
The /ftp that must be at the start of any URL for this middleware to match.
The incoming URL request and how it was formed by the browser based on how you specified it in your HTML.
The current working directory that is combined with data/uploads to make a full path reference or you could build your own absolute path and not depend upon the cwd.
The files in cwd + /data/uploads that express.static() will attempt to match to the path of the incoming URL.
Let's look into these further:
Your middleware will first only look at URLs that start with /ftp. And, then for any URL it sees that does start with /ftp, it should take the rest of the URL and append it to data/uploads and see it finds a matching file in your local file system. It will use the current working directory in your server process at the time of the request to try to resolve the relative path data/uploads. That current working directory (if you haven't programmatically changed it) will depend upon how your app was started.
So, if you started your app with node index.js, then the current working directory will be the directory where index.js is located and express static will be looking in the data/uploads sub-directory below where 'index.js` is.
Then, we need to look at how the HTML tag that specifies this static resource is specified.
Let's say this is an <img> tag for example. If you specify something like this:
<img src="/ftp/hello.jpg">
Then, the browser will create a request to your server for /ftp/hello.jpg. Since that does start with /ftp, your express.static() middleware will take the rest of the path /hello.jpg and append that to data/uploads and build a path that looks like this:
path.join(process.cwd(), 'data/uploads', '/hello.jpg')
And, it will look for that resulting file in your local file system. If it finds that file, then it will serve that file and return it as the response. If it doesn't find that exact file, then it will call next() and continue routing to your other route handlers.
There are a number of common mistakes (things that can go wrong):
You don't specify the correct URL in your web page that lines up with your express.static() middleware line (including the /ftp prefix that your middleware specifies).
Your middleware isn't quite pointing at the right directory in your file system so it never finds anything.
You are using relative URLs in your web page which the browser combines with the path of your web page causing it to request something different than you want. Static resource URLs in your web page should nearly always start with / so they are not dependent upon the path of the parent page.
The files aren't quite properly located in the file hierarchy you are pointing to with your middleware (often off by one level).
One other thing I will mention. Since you're using TypeScript, that means you have to compile/build your script into a regular .js script before it can be run. This will typically be in a different directory location.
This different directory location creates opportunities for you to not be referencing the proper directory where your static resources are, since they are probably located relative to your TypeScript files, not the built Javascript files that you're running (that depends upon your build script).
Again, if you show us where everything is in your file system (TypeScript files, built JS files, static resources) and what the HTML tag that references the static resource looks like, we can help you debug that more specifically.
In my case I solved my problem like this: in the parameter relative to the directory path I used path.resolve and in its first parameter I used __dirname as the first parameter and the relative path of the target directory as the second one.
app.get('/', express.static(path.resolve(__dirname, '../static/'))); –
Node.js is special because the backend and frontend use the same language. I wanted to take advantage of this and only write 1 set of util functions (universal functions like numToPercent) for backend and frontend. Here is how my (important) files are structured right now:
project
public
index.html
index.js
scripts
script1.js
index.js
otherScript.js
Where is the canonical location to put my util file?
Edit: to make this more specific, is there a "shared" folder or something to put this file? Because otherwise public seems like the best place to put this
You can package the shared code and add it as a dependency via npm.
I want to get an array of file names from my project public/logos folder. I am using create-react-app template and as you guess, I can not use const fs = require('fs') in browser after project start.
So, is there any way to fill an array right after npm start command and getting file names array from folder or am I out of context?
const fs = require('fs')
const path = require('path')
const appRoot = require('app-root-path').path
const getNames = () => {
fs.readdir(path.join(appRoot, "public", "logos"), (err, files) => {
return files
})
}
Although the Sathishkumar is correct, it's not the only way: having an application server just for reading static images can be too much in many situations.
What you can do is to handle this by change the webpack configuration (this requires you eject first so be really careful).
From webpack you have all of the Nodejs features available but you must make those changes static for the webapp.
An idea:
manually copy with html-copy-plugin every image in the dist folder
read every image file in that folder from node and generate a list of image names
put the list of images as a global variable in your bundle by using webpack DefinePlugin
Now you will be able to read images names from this new global.
Note: this will not be a dynamic read of resources in a folder. If add/remove images you will be forced to repeat the build process of the app.
Yes. It is out of context. Not possible in browser-based JS application. You can't access the file system using Javascript in the browser.
You can use a NodeJS(or any other language for the same) to create a REST API as you mentioned which will return the files list and then can consume it(APIs like fetch or package - axios) in the frontend. This is the preferred way of doing.
If you need to read the files from file system you need to start server, like express, and then read this files on the server by request from frontend or by the link you pasted in your browser address field.
I never thought this would be a problem with Node.js and Express, but on a crazy whim I decided to type into a browser the location of one of the source files in my Node.js Express project - something like:
http://www.mywebsite.com/mynodejsapp/app.js
To my extreme horror, my application's source code popped right up, publicly available for all to see.
So, that aside: how do I stop it in Node.js / Express?
My setup code is pretty straightforward:
var app = express();
app.configure(function() {
app.use(express.static('/home/prod/server/app/public'));
});
app.listen(8888);
To clarify, this is what my folder structure looks like:
/home/prod/server/
/home/prod/server/app.js
/home/prod/server/public/
All sorts of various files that are intended for public access live under /public. All of my server source code lives under /server/, and my understanding of Express's static folder configuration is that the static folder is the only place that Express happily serves up files from the filesystem from.
Any ideas?
From what you posted it really smells like the URL you entered is served by e.g. Apache/nginx/... and you did put your node app within the document root. The answer is simple in this (and any similar) case:
You never put any of your sourcecode files within the document root or another HTTP-accessible folder. In your case, /home/prod/server/app/public should contain only client-side stuff (HTML, CSS, Graphics, (minified) client-side JS) and nginx should not have anything above this folder as its document root.