Error: Module "html" does not provide a view engine (Express) - javascript

I'm trying to set up a simple routing app but I keep running int the error when rendering a page.
Error: Module "html" does not provide a view engine.
What is odd is I've specified the view engine in my app.js file but I'm still getting the error
// app.js
var express = require('express');
var app = express();
var router = express.Router();
// Need to import the route file
var chef = require('./chef');
app.use('/chef', chef);
// Set directory to contain the templates ('views')
app.set('views', __dirname + '/views');
// Set view engine to use
app.set('view engine', 'html');
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
// chef.js
var express = require('express');
var routes = express.Router();
routes.get('/', (req, res) => {
//res.send("I'm here!")
res.render('chef');
});
module.exports = routes;
// views/chef.html
Some HTML file here here ..
In the chef.js file when I just want to test if the route is working I uncomment res.send ... which sends "I'm here" to the DOM.
However whenever I try res.render to render the chef.html page I get the error above. Which I find odd because I've set the view engine in app.js.
Suggestions on how to render my HTML file?

use res.sendFile('/fileName.html'); instead of res.render()
for sending file , we used res.sendFile(fullPath) and if you are using other than HTML language then you should have to use res.render().
res.render() for template like ejs, pug etc.

Related

Express.js Routing is not making sense

I'm working on an Express.js app and I think I am having trouble understanding the nuances of multi-layer routing. My app has the following segment of code in its app.js file:
//app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
//new stuff
const routes = require('./routes');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
// middleware functions required
app.use(logger('dev')); //handles logging
app.use(express.json()); //JSON payload parser
app.use(express.urlencoded({ extended: false })); //urlencoded payload parser
app.use(cookieParser());
//content routes
app.use('/jquery', express.static(__dirname + '/node_modules/jquery/dist/'));
app.use('/', express.static(path.join(__dirname, 'public'))); //static files (css and other js files)
app.use('/', routes); //everything else (see /routes/index.js)
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
.
.
.
As indicated in the code, after a bunch of static file and default middleware setup for logging and such, app.use('/', routes); is declared, handing off to an index.js file in the /routes folder as follows:
//index.js
//main router entry point, sets up all route modules
//instantiate the express.Router class
const express = require('express');
const router = express.Router();
//import our route modules
const indexRouter = require('./indexRouter');
const resetRouter = require('./resetRouter');
const enrollRouter = require('./enrollRouter');
//map individual route modules to their respective routes
router.use('/', indexRouter);
router.use('/reset', resetRouter);
router.use('/enroll(/*)?', enrollRouter);
module.exports = router;
The three router.use lines call individual route files in the same directory as shown. The first two are simple get routes. The third one (router.use('/enroll(/*)?', enrollRouter);) has both get and post components via the enrollRouter.js file as follows:
//enrollRouter.js
const express = require('express');
const router = express.Router();
const { getEnroller } = require('../controllers/enrollGetController');
const { postEnrollment } = require('../controllers/enrollPostController');
router.post(/^(\/enroll\/new)/i, postEnrollment);
//router.post('/', postEnrollment);
router.get('/', getEnroller);
module.exports = router;
Here's where things get interesting. I'm using postman to make a post request to "/route/new". If the route string for the post route in the code above is set to '/', everything works fine, and enrollPostController.js is called returning appropriate content. However, if I set the route string to '/enroll/new' instead (the path I'm calling... doesn't matter if it's a string or a regex), the 404 error code in app.js is called.
I'm not following what is going on. I'm under the impression that the string at the beginning of a router.get or router.post call represents the path to be matched for the callback defined as the next parameter. When the path is clearly the one specified, why am I getting a 404?
The way I'm thinking, when the /enroll/new post request comes in, app.js should hand off to index.js for all routes matching '/'. Then index.js should hand off to enrollRouter because the route matches '/enroll(/*)?'. And then finally, enrollRouter.js should call postEnrollment defined over in ../controllers/enrollPostController, because the route matches '/enroll/new'. But it doesn't work that way.
Can someone enlighten? or fill in the holes in my understanding?
Here's the code in enrollPostController.js
//enrollPostController.js
module.exports = {
postEnrollment(erq, res) {
//at this point we have the form submission data.
console.log(erq.body);
res.send("received form submission!");
},
};
Try the following:
routes/index.js
// Delegate "/enroll/*" to router
router.use('/enroll', enrollRouter);
routes/enrollRouter.js
// Handle POST requests to "/enroll/new"
router.post('/new', postEnrollment);
I hope this helps.
If you are following some pattern and only endpoints are getting changed for example
http://localhost:4000/mycode/testUrl/abc
http://localhost:4000/mycode/testUrl/Pqr/xyz
http://localhost:4000/mycode/testUrl/abc/xyz/pqs
const service = express.Router();
// **console** is just to check your endUrl. you can print originalUrl as well
service.get('/*', function(req, res) {console.log(req.url); }
service.post('/*', function(req, res) { console.log(req.url);}
app.use('/mycode/testUrl', service);
In your index.js
The express router defined as
router.use('/enroll(/*)?', enrollRouter);
passes the '/enroll/new' to your enrollRouter.js
so all you need to give the "/" in the post route, so the "/enroll/new" is right in front of it but due to nesting of routes we can separate them.
Hope I answered the question.

A routing problem with workbox vuejs in production and express

I am creating a forum application to learn about VueRouter in Express. What I am trying to do is create a routing in vuejs and then take it to production. When I compile everything works fine. The view files go directly to the public folder in express and work almost perfect. I can change the route perfectly but when I touch CTRL + F5 from a different route to the main one, it returns a GET error.
For example this is my index and work perfect:
I can even change the route:
I touch F5 and reload the page without any problem, but when I touch CTRL + F5 to make the request again, obviously it returns an error because I don't have the route declared in express,
but vuejs returns only one html index as a view, I can't render any other files because they don't exist.
These public folder at image are the files created by vue by the build command:
This is my express configuration:
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersNotifications = require('./routes/notifications');
var usersNotifications = require('./routes/notifications');
var app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/notifications', usersNotifications);
module.exports = app;
this is my index route on express:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index');
});
module.exports = router;
The only option I have is to render the only index that vuejs offers. How can i Fix that?
The other problem is that I would not like these console workbox messages, how can i remove them so they never appear:
and this is the vuejs registerServiceWorkers.js file:
/* eslint-disable no-console */
import { register } from 'register-service-worker'
if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
/***
* Note that here were some methods also display messages
* on the console and I deleted them. Methods like
*/
})
}
Any ideas?
Since vue router is handling page routing, you'll have to render index for all requested paths like:
router.get('*', function(req, res, next) {
res.render('index');
});
// in server
app.use('*', indexRouter);
If you're exposing other endpoints from server you'll have to mount this as the last route middleware like, say in your case:
app.use('/notifications', usersNotifications);
app.use('*', indexRouter);

