I'm getting ReferenceError: main is not defined
when I open up the http://localhost:3000/
Here I try to open up the main.html located in views directory
This is my app.js
const express = require('express'),
app = express(),
config = require('./config/index'),
routes = require('./routes/route');
app.use(express.static(`${__dirname}/public`));
app.use(express.static(`${__dirname}/views`));
app.use('/',routes);
app.listen(config.port,()=>{
console.log(`Listing at port ${config.port}`)})
This is my route.js
const express = require('express'),
router = express.Router(),
helpers = require('../helpers/index');
router.route('/')
.get(helpers.index)
module.exports = router
This is my helpers/index.js
var user = require('../user/user');
exports.index = (req,res)=>{
if(user.name == ''){
res.sendFile(main.html);
}
else{
res.sendFile(chat.html)
}
}
module.exports = exports;
Directory Structure
>helpers
>index.js
>routes
>route.js
>user
>user.js
>views
>main.html
>chat.html
app.js
pacakage.json
Change:
res.sendFile(main.html);
to:
res.sendFile("main.html");
Without the quotes, it's trying to interpret main as a Javascript object which it looks for the .html property on. But, there is apparently no object named main so you get ReferenceError: main is not defined. You want to pass a string here instead.
Same for res.sendFile("chat.html");
If the files are not local to this module's directory, then you need to build a more complete path that specifies their location. Given the file hierarchy you show, I think that might be something like this:
const path = require('path');
const options = {root: path.join(__dirname, "../views")};
res.sendFile("main.html", options);
var user = require('../user/user');
var path = require('path');
exports.index = (req,res)=>{
if(user.name == ''){
res.sendFile(path.resolve('views/main.html'));
}
else{
res.sendFile(path.resolve('views/chat.html'))
}
}
module.exports = exports;
In addition to jfriend00's answer, you must also, build the correct absolute path, using the global __dirname variable in node.
So your path will be something like: res.sendFile(__dirname + "/main.html")
or, depending on your folder structure: res.sendFile(__dirname + "/someadditionalfoldrs/main.html")
or, construct the path using "./" if applicable, like "./main.html";
Related
I am working on an expressJS project. I have a route file named send_email.js, and I want to use parts of this file from two different places. These places are index.js and user.js.
So I added the following line for both of index.js and users.js:
const send_email = require("./send_mail");
But user.js is giving me an error because send_email is undefined. And then I just delete the same line from index.js and everything goes fine. I can reach send_mail in user.js, and it is what I expect.
Am I overlooking something about requiring files in expressJS? I can use this technique effectively in other projects. Are there expressJS specific things which cause this error?
I created same situation in another tiny project and its' codes like these:
// ------------------------index.js -----------------------
const express = require("express");
const app = express();
/* if coment this two line every thing goes fine */
const mylog = require("./deneme1").mylog;
mylog();
/* if coment this two line every thing goes fine */
const yourlog = require("./deneme2").yourlog;
const route = require("./deneme1").route;
console.log('route :', route);
yourlog();
app.get("/", (req, res)=>{
res.send("OK!");
})
app.listen(3000, () => { "listening on "+3000});
// --------------deneme1.js -------------------------
const express = require("express");
const route = express.Router();
const yourlog = require("./deneme2").yourlog;
console.log('yourlog mmm:', yourlog);
route.get("/deneme", function(req, res){
mylog();
res.send("OK!");
});
function mylog () {
console.log("mylog in deneme1.js");
};
module.exports.route = route;
module.exports.mylog = mylog;
// ------------------deneme2.js-----------------
const express = require("express");
const route = express.Router();
const mylog = require("./deneme1").mylog;
console.log('mylogxx :', mylog);
function yourlog(){
console.log("yourlog deneme2");
mylog();
console.log("----");
}
module.exports.yourlog = yourlog;
deneme1.js and deneme2.js require each other and express.js require both of deneme1.js and deneme2.js.
Did you export in your send_mail.js file? You should export whatever function you want to reuse . And use import wherever you need it. Instead of require.
For reference :MDN
I have realized that my problem is related "cyclic dependencies" between my route files. It is kind of design mistake. And there is a stackoverflow question/solution about it:
how-to-deal-with-cyclic-dependencies-in-node-js
I'm using the handlebars.js hbs wrapper in express.js. I have templates working fine, but I'm needing to add in partials to be rendered with my views.
I'd like to do something like this:
hbs.registerPartial('headPartial', 'header');
// where "header" is an .hbs file in my views folder
However, it's throwing a "header partial can not be found".
I can make the registerPartial work if I pass a string of html to the second param, but I'd like to use separate view files for my partials.
I haven't found any documentation on this, but hoping I may just be missing something easy.
Does anyone know how to use view files in the registerPartial method? If so, how do I implement this?
UPDATE
To give more context, let me add more code.
Here is my "server" file - app.js
var express = require('express')
, routes = require('./routes')
, hbs = require('hbs');
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'hbs');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// this is the line that generates the error
hbs.registerPartial('headPartial', 'header');
// What I'm expecting is for "headPartial" to be a compiled template partial
// of the template within views/header.hbs, but it is not loading this way.
// If I do something like hbs.registerPartial('headPartial', '<p>test</p>');
// then it does work. I need to know how to pass an .hbs file to the
// registerPartial method.
// Routes
app.get('/', routes.index);
app.listen(3000);
And here is my routes.index file:
exports.index = function(req, res){
res.render('index', { title: 'Express' })
};
In my views folder, I have three templates:
views/
header.hbs (this is my partial)
index.hbs
layout.hbs
In my index.hbs file, I'm calling the 'headPartial' partial with:
{{> headPartial}}
Any help is greatly appreciated.
For convenience, registerPartials provides a quick way to load all partials from a specific directory:
var hbs = require('hbs');
hbs.registerPartials(__dirname + '/views/partials');
Partials that are loaded from a directory are named based on their filename, where spaces and hyphens are replaced with an underscore character:
template.html -> {{> template}}
template 2.html -> {{> template_2}}
login view.hbs -> {{> login_view}}
template-file.html -> {{> template_file}}
Cheers!
This code loads all the partial templates in a directory and makes them available by filename:
var hbs = require('hbs');
var fs = require('fs');
var partialsDir = __dirname + '/../views/partials';
var filenames = fs.readdirSync(partialsDir);
filenames.forEach(function (filename) {
var matches = /^([^.]+).hbs$/.exec(filename);
if (!matches) {
return;
}
var name = matches[1];
var template = fs.readFileSync(partialsDir + '/' + filename, 'utf8');
hbs.registerPartial(name, template);
});
Looks like creating a variable and pulling in the template code manually works:
var hbs = require('hbs')
, fs = require('fs')
, headerTemplate = fs.readFileSync(__dirname + '/views/_header.hbs', 'utf8');
and later:
hbs.registerPartial('headPartial', headerTemplate);
For me I had template file my-partial.hbs
Then I tried to access them via:
{{> my-partial }}
But the partial was stored in hbs as my_partial regardless of the filename.
This is thanks to hbs version 3.1.0 line 218
.slice(0, -(ext.length)).replace(/[ -]/g, '_').replace('\\', '/');
This is in the readme
For me, I have a function like:
var hbs = require('hbs');
var fs = require('fs');
var statupfunc = {
registerHbsPartials : function(){
//this is run when app start
hbs.registerPartials(__dirname + "/" + resource.src.views + '/partials');
},
registerOneHbsPartials : function(event){
//this is run for gulp watch
if(event.type == 'deleted')
{
return;
}
var filename = event.path;
var matches = /^.*\\(.+?)\.hbs$/.exec(filename);
if (!matches) {
return;
}
var name = matches[1];
var template = fs.readFileSync(filename, 'utf8');
hbs.registerPartial(name, template);
}
};
Run statupfunc.registerHbsPartials at app startup and then register gulp watch with statupfunc.registerOneHbsPartials to register partials on new creation
gulp.task('watch', function() {
gulp.watch(resource.src.views + '/partials/*.*', statupfunc.registerOneHbsPartials);
});
My app structure (using ExpressJS & HBS-NPM) is:
APP FOLDER
-src
app.js
- routers
- views
-- partials
header.hbs
const hbs = require('hbs')
hbs.registerPartials(path.join(__dirname,'views','partials'))
The above does the job of loading all partials in a single shot. Use this as long as you believe it doesn't impact your performance (loading all partials, even if not required).
And then, use this partial in any HBS file as follows:
{{> partial_file_name_without_hbs_extension}}
Example
{{> header}
I am new to nodejs. I want to create a very simple website which has 3 pages. In every page I want to display an image to make the pages look uniform.
My code looks like this:
/**
* Module dependencies.
*/
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var fs = require('fs');
var mail = require("nodemailer").mail;
/*List of variables*/
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.get('/main', function(req, res) {
fs.readFile('./home.html', function(error, content) {
if (error) {
res.writeHead(500);
res.end();
}
else {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(content, 'utf-8');
}
});
});
/* After this I have code for post event - all these navigation works perfectly fine*/
in home.html file I have an image to display:
/*Header part of HTML file*/
<body>
<img class="logo" src="./Heading.png" alt="My_Logo">
console.log (src);
<h1 class="center">Welcome to message reprocessing</h1>
</br>
</body>
This image is not displayed in my browser. When I check my console I have this error:
GET http://localhost:3000/Heading.png 404 (Not Found)
Please help, thanks
First, you have to set the public (folder) as static under server.js file
server.js
// configure our application
const Express = require('express');
const app = new Express();
.......
.......
app.use(Express.static(__dirname+'/public'));
.......
then your img source will be
<img class="logo" src="/images/Heading.png" alt="My_Logo">
and here the folders structure would be -
project(root folder) \ public \ images\ Heading.png
Thanks for your answers.I had tried using absolute path already with no luck. However one of my friend suggested as below:
<img class="logo" src="http://localhost:3000/images/Heading.png" alt="My_Logo">
and keep the Heading.png file in public/images directory.
Thanks all.
Okay, its not with express.js, but here is a snippet of my code that handles images and external javascripts, but has a protection:
function handler (req, res){
var pathname = url.parse(req.url).pathname;
var isImage = 0, contentType, fileToLoad;
var extension = pathname.split('.').pop();
var file = "." + pathname;
var dirs = pathname.split('/');
if(pathname == "/"){
file = "index.html";
contentType = 'text/html';
isImage = 2;
}
else if(dirs[1] != "hidden" && pathname != "/app.js"){
switch(extension){
case "jpg":
contentType = 'image/jpg';
isImage = 1;
break;
case "png":
contentType = 'image/png';
isImage = 1;
break;
case "js":
contentType = 'text/javascript';
isImage = 2;
break;
case "css":
contentType = 'text/css';
isImage = 2;
break;
case "html":
contentType = 'text/html';
isImage = 2;
break;
}
}
if(isImage == 1){
fileToLoad = fs.readFileSync(file);
res.writeHead(200, {'Content-Type': contentType });
res.end(fileToLoad, 'binary');
}
else if(isImage == 2){
fileToLoad = fs.readFileSync(file, "utf8");
res.writeHead(200, {'Content-Type': contentType });
res.write(fileToLoad);
res.end();
}
This assuming that you have your app.js and index.html in your root, you can have folders like /css, /img, /js etc. But the app.js and content inside your /hidden folder is unable to reach, but files in your root is still accessable.
If you want a quick solution, do this: instead of this <img class="logo" src="./Heading.png" alt="My_Logo"> use:
<img class="logo" src="your file path /Heading.png" alt="My_Logo">
Still not working?
check image spelling, file extension(png) because png and PNG are different in live server(case sensitive).
and verify
path.join(__dirname, 'public')
too
Index.js
Inside this file, add the code below to give the directory name to your index.js (server), in a way it is based on your actual directory path.
app.use(express.static(path.join(__dirname, "/public")));
Directory Structure
now inside Index.ejs (you HTML page) add the code below to insert your image and make it visible.
<div id="main-content">
<img src="img\navthome" />
</div>
Notice inside IMG tag we set the SRC as "img\navthome.gif", here we don't need to declare all the path since we already declared the __dirname, and the PUBLIC folder inside index.js
I hope it can helps you with your issue :D
One of the problems I had was that I wanted to define a few specific paths and I found the best answer in the link below.
https://www.geeksforgeeks.org/how-to-fetch-images-from-node-js-server/
// Requiring module
const express = require('express');
// Creating express object
const app = express();
// Defining port number
const PORT = 3000;
// Function to serve all static files
// inside public directory.
app.use(express.static('public'));
app.use('/images', express.static('images'));
// Server setup
app.listen(PORT, () => {
console.log(`Running server on PORT ${PORT}...`);
})
I did the following in my program:
Shows the structure of folders and files here
root
> client
> node_modules
> folder_1
> folder_2
> package.json
> server.js
And on my server I define that folder_1 in fl1 path and folder_2 in fl2 path each have a separate static path. And the interesting thing is that I do not use the original name of those folders and I give it my own route.
// Requiring module
const express = require('express');
const path = require('path');
// Creating express object
const app = express();
// http://localhost:3000/fl1/...
app.use('/fl1',express.static(path.resolve(__dirname,'folder_1')));
// http://localhost:3000/fl2/...
app.use('/fl2',express.static(path.resolve(__dirname,'folder_2')));
// Server setup
app.listen(3000, () => {
console.log(`Running server on port 3000`);
})
After running the server to access this path is enough to use the following path to access its contents.
Note that you must specify the internal routes accurately. For example, the subfolders and file name must be specified. main path /folder_1/img/image_1.png in url /fl1/img/image.png.
i want to route in multiple files
var routes=require('./routes');
in the routes/index.js
exports.inicio=require('./inicio')
exports.home=require('./home')
in the inicio.js
exports.index=function(req,res){res.render('index/index',{title: 'Bienvenido a Inmoweb'});}
in the home.js
exports.nosotros=function(req, res){res.render('index/nosotros',{title:'Nosotros'});}
when i console.log(routes)
{
inicio: {index:[function]},
home: {nosotros:[function]}
}
so i call in app
app.get('/',routes.inicio.index);
but i want to call like this
app.get('/',routes.index);
app.get('/nosotros',routes.nosotros);
and the console.log supose to be????
{
index:[function],
nosotros:[function]
}
how to do that??? tnx all
Your routes/index.js can do the following:
exports.index = require('./inicio').index
exports.nosotros = require('./home').nosotros
You can make this even shorter by assigning directly to module.exports in inico.js:
module.exports = function(req,res){res.render('index/index',{title: 'Bienvenido a Inmoweb'});}
Now you can do this in routes/index.js:
exports.index = require('./inicio') //See the difference?
// require('./inicio') now directly exports your route
exports.nosotros = require('./home').nosotros
Get the idea? :)
I just started using a new version of Express (2.5.5) that by default creates a ./routes directory along with ./views and ./public
Inside of routes there is a index.js file which contains:
/*
* GET home page.
*/
exports.index = function(req, res){
res.render('index', { title: 'Express' })
};
by default (after running express from the commandline) and this is the routes section in the main app.js:
// Routes
app.get('/', routes.index);
I've set up a variable for a redis client in the main app.js:
var redis = require('redis'),
db = redis.createClient();
and I was wondering how I could access the methods of db (and whatever other modules I require in app.js) in the files contained in ./routes
I really liked Jamund's solution, but I would extend the concept to this:
// db.js
var redis = require('redis');
module.exports = redis.createClient();
// index.js
var db = require(.'/db')
// whatever other file
var db = require(.'/db')
// do something with db
db.disconnect();
both db on index and other file would get the same instance of the redis client
Just call this at the top of your files. Requires are in a shared space, so you can re-require the file multiple times and it will always reference the same version. If you want to be fancy you can create your own db module that does something like this, to prevent double creating clients:
// db.js
var db
var redis = require('redis')
exports.connect = function() {
if (!db) db = redis.createClient()
return db
}
exports.disconnect = function() {
redis.quit()
db = null
}
// index.js
var dbHelper = require(.'/db')
var db = dbHelper.connect()
// whatever other file
var dbHelper = require(.'/db')
var db = dbHelper.connect() // won't connect twice
You can either create an app global and hang the vars you want to share off that or you can use an initializer function in your routes file
f.e.
// app.js
var app = express.createServer()
, db = require('redis').createClient();
require('./routes').with(app, db);
// routes.js
module.exports.with = function(app, db) {
app.get('/',function(r,s) { s.end('Sweet');});
}