Apparently the solutions I keep coming across are meant for production and not development, thus they are not working.
These solutions include any number of the following:
index.html
<base href="/client">
.env
PUBLIC_URL="/client"
package.json
"homepage": "/client"
or
"homepage: "http://localhost/client"
App.js
<BrowserRouter
basename='/client'>
<>
<Route exact path='/' component={Test} />
</>
</BrowserRouter>
None of these work in solving what I am trying to accomplish: I need the URL for assets to be /client/static and not /static. The latter makes the app not render at all in my development environment.
I'm basically playing around in development at this point and routing should be like the following:
/ = general landing page
/client = route for client login
/admin = route for internal admin login
/api = route for server that the /client and /admin communicate with
Seems like something that should be fairly easy to implement, but failing at it as none of the proposed solutions seem to work in development. For example, PUBLIC_URL is ignored in development according to the Node and/or React docs.
What is the solution here?
Repo to demo the issue:
https://github.com/eox-dev/subdir-issue
Apparently this is not possible currently in CRA:
https://github.com/facebook/create-react-app/issues/8222#issuecomment-568308139
Related
I'm developing a full-stack web app, which has both a frontend and a backend. In production, my frontend will be hosted at https://frontend.com, and my backend at https://backend.com. It seems reasonable to hardcode the address https://backend.com in my frontend code.
However, when I am testing the app locally, I'll want to spin up the backend at, say, localhost:8000, and redirect my frontend to this address instead. My question is: what's the easiest/most elegant way to do this?
One approach is to manually change the frontend code to point to localhost:8000 for local testing, and then change it back before deploying. However, this is quite annoying, and it's too easy to forget to change it back.
An approach I've used in the past is:
Create a file server.js containing:
const LOCAL_SERVER = "http://localhost:8000"
Import this file in my frontend HTML:
<script src="server.js"></script>
Set a fallback to the remote/production server in my JS scripts:
let SERVER = typeof LOCAL_SERVER === 'undefined' ? 'https://backend.com' : LOCAL_SERVER
Add server.js to my .gitignore.
This works, but it feels kind of hacky, and it pollutes my production code with references to this (possibly non-existent) server.js and LOCAL_SERVER constant. I'm wondering if anyone has a better way.
If your real backend & local backend use the same port, a simple solution is to add the following line to your hosts file:
127.0.0.1 backend.com
I am starting from this excellent tutorial: https://www.fullstackreact.com/articles/using-create-react-app-with-a-server/ and trying to extend it by adding a new page to serve through a new route. However after hours of mucking around I am realizing that somehow create-react-app is doing some weird magic (as mentioned in their docs here):
`create-react-app` configures a Webpack development server to run on `localhost:3000`.
This development server will bundle all static assets located under `client/src/`.
All requests to `localhost:3000` will serve `client/index.html` which will include Webpack's `bundle.js`.
The key quote is "All requests to localhost:3000 will serve client/index.html". I have no idea how this happens. So even though i mess around with routes/index.js:
app.route('/')
.get(function (req, res) {
res.sendFile(bipath.join(__dirname, '../public', 'THISCANBEANYRANDOMFILENAME.html'))
});
it doesnt matter because webpack is somehow directing localhost:3000 to index.html anyway. where and how is it doing this? Bottom line I am trying to modify my routes to serve a new html file and am running into all sorts of filepath issues (yes, even when i use require('path') or sendFile(...,{root: __dirname}).)
So what exactly is going on here and can you give me any hints to help me out?
Edit: this could be from babel as well as webpack - i'm not exactly clear where babel hands off and where webpack starts.
I haven't played around with create-react-app, but it seems like instead of using the default npm start, you could create your own server file and run that.
This looks like a good example.
https://medium.com/#patriciolpezjuri/using-create-react-app-with-react-router-express-js-8fa658bf892d#.6y4rrl61q
Alternatively, if you're looking to have routes used as an api, you could proxy them to a different port like shown in the tutorial you linked.
I'm running Apache on a Linux server and find that my node.js apps routing doesn't work correctly when using URLS that go through Apache.
I followed instructions on other posts for turning on the proxy modules within apache and then set up this definition:
ProxyPass /testauth http://localhost:3000/
(I also had a line in there to define a similar reverse proxy that did nothing)
My node app runs on port 3000 with routing set up like in app.js
app.use('/', routes);
app.use('/tests', tests);
app.use('/questions', questions);
If I access URLs on my server like this:
http://rose.cs.umass.edu:3000/
http://rose.cs.umass.edu:3000/questions/179
I get correct results (note the styling with some simple CSS)
If I try to access thru apache like this:
http://rose.cs.umass.edu/testauth/questions/179
I get a 404 error but see from the backtrace that it is inside my js code.
For some reason the URL http://rose.cs.umass.edu/testauth partially works (but CSS doesn't get applied (because the index.ejs file includes the css like this:
<link rel='stylesheet' href='/stylesheets/style.css' />
The location of CSS files and the coding of relative paths follows all the node.js examples I have looked at and works fine in my development environment. But when running the app by going thru Apache, things are not working right.
Is there a fix to the apache config? Do I have to make an adjustment to how code paths in the my javascript and ejs files?
One clue I had to what was wrong is that node was printing the paths each time a request came in and they looked like
GET //questions/ 404 4.278 ms - 916
So I changed apache to have:
ProxyPass /testauth http://localhost:3000 (removed trailing slash)
Now the paths coming into my app were correctly formed.
The next order of business is to rework all the relative URLs in my EJS templates, client-side javascript, and even redirects in the server side.
Because I had to put "testauth" in the path so that Apache can forward to node, all the URLs coming into the app are of the form rose.cs.umass.edu/testauth/rest-of-url . This means relative URLs inside my app code that looked like
<a href="/questions" ....>
were now incorrect because they created absolute URLs that omitted the testauth in the path. Some of these relative URLs now are pretty strange (using things like ../ or even ../.. to get to things) . I wish there was a variable similar to ${pageContext.request.contextPath} that I use in JSP to build URLs.
I decided to mimic the JSP ${pageContext} idea
I added to file called config.js that has various settings that are particular to where the app is running (stuff like db credentials, etc). I added
// uncomment the line that applies
config.pageContext = "" // dev environment
// config.pageContext = "testauth" // production environment
My routing scripts all do something like:
res.render('questions', {pageContext: util.pageContext(req), questions: questionArray});
And the EJS templates all have stuff like this in the URLS:
<script src="<%= pageContext %>/static/js/bootstrap.min.js"></script>
A second alternative that I used for awhile until I went with the above:
Pass an argument to your node app when you start it. You then set a global variable similar to above and use it similarly. If you use a process manager (I use pm2) to run your node app on your server you might have to do something like:
pm2 start testauth -- -c /testauth // start testauth.bin using /testauth for the page context
I'm rather new to how webservers behave in general, so I have a few questions I hope someone can help me with.
It would also be nice if anyone could point me to an article or some documentation about the following topics.
Basically I'm trying to develop a webapp using Angular2, Expressjs and obviously node.js.
I have already successfully developed some basic Angular2 apps without a backend attached to it, which worked fine.
However, now I'm trying to send the index.html file (which contains a tag referring to an Angular component) to the browser from my server.
app.get('/test', function(req, res) {
res.sendfile('index.html');
});
You can find the html here: http://pastebin.com/utMHk8Pe
However, even though the node_modules package is on the same hierarchic level as both server.js and index.html, going to localhost:8080/test gives me a 404 for the node_modules script files in my html header.
Q1: Why doesn't my server find the node_modules folder?
Now, when I run my index.html file through following link, http://localhost:54720/testapp/index.html, everything works just fine.
Somehow it finds the node_modules at port 54720 but not 8080 (which is the port I made the express app listen on).
Q2: Why can't my server find the node_modules folder at the port I make it listen on?
As I've already said, I'm really new to node.js and webservers in general.
I'd be very grateful for any help!
Even linking me to an article which could be helpful would help me tons, since I can't really find anything since I don't know what to Google for.
You need to define a static folder to enable this. Something like this:
var express = require('express');
var app = express();
(...)
app.use('/static', express.static('public'));
This way, you will be able to serve the static files you need for Angular2, the ones that are present under the node_modules (angular2, systemjs and rxjs).
See this documentation for more details: http://expressjs.com/en/starter/static-files.html.
Hope it helps you,
Thierry
I am facing tremendous issues trying to implement multiple entry points along with react router. The aim is to achieve using webpack to do something that is suggested by https://github.com/petehunt/webpack-howto.
So far I have currently set it up like this:
webpack.config.js
entry: {
entry1: __dirname + './entry1.jsx',
entry2: __dirname + './entry2.jsx'
}
routes.jsx
export default (
<Route path='/' name='app' handler={App}>
<DefaultRoute handler={entry1} />
<Route name='entry2' handler={entry2}/>
</Route>
);
Whenever this code is run to instantiate a instance of Router on the client
Router.run(routes, Router.HistoryLocation, (Handler, state) => {
React.render(<Handler />, document.getElementById('app'));
});
Node.js will try to run this code on the server which obviously fails as DOM is not available there. It will produce an error.
Is there any proper way to implement multiple-entry points with react-router?
I have done something similiar to this in a sandbox webpack-react-boilerplate repository I've been playing around with using react-router.
I believe the answer you may be looking for lies here where you need to use React.renderToString and/or React.renderToStaticMarkup in your server entry file as you rightly suggest, there is obviously no DOM on the server. You can see how the client entry point here differs to the server one.