Basic form page in Express JS

i am really new to Node Js and Express Js and i am following the (book)[http://www.sitepoint.com/store/jump-start-node-js/] to learn Node Js.
In the book the author created a simple page for simple Login Form. I am following that but getting 404 Not found.
Not Found
404
Error: Not Found
at Layer.app.use.res.render.message [as handle] (/Applications/MAMP/htdocs/resto/app.js:29:15)
at trim_prefix (/Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:240:15)
at /Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:208:9
at Function.proto.process_params (/Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:269:12)
at next (/Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:199:19)
at next (/Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:176:38)
at /Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:137:5
at /Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:250:10
at next (/Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:160:14)
at next (/Applications/MAMP/htdocs/resto/node_modules/express/lib/router/index.js:176:38)
I added the following code in App.js
var fs = require('fs');
app.get('/form', function(req, res){
fs.readFile('.views/form.html', function(error, content){
if(error){
res.writeHead(500);
res.end();
}
else{
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(content, 'utf-8');
}
});
});
and then created a file form.html in Views folder in which i created a simple html form.
This didnt work for me, so following the flow of default index.jade, i created a file form.js and added the following code in it
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/form', function(req, res) {
res.render('form');
});
module.exports = router;
Which also did not work. I am sure i am doing something wrong but i do not know where.
Please help, Thanks
Assuming you have those files :
-- app.js
-- routes (folder containing root.js)
-- views (folder containing form.jade)
Then, in your app.js :
var path = require('path');
var express = require('express');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use('/', require('./routes/root')); // Say that all the routes defined in root.js will start with http://yourdomain.com/
And in root.js :
var express = require('express');
var router = express.Router();
/* GET http://yourdomain.com/form */
router.get('/form', function(req, res) {
res.render('form'); // Render form.jade view
});
Of course, this is really minimalist and you'll have much more things to do... but I hope this will help you to better understand node.js using Express
Express Router documentation
I am new to NodeJS and Express too but I think the problem is that you never declare where to find the form.html file. Right before the app.get('/form',....), put app.use(express.static(__dirname+'put the directory your form.html is in or dont put anything if it's not in a directory')); this way express knows where to find the form.html and you shouldn't get a 404 anymore
Express provides a sendFile function in the response object, which allows you to do this:
app.get('/form', function(req, res){
res.sendFile('./views/form.html', {root: __dirname}, function(error, content){
if(error){
res.writeHead(500);
res.end();
}
});
});
The jade renderer isn't used in this case.

Using Route of express node.js but express.Router getting as undefined

My code of router from default routes/index
/* GET home page. */
exports.index = function(req, res){
res.render('user', { title: 'Abcd' });
};
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.render('index', { title: 'Express' });
});
router.get('/helloworld', function(req, res) {
res.render('helloworld', { title: 'Hello, World!' })
});
module.exports = router;
getting error as can not call method get of undefined.I am new in node js please anyone help me.
Try upgrading to Express 4.x. You are probably running a 3.x flavor.
Router is a middleware of express which is registered implicitly with the express object the first time post() or get() is used. You can but don't have to add this explicitly calling use(), which allows you to register various middleware with express and so allows configuring processing and behavior in consideration of precedence.
Correct initialization and usage might look like this:
EDIT: Changed the example to be a "complete" http server.
app.js
var http = require('http');
var express = require('express');
// Requiring express exports a function that creates the application. Call it!
var app = express();
// Set port to listen to
app.set('port', process.env.PORT || 3000);
// Set view engine
app.set('view engine', 'jade');
// Tell express to use the router middleware
// Can be omitted if precedence doesn't matter
// (e.g. for loading static resources)
app.use(app.router);
// Add callback handler for home (/) route
app.get('/', function(req, res) {
res.render('index', { title: 'Express' });
});
// Create http server by passing "app" to it:
http.createServer(app).listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
});
Now, if you place a minimal view into the default folder for views...
views/index.jade
doctype 5
html
head
meta(charset='utf-8')
title #{title}
meta(name='viewport', content='width=device-width, initial-scale=1.0')
body
div
h1 Gotcha! Title is "#{title}"
... and start your server from the console with...
$ node app.js
...you should have your first node/express/jade powered app up and running!

