You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Use a div with the correct id and a separate <script> tag that points to the script (which is duplicated from static/js/main.*.js to main.js in the root) and pass params via the dataset
I don’t see why this question would be related to CRA. Open the Network tab and check which request is getting a 404. Then you need to figure out why the server isn’t serving what you expect at the path you expect. Hope this helps!
@gaearon The error I get is because it's searching for /static/media/logo.2e151009.png on the parent server (that implements the div + script) like https://parent.com/static/media/logo.2e151009.png instead of at the server where the CRA is located (https://plugin.domain.com/plugin-name/version-number/static/media/logo.2e151009.png)
But main.js is (like I said) just a copy of static/js/main.*.js.
I think the problem is, it uses relative paths?
It uses an absolute path but absolute paths are calculated from the host that served the page.
If you want to hardcode a specific URL to calculate them against, you need to set PUBLIC_URL environment variable during the build. You can see an example in #937.
Your best solution is as described above, use PUBLIC_URL and build twice -- there't not really another way unless that plugin-name/version-number/ is always static [but if you sub it out with abc/1.0.0/ the point is moot].
@Timer so for both staging and production, you'll have the same plugin-name & version-number, so that's not the case, the only difference is staging-domain vs. domain.
But the problem is that the script is loaded @ parent-domain, so if I just set PUBLIC_URL to /plugin-name/version-number, the script will still look @ parent-domain/plugin-name/version-number 😕
@gaearon OK I'll try to explain it as clear as possible 🙂
I'm building a react app (using CRA) that's going to be used as a plugin.
The idea of the app is that the owner has a database of files and the plugin is used to show all these files (+ metadata).
So instead of offering an API for getting al the files, metadata, ... the plugin will be embedded inside the client's site.
Using a div with the correct id and a separate <script> tag that points to the script (which is duplicated from static/js/main.*.js to main.js in the root) and pass params via the dataset
So in order to get this behavior, I use the default build script (react-scripts build) and added a postbuild script (cp $(find $PWD/build/static/js -type f -name 'main.*.js') $PWD/build/main.js").
When releasing a new version, I use the following workflow to deploy the app:
Build the app (npm run build)
Publish it to the npm repository (as a private repo)
npm i on the staging server and test it on the staging server environment (equal to production server)
fix bugs if any are present due to environment (which is almost never the problem, but you never know)
npm i on our production server
When then using the div+ script version, I get an error when loading local assets, because it's searching for /static/media/logo.2e151009.png on the parent server (so https://parent.com/static/media/logo.2e151009.png) instead of at the server where the CRA is located (https://plugin.domain.com/plugin-name/version-number/static/media/logo.2e151009.png).
Building the app 2 times with a different PUBLIC_URL (1 time for staging and 1 time for the production server, like you and @Timer suggested) will solve the 'problem'.
But that implies that I would need to publish both versions to npm.
That is a bit grim and cumbersome in my opinion, since both builds are exactly the same, except for the PUBLIC_URL.
I hope you understand my use case a bit more.
If you still have some questions, I'm happy to answer them offcourse 🙂
setting PUBLIC_URL=__STUB__URL__ and running search & replace on the generated assets
@viankakrisna That could maybe be a solution indeed. 🙂
I'm also looking into setting __webpack_public_path__ on the fly (like described in the docs), by having something like
// src/index.jsimport'./public-path';// ...
// src/public-path.js__webpack_public_path__=resolvePublicPath();functionresolvePublicPath(){// check the file path of the current executing script and derive the root-folder// Ref: https://stackoverflow.com/questions/2255689/how-to-get-the-file-path-of-the-currently-executing-javascript-code}
And dropping the PUBLIC_URL variable. @gaearon This solution could maybe be embedded inside CRA as an opt-in option?
@gaearon This solution could maybe be embedded inside CRA as an opt-in option?
Tbh this sounds a bit too esoteric to me. I think it’s cool if this workaround is working for you but I don’t think we’ll be embracing something like this as a first-class feature. Usually when you need something like this you end up needing even more customizations, and at that point ejecting, forking or “rewiring” but be better anyway.
I think I understand the problem you're describing with parent.com website. But how is this related to the staging/production difference you also mention? Do you mean you only use div + script on staging, but iframe in production? Or do you have two separate problems (one caused by iframe/script difference, and another by production/staging difference)?
@gaearon Well I sort of have 2 problems indeed, but they're related
Problem 1 is the breaking assets when using the div + script.
This can be solved by building the app with a correct PUBLIC_URL (like PUBLIC_URL=https://plugin.domain.com/plugin-name/version-number).
But solving it right that causes a new problem, which is that I have to build the app 2 times, because the PUBLIC_URL needs to be set different for the staging/production server.
It won't work for you if you use pushState routing because then if the user loads http://plugin.com/plugin-name/my/client-side/path then the assets will be requested relative to that. But I’m not sure you’re using client-side routing like this?
Other than that I don’t really see other good options.
@gaearon I'm using client-side routing (react-router), so setting the homepage won't work either 😕
I've already looked into setting __webpack_public_path__ to the file-path of the current running script (ref: StackOverflow), which would be possible by calling document.currentScript (ref: MDN) and having this answer as a fallback, which would be a possible solution to set it dynamically on the fly...
I really think this could be the default implementation for the PUBLIC_URL param, since it will always be correct I think?
Implementation would be something like
// src/index.jsimport'./public-path';// ...
// src/public-path.js__webpack_public_path__=resolvePublicPath();functionresolvePublicPath(){constcurrentScript=document.currentScript||getCurrentScriptViaFallback();constpublicPath=currentScript.split('/static/js')[0]// app root directory.split('main.')[0];// add support for script in app root directoryreturn`${publicPath}/`;}
@gaearon I don't know how PUBLIC_URL is implemented right now, but I think that my solution could be a possible default for it?
So instead of using a relative path, use an absolute path (the app-root directory).
I think this will probably (as a default) be the best solution instead of deriving it from homepage (in package.json) or by setting the PUBLIC_URL manually in most cases.
We can still keep those 2 as a way to set it manually if we want?
Activity
[-]Using the script directly breaks[/-][+]Using the script directly breaks assets[/+]gaearon commentedon Jan 8, 2018
I don’t see why this question would be related to CRA. Open the Network tab and check which request is getting a 404. Then you need to figure out why the server isn’t serving what you expect at the path you expect. Hope this helps!
MichaelDeBoey commentedon Jan 8, 2018
@gaearon The error I get is because it's searching for
/static/media/logo.2e151009.pngon the parent server (that implements thediv+script) likehttps://parent.com/static/media/logo.2e151009.pnginstead of at the server where the CRA is located (https://plugin.domain.com/plugin-name/version-number/static/media/logo.2e151009.png)But
main.jsis (like I said) just a copy ofstatic/js/main.*.js.I think the problem is, it uses relative paths?
gaearon commentedon Jan 8, 2018
It uses an absolute path but absolute paths are calculated from the host that served the page.
If you want to hardcode a specific URL to calculate them against, you need to set
PUBLIC_URLenvironment variable during the build. You can see an example in #937.MichaelDeBoey commentedon Jan 8, 2018
@gaearon
Yeah I already looked at
PUBLIC_URL, but then I need to build the app 2 times?PUBLIC_URL=https://plugin.staging-domain.com/plugin-name/version-number/in stagingPUBLIC_URL=https://plugin.domain.com/plugin-name/version-number/in productionAnd that's what I'm trying to avoid... 😕
Timer commentedon Jan 8, 2018
Do you require routing? If not, you can try to set the homepage to
.; this will build it for relative paths.MichaelDeBoey commentedon Jan 8, 2018
@Timer Yeah we use
react-routerin the project unfortunately 😕I'm open to any given solution that could help us. 🙂
The way we deploy right now is:
npmnpm ion our staging server and test it on the staging server environment (equal to production server)npm ion our production serverTimer commentedon Jan 8, 2018
Your best solution is as described above, use
PUBLIC_URLand build twice -- there't not really another way unless thatplugin-name/version-number/is always static [but if you sub it out withabc/1.0.0/the point is moot].MichaelDeBoey commentedon Jan 8, 2018
@Timer
Yeah
plugin-name&version-numberwill be replaced with the actual name of the plugin/app & with thenpmversion numberMichaelDeBoey commentedon Jan 8, 2018
@Timer so for both staging and production, you'll have the same
plugin-name&version-number, so that's not the case, the only difference isstaging-domainvs.domain.But the problem is that the script is loaded @
parent-domain, so if I just setPUBLIC_URLto/plugin-name/version-number, the script will still look @parent-domain/plugin-name/version-number😕Timer commentedon Jan 8, 2018
This is going to be your best solution: #3708 (comment)
MichaelDeBoey commentedon Jan 8, 2018
Too bad 😕
There's also not an option to set the
PUBLIC_URLat runtime?gaearon commentedon Jan 8, 2018
No, it needs to be embedded in the bundle.
MichaelDeBoey commentedon Jan 8, 2018
Too bad 😕
It's just stupid to build it 2 times, when the code is exactly the same, except for the
PUBLIC_URL, because it's on another environment 😕5 remaining items
MichaelDeBoey commentedon Jan 16, 2018
@gaearon OK I'll try to explain it as clear as possible 🙂
I'm building a react app (using CRA) that's going to be used as a plugin.
The idea of the app is that the owner has a database of files and the plugin is used to show all these files (+ metadata).
So instead of offering an API for getting al the files, metadata, ... the plugin will be embedded inside the client's site.
This need to be possible in 2 different ways:
iframeand pass parameters via the URLdivwith the correctidand a separate<script>tag that points to the script (which is duplicated fromstatic/js/main.*.jstomain.jsin the root) and pass params via thedatasetSo in order to get this behavior, I use the default
buildscript (react-scripts build) and added apostbuildscript (cp $(find $PWD/build/static/js -type f -name 'main.*.js') $PWD/build/main.js").When releasing a new version, I use the following workflow to deploy the app:
npm run build)npmrepository (as a private repo)npm ion the staging server and test it on the staging server environment (equal to production server)npm ion our production serverWhen then using the
div+scriptversion, I get an error when loading local assets, because it's searching for/static/media/logo.2e151009.pngon the parent server (sohttps://parent.com/static/media/logo.2e151009.png) instead of at the server where the CRA is located (https://plugin.domain.com/plugin-name/version-number/static/media/logo.2e151009.png).Building the app 2 times with a different
PUBLIC_URL(1 time for staging and 1 time for the production server, like you and @Timer suggested) will solve the 'problem'.But that implies that I would need to
publishboth versions tonpm.That is a bit grim and cumbersome in my opinion, since both builds are exactly the same, except for the
PUBLIC_URL.I hope you understand my use case a bit more.
If you still have some questions, I'm happy to answer them offcourse 🙂
viankakrisna commentedon Jan 16, 2018
@MichaelDeBoey maybe setting
PUBLIC_URL=__STUB__URL__and running search & replace on the generated assets will solve your problem?MichaelDeBoey commentedon Jan 16, 2018
@viankakrisna That could maybe be a solution indeed. 🙂
I'm also looking into setting
__webpack_public_path__on the fly (like described in the docs), by having something likeAnd dropping the
PUBLIC_URLvariable.@gaearon This solution could maybe be embedded inside CRA as an opt-in option?
gaearon commentedon Jan 17, 2018
Tbh this sounds a bit too esoteric to me. I think it’s cool if this workaround is working for you but I don’t think we’ll be embracing something like this as a first-class feature. Usually when you need something like this you end up needing even more customizations, and at that point ejecting, forking or “rewiring” but be better anyway.
I think I understand the problem you're describing with
parent.comwebsite. But how is this related to the staging/production difference you also mention? Do you mean you only usediv+scripton staging, butiframein production? Or do you have two separate problems (one caused by iframe/script difference, and another by production/staging difference)?MichaelDeBoey commentedon Jan 17, 2018
@gaearon Well I sort of have 2 problems indeed, but they're related
Problem 1 is the breaking assets when using the
div+script.This can be solved by building the app with a correct
PUBLIC_URL(likePUBLIC_URL=https://plugin.domain.com/plugin-name/version-number).But solving it right that causes a new problem, which is that I have to build the app 2 times, because the
PUBLIC_URLneeds to be set different for the staging/production server.gaearon commentedon Jan 17, 2018
The only other solution I can see is #3708 (comment).
It won't work for you if you use
pushStaterouting because then if the user loadshttp://plugin.com/plugin-name/my/client-side/paththen the assets will be requested relative to that. But I’m not sure you’re using client-side routing like this?Other than that I don’t really see other good options.
MichaelDeBoey commentedon Jan 17, 2018
@gaearon I'm using client-side routing (
react-router), so setting the homepage won't work either 😕I've already looked into setting
__webpack_public_path__to the file-path of the current running script (ref: StackOverflow), which would be possible by callingdocument.currentScript(ref: MDN) and having this answer as a fallback, which would be a possible solution to set it dynamically on the fly...I really think this could be the default implementation for the
PUBLIC_URLparam, since it will always be correct I think?Implementation would be something like
gaearon commentedon Jan 17, 2018
Maybe. I'm afraid I'm out of suggestions because I don't know how
__webpack_public_path__works in webpack.MichaelDeBoey commentedon Jan 17, 2018
@gaearon I found it in their docs 🙂
https://webpack.js.org/guides/public-path/#on-the-fly
MichaelDeBoey commentedon Jan 17, 2018
@gaearon I don't know how
PUBLIC_URLis implemented right now, but I think that my solution could be a possible default for it?So instead of using a relative path, use an absolute path (the app-root directory).
I think this will probably (as a default) be the best solution instead of deriving it from
homepage(inpackage.json) or by setting thePUBLIC_URLmanually in most cases.We can still keep those 2 as a way to set it manually if we want?
gaearon commentedon Jan 17, 2018
I'm not sure. If you can write a proposal in another issue with how it should work instead we can take a look.
MichaelDeBoey commentedon Jan 17, 2018
@gaearon OK I'll try to submit one asap 🙂
MichaelDeBoey commentedon Jan 17, 2018
@gaearon Made a proposal in #3834 🙂
JSONRice commentedon Jun 4, 2018
@MichaelDeBoey you might want to have a look at this: https://itnext.io/so-you-want-to-host-your-single-age-react-app-on-github-pages-a826ab01e48
If you want to pre-deploy or deploy you could even have a bash script to take care of the PUBLIC_URL parameters.
FYI @gaearon