I have the following output section specified in my webpack.config.js:
output: {
path: path.resolve(__dirname, 'dist/'),
publicPath: '/'
},
I then have my express server set up like this:
const path = require('path');
const express = require('express');
const webpack = require('webpack');
const config = require('./webpack.config.dev');
const app = express();
const compiler = webpack(config);
var host = config.host || 'localhost';
var port = (Number(config.port) + 1) || 4040;
const serverConfig = {
contentBase: 'http://' + host + ':' + port,
quiet: true,
noInfo: true,
hot: true,
inline: true,
lazy: false,
headers: {'Access-Control-Allow-Origin': '*'},
stats: {colors: true},
publicPath: '/'
};
app.use(express.static(__dirname + '/public'));
app.use(require('webpack-dev-middleware')(compiler, serverConfig));
app.use(require('webpack-hot-middleware')(compiler));
const indexFile = path.join(__dirname, './client/public/index.html');
app.use(express.static(__dirname + './build'))
app.get('*', function(req, res) {
console.log(req.originalUrl);
res.sendFile(indexFile);
});
app.listen(4040, 'localhost', function(err) {
if (err) {
console.log(err);
return;
}
console.log('Listening at http://localhost:4040');
});
When I am at the root url, i.e. '/' then the bundle.js file is rendered:
<script src="bundle.js"/>
But when I navigate to a non root url and refresh the page, webpack does not render the bundle.js and the script tag is not added.
By default only the root serves index.html. You need to enable historyApiFallback in your dev server config historyApiFallback: true. That way the server will serve index.html in all routes.
Turns out this more convoluted because I am using the HtmlWebpackPlugin, this fixes it:
var express = require('express');
var app = express();
var webpack = require('webpack');
var path = require('path');
var compiler = webpack(require('./webpack.config.js'));
app.use(require('webpack-dev-middleware')(compiler, {
noInfo: true,
publicPath: '/'
}));
app.use('*', function (req, res, next) {
var filename = path.join(compiler.outputPath,'index.html');
compiler.outputFileSystem.readFile(filename, function(err, result){
if (err) {
return next(err);
}
res.set('content-type','text/html');
res.send(result);
res.end();
});
});
app.listen(3000);
Related
I'm prototyping a NextJS implementation with the following server code:
import express from 'express';
import next from 'next';
import path from 'path';
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
dotenv.config();
app.prepare().then(() => {
const server = express();
// Custom build resources aliases
// ---------------------------------------------------------------------
server.use('/favicon.ico', express.static(path.join(__dirname, 'static', 'images', 'icons', 'favicon.ico')));
// ---------------------------------------------------------------------
// Custom/dynamic routes
// ---------------------------------------------------------------------
server.get('/p/:id', (req, res) => {
const actualPage = '/post';
const queryParams = { title: req.params.id };
app.render(req, res, actualPage, queryParams);
});
// ---------------------------------------------------------------------
// Default route
// ---------------------------------------------------------------------
server.get('*', (req, res) => handle(req, res));
// ---------------------------------------------------------------------
// Express: Listener
server.listen(process.env.WEB_PORT, () => {
console.log(`Server listening on port: ${process.env.WEB_PORT}...`);
});
}).catch((ex) => {
console.error(ex.stack);
process.exit(1);
});
As apparent, my static assets sit in a /static/ folder. Of these, I have a favicon file at /static/images/icons/favicon.ico. I am able to visit this file using https://schandillia.com/static/images/icons/favicon.ico. However, when I try hitting https://schandillia.com/favicon, it throws a 404. Am I not using express.static() correctly?
I'm trying to build a small nodejs, express, mongodb app with authentication using passport-local and passport-local-mongoose, however for some reason when entering the middleware for passport in the main app.js file I get this error "TypeError: User.authenticate is not a function"
I tried the authentication by itself in a test project and it worked just fine, so maybe it's something to do with the order of my code but I can't get to what's causing this issue. I've tried several refactors but to no avail.
Below is the code for the app.js and the User Schema , but Here's a link to the project files if needed.
app.js
const express = require('express'),
app = express(),
path = require('path'),
exphbs = require('express-handlebars'),
methodOverride = require('method-override'),
flash = require('connect-flash'),
session = require('express-session'),
bodyParser = require('body-parser'),
mongoose = require('mongoose'),
LocalStrategy = require("passport-local"),
passport = require("passport"),
mongodb = require("mongodb"),
User = require("./models/User");
// Load routes
const ideas = require('./routes/ideas');
const users = require('./routes/users');
// Connect to mongoose
mongoose.connect('mongodb://localhost/diaries');
mongoose.Promise = Promise;
// Handlebars Middleware
app.engine('handlebars', exphbs({
defaultLayout: 'main'
}));
app.set('view engine', 'handlebars');
// Body parser middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Static folder
app.use(express.static(path.join(__dirname, 'public')));
// Method override middleware
app.use(methodOverride('_method'));
// Express session midleware
//PASSPORT CONFIGURATION
app.use(require("express-session")({
secret: "secret",
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(flash());
// Global variables
app.use(function(req, res, next) {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
next();
});
// Index Route
app.get('/', (req, res) => {
const title = 'Welcome';
res.render('index', {
title: title
});
});
// About Route
app.get('/about', (req, res) => {
res.render('about');
});
// Use routes
app.use('/ideas', ideas);
app.use('/users', users);
const port = process.env.PORT;
app.listen(port, () => {
console.log(`Server started on port ${port}`);
});
User Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const passportLocalMongoose = require("passport-local-mongoose");
// Create Schema
const UserSchema = new Schema({
name:{
type: String,
required: true
},
email:{
type: String,
required: true
},
password:{
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
UserSchema.plugin(passportLocalMongoose, {usernameField: "email"});
mongoose.model('users', UserSchema);
try importing LocalStrategy from require('passport-local').Strategy
like
const LocalStrategy = require('passport-local').Strategy
I'm following this Thinkster tutorial on building a reddit-esque web app using MEAN.
The tutorial instructs using curl to create a new post.
C:\root>curl --data "title=test&link=http://test.com" http://localhost:3000/posts
However, I get this error in response:
<h1>Not Found</h1>
<h2>404</h2>
<pre>Error: Not Found
at C:\root\app.js:30:13
at Layer.handle [as handle_request] (C:\root\node_modules\express\lib\router\layer.js:95:5)
at trim_prefix (C:\root\node_modules\express\lib\router\index.js:312:13)
at C:\root\node_modules\express\lib\router\index.js:280:7
at Function.process_params (C:\root\node_modules\express\lib\router\index.js:330:12)
at next (C:\root\node_modules\express\lib\router\index.js:271:10)
at C:\root\node_modules\express\lib\router\index.js:618:15
at next (C:\root\node_modules\express\lib\router\index.js:256:14)
at Function.handle (C:\root\node_modules\express\lib\router\index.js:176:3)
at router (C:\root\node_modules\express\lib\router\index.js:46:12)</pre>
I looked through those files, but all the references were just showing me what happens to the error...
Here's some code
/routes/index.js:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
var mongoose = require('mongoose');
var Post = mongoose.model('Post');
var Comment = mongoose.model('Comment');
router.get('/posts', function(req, res, next){
Post.find(function(err,posts){
if(err){ return next(err); }
res.json(posts);
})
})
router.post('/posts', function(req,res,next){
var post = new Post(req.body);
post.save(function(err, post){
if(err){ return next(err); }
res.json(post);
})
})
/models/Posts.js:
var mongoose = require('mongoose');
var PostSchema = new mongoose.Schema({
title: String,
link: String,
upvotes: {type: Number, default: 0},
comments: [{type: mongoose.Schema.Types.ObjectId, ref: 'Comment'}]
});
mongoose.model('Post', PostSchema);
app.js:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
var mongoose = require('mongoose');
require('./models/Posts');
require('./models/Comments');
mongoose.connect('mongod:localhost/news');
I feel like I did everything correct, except I wasn't sure where to place the additional routes in the routes index file, and similarly in app.js. But this seems negligible to me. I performed all the debugging I could think of but am stuck.
It should also be noted that this tutorial was perhaps not intended for use on a Windows machine. I had to install curl and do a few other things that perhaps wouldn't be necessary on a Linux or Mac. I am using Windows 10.
Your module.exports is called prematurely in routes/index.js. Move module.exports = router; to the bottom of your file, recycle your service, and try again.
Also there are issues with app.js. See below:
app.js:
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
// Notice the differences starting here
var app = express();
var mongoose = require('mongoose');
// connect MongoDB
mongoose.connect('mongodb://localhost/news', function(err,db){
if (!err){
console.log('Connected to /news!');
} else{
console.dir(err); //failed to connect
}
});
require('./models/Posts');
require('./models/Comments');
var index = require('./routes/index');
var users = require('./routes/users');
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
routes/index.js:
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Post = mongoose.model('Post');
var Comment = mongoose.model('Comment');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.get('/posts', function(req, res, next){
Post.find(function(err,posts){
if(err){
alert(err);
return next(err);
}
res.json(posts);
})
})
router.post('/posts', function(req,res,next){
var post = new Post(req.body);
post.save(function(err, post){
if(err){
alert(err);
return next(err);
}
res.json(post);
})
})
module.exports = router;
i'm very new of Express and server side in general, for my small react messaging app i'm using Express for the backend(a json file) and webpack dev server for frontend.
If i start just the Webpack server, the app show correctly, probelems come when i try to make the two works together and i think the problem is the proxy configuration of webpack-dev-server.
Here is my express server, json-api-server.js:
var express = require('express');
var serveStatic = require('serve-static');
var fs = require('fs');
var path = require('path');
var bodyParser = require('body-parser');
module.exports = (PORT) => {
const MESSAGES_FILE = path.join(__dirname, 'src/app/data/messages.json');
const app = express();
app.use(serveStatic(__dirname + '/build'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
// Additional middleware which will set headers that we need on each request.
app.use(function(req, res, next) {
// Set permissive CORS header - this allows this server to be used only as
// an API server in conjunction with something like webpack-dev-server.
res.setHeader('Access-Control-Allow-Origin', '*');
// Disable caching so we'll always get the latest comments.
res.setHeader('Cache-Control', 'no-cache');
next();
});
app.get('/messages', function(req, res) {
fs.readFile(MESSAGES_FILE, function(err, data) {
if (err) {
console.error(err);
process.exit(1);
}
res.json(JSON.parse(data));
});
});
app.post('/messages', function(req, res) {
fs.readFile(MESSAGES_FILE, function(err, data) {
if (err) {
console.error(err);
process.exit(1);
}
var messages = JSON.parse(data);
var newMessage = {
id: Date.now(),
body: req.body.body,
date: req.body.date,
from: req.body.from,
to: req.body.to
};
messages.push(newMessage);
fs.writeFile(MESSAGES_FILE, JSON.stringify(messages, null, 4), function(err) {
if (err) {
console.error(err);
process.exit(1);
}
res.json(messages);
});
});
});
app.listen(PORT, function (err) {
if (err) {
return console.log(err);
}
console.log('Listening at' + PORT );
});
}
This is webpack-server.js:
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');
module.exports = (PORT) => {
const backendPort = PORT - 1;
const server = new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
historyApiFallback: true,
proxy: {
'*' : {
target: 'http://localhost:' + backendPort
}
}
});
server.listen(PORT, 'localhost', function (err) {
if (err) {
return console.log(err);
}
console.log('Listening at ' + PORT);
});
}
And here is server.js:
var apiServer = require('./json-api-server');
var webpackServer = require('./webpack-server');
const PORT = process.env.PORT || 4001;
const PROD = process.env.NODE_ENV === 'production';
if (PROD) {
apiServer(PORT);
} else {
apiServer(PORT - 1);
webpackServer(PORT);
}
My filetree looks like:
--- /
----- server.js
----- webpack-server.js
----- json-api-server.js
----- src/
------- app/index.js
------- app/data/
-------------- messages.json
Both server start correctly and they don't give any errors in the terminal
I can reach localhost:4000/messages
I cannot reach localhost:4001. I got: "Can't get / "
Any helps? :)
Got it!
The * symbol here means: Use "*" to proxy all paths to the specified server.
proxy: {
'*' : {
target: 'http://localhost:' + backendPort
}
}
Which brings my index to be undefined.
So i have to point the key to the place where my json(or api) lives:
proxy: {
'/messages' : {
target: 'http://localhost:' + backendPort
}
}
As reference, this is also a valid solution:
proxy: {
'/messages': 'http://localhost:' + backendPort
}
I'm trying to install Ghost to my node app. I followed the configuration instructions and got it running with, however when I navigate to the blog subdirectory it just shows my site's homepage. I'm passing it the express app instance to start the server. What am I doing wrong?
var ghost = require('ghost');
ghost().then(function (ghostServer) {
app.use(ghostServer.config.paths.subdir, ghostServer.rootApp);
ghostServer.start(app);
});
I read online about running Ghost with ngynx or apache and configuring it to do some kind of proxy thing, but I don't really understand what all that's about.
Here is a working version of app.js for express and ghost subdirectory setup. Notice how your express routes need to be wrapped in the ghost.then() callback.
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var ghost = require('ghost');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
ghost().then(function (ghostServer) {
app.use(ghostServer.config.paths.subdir, ghostServer.rootApp);
ghostServer.start(app);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
});
module.exports = app;
const ghost = require('ghost')
const express = require('express')
const path = require('path')
const { getSubDir } = require('./node_modules/ghost/core/server/services/url/utils')
const app = express()
ghost().then((ghostServer) => {
app.use('/games', express.static(path.join(__dirname, 'games')))
app.use(getSubdir(), ghostServer.rootApp)
ghostServer.start(app)
})
latest howto included here:
https://docs.ghost.org/docs/using-ghost-as-an-npm-module