How to set path to partials in Node.js with Express, Handlebars and Conslidate

I have a working Node.js site, using Express.js, Handlebars.js and Consolidate.js. I want to use partials for common parts of my templates, but can't work out how to make them work for pages at different URLs.
My /views/ directory contains this:
_footer.html
_header.html
article.html
index.html
The relevant parts of my Node app looks something like:
var express = require('express'),
consolidate = require('consolidate'),
handlebars = require('handlebars'),
path = require('path');
var app = express();
app.engine('html', consolidate.handlebars);
app.set('view engine', 'html');
app.set('views', path.join(__dirname, '/views'));
var partials = {header: '_header', footer: '_footer'};
app.get('/', function(req, res) {
res.render('index', {partials: partials});
};
app.get(/^\/([\w-]+)\/$/, function(req, res) {
res.render('article', {partials: partials});
};
And in my index.html and article.html Handlebars templates I have something like:
{{> header}}
<!-- page content here -->
{{> footer }}
I should be able to access both / (when index.html is rendered) and /foo/ (when article.html is rendered). But it only works for whichever I try to access first after starting the Node server. When I then navigate to the other path, I get errors like:
Error: ENOENT, no such file or directory '/Users/phil/Projects/projectname/views/<!DOCTYPE html>...
with the rest of the _header.html partial following.
I assume I need to somehow set the path to my partials to be absolute somehow, but I can't see how to do that.
For consolidate check that : https://github.com/tj/consolidate.js/issues/18
I would recommend to switch to something a bit more specific like that https://github.com/donpark/hbs it will be simpler.
I had the same exact issue. It seems that consolidate is reusing the "partials" object that you pass, replacing the values with the file content (yuck!).
A workaround is to create a new "partials" object every time. If you don't want to rewrite the whole object every time, you can use a function returning the object literal.
In your case something like the following should work:
var express = require('express'),
consolidate = require('consolidate'),
handlebars = require('handlebars'),
path = require('path');
var app = express();
app.engine('html', consolidate.handlebars);
app.set('view engine', 'html');
app.set('views', path.join(__dirname, '/views'));
var partials = function() {
return {header: '_header', footer: '_footer'};
}
app.get('/', function(req, res) {
res.render('index', {partials: partials()});
};
app.get(/^\/([\w-]+)\/$/, function(req, res) {
res.render('article', {partials: partials()});
};
Not really elegant, but I don't think there is really a way to keep it simpler.

Categories