I've added an expressJS app inside my ember app so I can provide a backend API for my ember app.
My process:
npm install express --save
I created a folder called "server" in the route of my ember application and inside that a file called "server.js".
Yesterday I had it working fine, I already had my ember app running via ember s and tested out the express app using nodemon server/server.js and checking the endpoints I created with Postman.
However this morning when I've tried to run ember s I'm given the following error:
C:\Sandbox\tsodash>ember s
version: 2.3.0-beta.2
Cannot find module 'C:\Sandbox\tsodash\server'
Error: Cannot find module 'C:\Sandbox\tsodash\server'
at Function.Module._resolveFilename (module.js:339:15)
at Function.Module._load (module.js:290:25)
at Module.require (module.js:367:17)
at require (internal/module.js:16:19)
at Project.require (C:\Sandbox\tsodash\node_modules\ember-cli\lib\models\project.js:281:12)
at Class.module.exports.Task.extend.processAppMiddlewares (C:\Sandbox\tsodash\node_modules\ember-cli\lib\tasks\server\express-server.js:115:33)
at Class.<anonymous> (C:\Sandbox\tsodash\node_modules\ember-cli\lib\tasks\server\express-server.js:220:21)
at lib$rsvp$$internal$$tryCatch (C:\Sandbox\tsodash\node_modules\ember-cli\node_modules\rsvp\dist\rsvp.js:1036:16)
at lib$rsvp$$internal$$invokeCallback (C:\Sandbox\tsodash\node_modules\ember-cli\node_modules\rsvp\dist\rsvp.js:1048:17)
at C:\Sandbox\tsodash\node_modules\ember-cli\node_modules\rsvp\dist\rsvp.js:331:11
Naturally I assumed I just needed to use modules.exports = function(){ //..expressjs code}
Full Code
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var request = require('request');
var btoa = require('btoa');
var config = require('./config');
var _ = require('lodash');
module.exports = function(){
var endPoints = config.endPoints;
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
var port = process.env.PORT || 4200;
var router = express.Router();
// middleware to use for all requests
router.use(function (req, res, next) {
// do logging
console.log('Something is happening.');
next(); // make sure we go to the next routes and don't stop here
});
router.get('/', function (req, res) {
res.json({
message: 'TSO Git Dash'
});
});
// ..
app.use('/api', router);
app.listen(port);
console.log('Magic happens on port: ' + port);
}
Still no avail.
Folder structure:
Any ideas? I'm assuming it's something simple that I've missed. But I'm stumped.
As #locks suggested in the comments, there is an express server used in mocks and fixtures. The fix was simple, I renamed the folder and the JS file to "api" and ran ember s and it worked perfectly. It seems to have been a naming conflict.
Related
I have been trying for the past hour and a half to debug a project of mine.
The project works fine locally. Routes are systematically not working remotely except for one, the root of the project. I get a Cannot GET message in the browser elsewhere (all other paths).
From what I understand from my readings, this might have something to do with vue-router and might be caused by the server.js file I created in the root folder. The problem might have to do with the fact that my routes are dynamic.
const express = require('express');
const serveStatic = require("serve-static")
const path = require('path');
app = express();
app.use(serveStatic(path.join(__dirname, 'dist')));
const port = process.env.PORT || 3000;
app.listen(port);
This might also be caused by the fact I did not create the project with the history mode (although I'm pretty sure I did). I understand that I might have to go to my webpack config file to solve this, but I don't think I have one.
EDIT: By the way, my VueJS application is just a front-end to the PokéAPI back-end. I didn't build the back-end myself.
Simply creating the project with history mode is not enough. Your browser is trying sending text/html GET requests to the path you navigate to. But your app is a single page application which only has one index.html in /public, so you get 404 errors. Its in the vue-router docs:
To fix the issue, all you need to do is add a simple catch-all fallback route to your server. If the URL doesn't match any static assets, it should serve the same index.html page that your app lives in.
For Node.js+express setup, you can use connect-history-api-fallback package.
npm install --save connect-history-api-fallback
Then change your server.js file to this:
const express = require('express');
var history = require('connect-history-api-fallback');
const serveStatic = require("serve-static")
const path = require('path');
app = express();
app.use(history());
app.use(serveStatic(path.join(__dirname, 'dist')));
const port = process.env.PORT || 3000;
app.listen(port);
In case you don't want to use third-party package you might be able to simply do this:
const express = require('express');
const serveStatic = require("serve-static")
const path = require('path');
app = express();
app.use(serveStatic(path.join(__dirname, 'dist')));
app.get(/.*/, function (req, res) {
res.sendFile(__dirname + "/dist/index.html");
});
const port = process.env.PORT || 3000;
app.listen(port);
But I'd recommend using the package as it handles some edge-cases
I am getting this error, "TypeError: path must be absolute or specify root to res.sendFile"
root
-dist
|--index.html
|--index_bundle.js
-src
|-server
|-server.js
//server.js
var path = require('path')
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const app = express()
let dataStorage = {};
app.use(cors())
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: true
}))
app.use(express.static('dist'))
app.listen(8081, function(){
console.log('Server running on port 8081!')
})
app.get('/', function (req, res) {
res.sendFile('../dist/index.html') //need help setting this up
})
app.post('/formHandler', function(req, res){
//post to dataStorage here
})
I am trying to run an express server while also using webpack-dev-server for hot reloading.
I am having trouble with setting up the path to generated 'dist' file.
I am able to just run the webpack-dev-server without express and the file is working then.
Thank you
You can have access to it by serving It's content as express static.
const path = require('path');
app.use(express.static(path.resolve(__dirname, '../../dist'));
You can also define the path at which statics assets can be accessible like this
app.use('/', express.static(path.resolve(__dirname, '../../dist'));
As in your dist folder there are already an index.html file it will be rendered by default when visiting the / path in your browser. No need to specify the index.html file in you request URL
I tried to create the simplest test route to test on my localhost as follows.
Verified localhost:3000 is up. Wrote a simple test file.
const express = require('express');
const router = express.Router();
router.route('/test').get((req, res) => {
console.log('route found');
});
module.exports = router;
My routes are split up as follows in my index routing file in the routes directory.
module.exports.api = require('./api');
module.exports.auth = require('./auth');
module.exports.root = require('./root');
module.exports.articles = require('./articles');
module.exports.test = require('./test');
I use the route as follows in my index.js for the server:
const routes = require(__dirname + '/routes');
app.use('/test', routes.test);
Tested it using Postman.
Sent request to localhost:3000/test/test.
No response. How can I troubleshoot further?
You are not getting any response because you are not sending any response from the server. You need to send some response back otherwise the client will keep waiting for the response until request times out.
router.route('/test').get((req, res) => {
res.send('route not found');
});
Edit
app.use('/test', routes.test); won't work with the way your route is defined. For it to work, request url should be /test/test. If you want request url to be just /test, change
app.use('/test', routes.test);
to
app.use(routes.test);
Here's a working version of what you want to do
const express = require('express');
const router = express.Router();
router.get('/test', (req, res) => {
res.send("hey");
console.log('route found');
});
module.exports = router;
Now in your main module, you need to check that you're listening to the right port, and that your express app is actually using the exported router!
const express = require('express');
const app = express();
const router = require('path/to/router/module');
app.use(router)
app.listen(8080, () => console.log("listening to port 8080"));
EDIT:
You mentioned that
My routes are split up as follows in my index routing file in the routes directory.
And, I can see that in the main module, you are requiring the directory itself, and not the routes module
const routes = require(__dirname + '/routes');
while what you should require is a module and not a directory!
const routes = require(__dirname + '/routes/yourRouteModuleName');
The solution I just gave assumes the following project's structure:
├── index.js
├── routes
│ ├── test.js
│ ├── routeModuleOrWhatever.js
│
I am deploying an Apollo Server for my database to heroku and it is giving an application error. It is not simply show that there is a problem with the get route, it says that the application has an error and the error logs say that the app is crashing. It runs fine locally.
I have set up the procfile with: web: node app.js .
I have tried it with the procfile removed.
I have set playground and introspection to true. I saw that that could be the problem but it did not seem to help.
The port is set to process.env.PORT || 8080 .
Here is the minimal code:
const { ApolloServer } = require('apollo-server-express');
const express = require('express');
const db = require('./models');
const typeDefs = require('./data/schema');
const resolvers = require('./data/resolvers');
const app = express();
const server = new ApolloServer({
typeDefs,
resolvers,
context: { db },
introspection: true,
playground: true,
});
server.applyMiddleware({ app });
const PORT = process.env.PORT || 8080;
app.get('/', (req, res) => {
res.send('hello');
});
app.listen(PORT, () => {
console.log(`Server is ready at ${PORT}`);
});
I am also using some other functions (trying to set up a cron process), but those are commented out.
I would expect to get the / get route to at least say hello, or for the /graphql route to display playground. I am getting neither of those options.
It turns out that I needed to add the following to package.json:
"scripts": {
"start": "app.js",
...
}
And I needed to install packages listed in the heroku logs --tail, but I have had those errors before. Writing the script start key into the package.json file is for when you are deploying your server independently of your react (or client) side.
quick question regarding using React-Router. I'm having trouble getting my server to handle pushState (if this is the correct term). Originally, I was using a module called connect-history-api-fallback, which was a middleware that enabled me to only server up static files form my dist directory. Visiting the client www.example.com obviously worked and I could navigate throughout the site, additionally, refreshing at any route like www.example.com/about - could also work.
However, I recently added one simple API endpoint on my Express server for the React app/client to ping. The problem now is that while I can get the initial page load to work (and thus the /api/news call to work, to fetch data from a remote service), I can no longer do a refresh on any other routes. For example, now going to www.example.com/about will result in a failed GET request for /about. How can I remediate this? Really appreciate the help! PS - not sure if it matters, but I'm considering implementing Server Side Rendering later on.
import express from 'express';
import historyApiFallback from 'connect-history-api-fallback';
import config from '../config';
import chalk from 'chalk';
import fetch from 'node-fetch';
import path from 'path';
const app = express();
// FIXME: Unsure whether or not this can be used.
// app.use(historyApiFallback({
// verbose : true
// }));
//// DEVELOPMENT MODE ONLY - USING EXPRESS + HMR ////
/* Enable webpack middleware for hot module reloading */
if (config.get('globals').__DEV__) {
const webpack = require('webpack');
const webpackConfig = require('../build/webpack/development_hot');
const compiler = webpack(webpackConfig);
app.use(require('./middleware/webpack-dev')({
compiler,
publicPath : webpackConfig.output.publicPath
}));
app.use(require('./middleware/webpack-hmr')({ compiler }));
}
//// PRODUCTION MODE ONLY - EXPRESS SERVER /////
if (config.get('globals').__PROD__) {
app.use(express.static(__dirname + '/dist'));
}
//// API ENDPOINTS FOR ALL ENV ////
app.get('/api/news', function (req, res) {
fetch('http://app-service:5000/news')
.then( response => response.json() )
.then( data => res.send(data) )
.catch( () => res.sendStatus(404) );
});
// Wildcard route set up to capture other requests (currently getting undexpected token '<' error in console)
app.get('*', function (req, res) {
res.sendFile(path.resolve(__dirname, '../dist', 'index.html'));
});
export default app;
Express works by implementing a series of middleware that you "plug in" in order via .use. The cool thing is your routes are also just middlware — so you can separate them out, have them before your history fallback, and then only requests that make it past your routes (e.g., didn't match any routes) will hit the fallback.
Try something like the following:
const app = express();
// ...
var routes = exprss.Router();
routes.get('/api/news', function (req, res) {
fetch('http://app-service:5000/news')
.then( response => response.json() )
.then( data => res.send(data) )
.catch( () => res.sendStatus(404) );
});
app.use(routes);
app.use(historyApiFallback({
verbose : true
}));