I am new to React and Node, trying to setup an environment to work.
I worked a little with Node.js/Express before and I used nodemon to monitor file changes and restart my app.
Also I recently started to work with React and I use webpack dev server (specifically webpack-dev-server --content-base src --inline --hot --history-api-fallback) setup that monitors file changes and reload the UI.
The problem
Now, I want to tie it together.
First solution I found was: Start my node app on specific port, say 3000 then start webpack dev server on 8080 port and proxy requests to specific urls to my backend app.
devServer: {
proxy: {
'/backend-api/': {
target: {
"host": "localhost",
"protocol": 'http:',
"port": 3000
},
ignorePath: false,
changeOrigin: true,
secure: false
}
}
},
It should work but i do not feel right starting two servers for single application.
Is there any way (and simple example i could understand) to start single server that would serve both: a server side app and React UI?
And of course, it should track file changes and restart server app if server code changes OR reload UI if client side code changes.
You can use webpack through Express middleware using this package: https://github.com/webpack/webpack-dev-middleware
You can use it by simply adding it to the app:
var webpackMiddleware = require("webpack-dev-middleware");
app.use(webpackMiddleware(webpack({/* webpack options */})));
In addition there's a package that builds on this to offer hotloading and "Create React App" style terminal display: https://www.npmjs.com/package/webpack-express-middleware
Related
So I have created a React app with
npx create-react-app my-app
and written a few functions and some content to my web app. Now I do need to implement backend for connecting to my SQL database and reading/writing from there. It is my understanding that server-side logic (NodeJS) and front-end code (React) should be in same repository, but how exactly is that done? I should probably create /backend folder and server.js inside it, but where? In the same folder with node_modules, public and src or elsewhere? Also, it would be nice to know more about how information exchange between Node and React works so I can display data fetched from database with React. Thanks in advance.
For development I have two folders on same level - src with react and server with node.
You start (e.g.)
nodejs server on port 5000
webpack-dev-server on port 3000
React communicates with backend via REST API. You have to proxy api requests to your server (part of webpack dev configuration):
devServer: {
contentBase: path.join(__dirname, 'server', 'static', 'public'),
port: 3000,
publicPath: 'http://localhost:3000/',
historyApiFallback: true,
disableHostCheck: true,
hot: true,
proxy: {
'/api': {
target: 'http://127.0.0.1:5000/',
},
},
},
In production environment the react is compiled to server/reactapp subfolder and served with expressjs as any other webpage.
Part of webpack production:
output: {
path: path.join(__dirname, 'server', 'reactapp'),
// publicPath: path.join('dist'),
filename: '[name].bundle.js',
publicPath: '/',
},
In Express (or any other web framework) you then serve the /api path with your backend tasks.
This all means I have two separated development environments - server and react, which partly join till in production environment. They both have separated package.json and node_modules.
In newer versions I have replaced REST API communication with websocket, what needs some other settings in communication.
I've started a new app with create-react-app, and ejected from that. I made a small express server as follows:
const express = require('express');
const app = express();
if(process.env.NODE_ENV === 'production') {
app.use(express.static('build'));
}
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Server started at: http://localhost:${port}/`);
});
In package.json I've added a line, "proxy": http://localhost:3000", as well as switching the commands:
"scripts": {
"run": "npm-run-all -p watch-css start-js",
"start": "node server.js",
},
run used to be start.
However now of course when I run npm start and go to localhost:3000, I get Cannot GET /. I need this server to receive and return local API calls I'll be making from my app, but I also want it to run a hot-reloading dev server just like the old npm start (now npm run) command did. How do I do this?
Some time ago I made a fork of the create-react-app repository adding webpack watch option because of this same reason. It might help you.
Just to add more info, I really invested time looking on how to get webpackdevserver to build the "bundle.js", and found that it is not possible because it loads the bundle into memory but doesn't persist it, so the file is never created. The only way available is the webpack watch option but, I don't understand why the create-react-app team can't add it to the repo, it's a really requested feature, and there are more forks than mine that solves this issue. So, you have three options:
Use the proxy server in package.json (if it works)
Make your own fork and add the watch option, or use an existing one
Don't use create-react-app
I am attempting to setup a project that uses both Angular 5 and Wordpress. Currently my solution allows the serving of both applications using node. From the root directory I run "node index.js" to run wordpress, and in a separate terminal, in a subdirectory I run "ng serve" to run the angular implementation.
Is it possible to run both angular and wordpress on the same terminal window? An example being, by typing "node index.js" in the root directory, can I serve both the angular application in a subdirectory and the wordpress through that one console?
My projects are pretty bare but here is some base code:
/index.js
const express = require('express')
const epf = require('express-php-fpm')
const options = {
// root of your php files
documentRoot: __dirname + '/wordpress',
// extra env variables
env: {},
// connection to your php-fpm server
// https://nodejs.org/api/net.html#net_socket_connect_options_connectlistener
socketOptions: { port: 9000 },
}
const app = express()
app.use('/', epf(options))
app.listen(3000)
/subproject/protractor.conf.js
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./e2e/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: 'e2e/tsconfig.e2e.json'
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};
Thank you.
I am working on a new plugin, Xo for Angular that may provide a solve for the use case above.
https://wordpress.org/plugins/xo-for-angular/
Xo gives you the option to load an Angular App as a theme with WordPress serving only as the management interface. Routes can be generated dynamically so all pages and posts are instantly viewable on the front-end without needing to recompile.
For local development I recommend setting up either apache or nginx using a tool like XAMPP. I have detailed the setup I use for my own local development here: https://github.com/WarriorRocker/angular-xo-material
Once you have wordpress running through a server like apache you can then just run ng build and let Xo load your App/theme through the main front-end. Alternatively you can also run with ng serve for rapid development.
In production you can either have Xo load your App and inject wp_head/wp_footer as necessary (Live Redirect Mode) or redirect all front-end requests to your App's dist index.html (Offline Redirect Mode).
Additional docs (work in progress): https://angularxo.io/
I have an ember project using Signalmaster. In the config/environment.js I have the following:
if (environment === 'production') {
ENV.SIGNALMASTER = {
HOST: 'https://localhost:8890',
PORT: '8890',
FORCE_CONNECTION: true
};
On my server I have signalmaster running at https://localhost:8890 (in the development.json and production.json files in the config directory for signalmaster I have secure set to true, and in the server.js file for signalmaster I've put in the location of my SSL certificate and key, as is required for running it on https) - when running "node server.js" I get the following:
signal master is running at: https://localhost:8890
Running "netstat -lnp" also shows a process running on port 8890. However when I use the app I get errors like this:
GET https://localhost:8890/socket.io/?EIO=3&transport=polling&t=LjG8--J net::ERR_CONNECTION_REFUSED
I am using socket.io version 1.3.7.
Instead of having the host as https://localhost:8890, seems it had to be https://[domain.com]:8890
this seemed easy question now blocked my brain, hope to get your help.
I am now using webpack to start angular2 app, it is fine, just run npm start, in realty, it is running this command to boost angular2 project
webpack-dev-server --inline --progress --port 8080
Now everything is fine until I want to start actual development. Our actual development is using nodeJS, I want to use nodeJS to boost the whole angular2 project. I know I can use npm build to build angular project and then using static page inside nodeJS/express to loda that static page. This is ok for deployment or production enviornment. But for development, how can I do?
As above mentioned, I am using webpack-dev-server to boost ng2 project, which is reading a lot webpack.configuration, such as type script loader, sass loader, by default it is port 8080, but in my nodeJs project, it is using "node app" to start, and port is 3000. Obviously, this has caused cross domain issue here.
So is that possible to let nodeJS to boost my local development environment in ng2 so as to avoid the cross domain issue? If I use nodeJS, then where the webpack solution goes?
Hope to hear your suggestion
You can try two solutions. In both you need to have 2 servers: webpack and yours. Both work for any backend.
Enable CORS on your server responses. This might be tricky. Also, it does not really replicate the production behaviour (folder structure, URL paths, etc.)
Proxy all non-webpack output to your server. This is achieved by a couple of lines in a webpack config but it is really good because you still see your non-angular pages, content, static files etc as you would see them in production. What is also good, you can specify your production (stage, develop, whatever) server as a target and simply have no backend running on your machine at all.
This is how-to:
devServer: {
port: 8080,
proxy: { '**': { target: 'http://localhost:3000', secure: false, headers } }
},
This will start angular server on 8080 and redirect any non-webpack generated file to the target.