Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

request for "serve app under" configuration #1582

Closed
ggerrietts opened this issue Feb 17, 2017 · 22 comments
Closed

request for "serve app under" configuration #1582

ggerrietts opened this issue Feb 17, 2017 · 22 comments

Comments

@ggerrietts
Copy link

ggerrietts commented Feb 17, 2017

The Issue

Currently, no matter what you do with routes and such inside your app, the Webpack node app that does all the hot module reloading and linting and such always wants to serve assets rooted at /. This breaks when a development environment includes more than one interoperating React app sharing a URI path space.

The Proposed Solution

We would really like to be able to serve those assets from a configurable path. It would be nice to be able to specify in our package.json some setting that identified a "mount under" pathspec. I think we can be somewhat flexible about the exact behavior, so long as the asset links Webpack generates contain a configurable path prefix.

The Use Case

We're using create-react-app to build two separate React applications. One application is our domain application. One application is a common user-and-organization management app. The user-and-organization management app is shared with other business units who are using completely separate stacks.

We're still relatively early in the development process, and to date, we've been fine using different ports to route between these apps. However, a new set of requirements requires us to gather the two apps under a single domain name. The user-and-org app should be mounted under domain.name.here/account and the remainder of domain.name.here should serve the domain-specific app.

In production, this shouldn't be a problem. We can emit a bundle that will have the right paths in it by using the homepage setting. We'll stick both bundles onto a CDN; a load balancer will route the API endpoints, and everything should be fine.

In development, things are a little trickier. Webpack's development app always wants to serve assets from /, and it writes all the asset links it emits to reference that path. We can handle getting requests with /account in them to the correct server, and we can write our user-and-org application to expect /account in front of all the routes, but we can't talk Webpack into serving assets under /account -- we could work around this problem -- nor can we get Webpack to emit links to those assets under /account -- and that problem we can't work around.

Workarounds

We've talked about continuing to route by port in development, and just making all our link-generation logic environment sensitive.

We've talked about ejecting and writing our own Webpack config -- we actually started down that path, but I don't think we've reached its conclusion.

We've also pushed back a little harder on using domain names to separate the two apps; that has some upside and some downside, but it obviates this problem.

@gaearon
Copy link
Contributor

gaearon commented Feb 17, 2017

If homepage ends with /account, would it be reasonable to serve under /account in development?

@ggerrietts
Copy link
Author

For our use case, absolutely. For us, it's even preferable that nothing cares about the protocol/domain/port parts of homepage.

@viankakrisna
Copy link
Contributor

how about basePath config in package json or BASE_PATH env?

@Timer
Copy link
Contributor

Timer commented Feb 17, 2017

@viankakrisna we like to avoid adding additional configuration as much as possible, and homepage in package.json already serves this purpose. 😄 Did you have a case that you need help with?

@Timer
Copy link
Contributor

Timer commented Feb 17, 2017

@ggerrietts: I believe @gaearon and I would both be open to a PR that enables this functionality so that we can play with it.
We need to make sure we understand the implications of the change fully and make sure we don't break any of webpack's HMR or other functionality.

We would greatly appreciate the contribution. 😃

@viankakrisna
Copy link
Contributor

viankakrisna commented Feb 17, 2017

@Timer yeah, I think homepage would be sufficient. Doesn't really found any use case that setting it to "." or PUBLIC_URL env would not solve.

For @ggerrietts use case:
maybe you can setup an nginx server that map your.app.dev to localhost:3000 (your main app) and your.app.dev/account tolocalhost:3001 (your account app). Haven't really tested if HMR works with proxying though

@Timer
Copy link
Contributor

Timer commented Feb 23, 2017

@ggerrietts are you willing to open a PR providing this functionality?

@Timer Timer added this to the 0.10.0 milestone Feb 23, 2017
@Timer
Copy link
Contributor

Timer commented Feb 23, 2017

Tagging for 0.10.0 since this would be a breaking change and we want to make sure it doesn't slip through the cracks if it's ready then.

@ggerrietts
Copy link
Author

Hey, I have this issue open in a tab in the hopes that I'll get bandwidth to work on it. I think my employer has opted to go with the final workaround listed above -- use domain names instead of mounting sub-apps -- so I need to fit it in after-hours. I have some things to learn, but my hope is that maybe I can deliver such a thing over the weekend. I have four kids, though, so sometimes I don't get what I want. :)

@mukaibot
Copy link

We are also having this problem. Our situation is that we have a monolithic Rails app which we are beginning to carve out into smaller React apps. For this reason, a different domain does not work. @Timer and @viankakrisna please be aware that cookies won't be sent when the ports are different. This breaks our app too (don't ask :P)

This is our first time using create-react-app. In our other React apps, we've had to configure basePath in Webpack, and are successfully using this in production behind Akamai.

@gaearon
Copy link
Contributor

gaearon commented Mar 21, 2017

This is up for grabs—please feel free to contribute the implementation.
My current thinking is it should use the same public path as in production.

@viankakrisna
Copy link
Contributor

viankakrisna commented Mar 22, 2017

For the cookie thing you need to have same top level domain. So the workaround is setup nginx server locally that maps the pathname to the devserver with a same top level domain. (haven't tested it, but that's the best solution i can think of)

The simpler way is to have cra generate development bundle and include it in your app.
There's a pr open for that in #1616. But this feature needs more exploration and validation, cause right now we lose access to hot reloading and error overlay. Also there's an added risk of deploying development bundle to production.

Currently, I think cra is more suitable to build a statically served single page app with an api server rather than integrated with monolith app with access to cookie etc for development.

@kellyrmilligan
Copy link
Contributor

Should this work happen off of master? Or the 0.10 release?

@kellyrmilligan
Copy link
Contributor

I see there is not a 0.10 release branch sorry my bad.

@kellyrmilligan
Copy link
Contributor

I have some of this working locally now. I am not sure all the cases to test though.

@kellyrmilligan
Copy link
Contributor

in testing, I created a new issue:
#1880

couldn't see in the issues well enough if this was reported or not, but I found similar issues reported as well on just webpack dev server.

@kellyrmilligan
Copy link
Contributor

opened a pr for this.

@gaearon gaearon added this to the 0.11.0 milestone May 14, 2017
@gaearon gaearon removed this from the 0.10.0 milestone May 14, 2017
@gaearon
Copy link
Contributor

gaearon commented May 14, 2017

Big thanks to @kellyrmilligan for starting work on this in #1887. Unfortunately I could only review it now, and I found a few blocking issues with it.

@kellyrmilligan Please let me know if you’d like to address those further in #1887, or if you’d rather have somebody else finish up the pull request. Since we plan to cut 0.10 very soon, I’m afraid I have to postpone this feature until 0.11, as it is not currently quite ready to be merged. I realize it is frustrating.

@kellyrmilligan
Copy link
Contributor

I will see what I can do in the next week or so. I really need this feature! Totally understand to postpone until 0.11

@gaearon
Copy link
Contributor

gaearon commented May 14, 2017

Yea, we want it too 😛
I’m sorry I couldn’t review earlier.

@lennartj
Copy link

lennartj commented Nov 8, 2017

While you are already about to solve this problem, I thought I would offer a small step-by-step workaround for those folks who are working with addressing static resources from their in-project CSS files. Feel free to ignore this in the issue - but it may help someone out there, so adding it as a comment. Fair?

The situation can be worked around (somewhat clunkily, but still...) with a rewrite rule in the web server serving the production build. Example below, and a small recipe for the rewrite rule required as well.

Description

Given a CSS file ("global.css") which links to a font placed within the static folder public/fonts:

[project] / src / styles / global.css
[project] / public / fonts / Fondamento-Regular.ttf

In order to work in development mode, the entry in global.css must contain the entry url(/fonts/Fondamento-Regular.ttf):

@font-face {
font-family: 'Fondamento';
font-style: normal;
font-weight: 400;
src: local('Fondamento Regular'), local('Fondamento-Regular'), url(/fonts/Fondamento-Regular.ttf) format('truetype');

Assuming that the context path of the production build should be /mithlond, the package.json entry should be "homepage" : "https://[someServerName]/mithlond",.

However, running the npm run build to generate a production build, the links inscribed within the static/css/main.[hash].css do not contain the context path, but are copied verbatim:

url(/fonts/Fondamento-Regular.ttf)

(Somewhat clunky) Workaround recipe

  1. Ensure that your static resources do not reside within directories "public/js" or "public/css". I chose "public/font" for the fonts in the case per above.
  2. Create a text substitution ("rewrite") rule within the server, on the context path of the application. For nginx, the rule is as follows (and repeat the sub_filter bit for all directories of static paths you include in your application:
    location /mithlond/ {
        # Prepend the /mithlond/ path to outbound font links
        sub_filter "/fonts/" "/mithlond/fonts/";
        sub_filter_once off;
        sub_filter_types *;
    }

The sub_filter above effectively replaces the malformed URLs embedded in the compiled CSS resource so that the outbound links work for clients.

@Timer
Copy link
Contributor

Timer commented Jan 10, 2018

We definitely want to go forward with this. Please consolidate all discussions into #1887. Thanks!

@Timer Timer closed this as completed Jan 10, 2018
@lock lock bot locked and limited conversation to collaborators Jan 20, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants