[英]Can't build create-react-app project with custom PUBLIC_URL
I'm trying我正在努力
PUBLIC_URL=http://example.com npm run build
with a project built using the latest create-react-script.使用最新的 create-react-script 构建的项目。
However, the occurrences of %PUBLIC_URL%
in public/index.html
are replaced with an empty string, not the expected value PUBLIC_URL
.但是,在
public/index.html
中出现的%PUBLIC_URL%
被替换为空字符串,而不是预期的值PUBLIC_URL
。
public/index.html
contains code like public/index.html
包含类似的代码
<script src="%PUBLIC_URL%/static/js/jarvis.widget.min.js"></script>
Hours of searching the internet and stack overflow show that very little is written about PUBLIC_URL
.数小时的互联网搜索和堆栈溢出表明,关于
PUBLIC_URL
的文章很少。 I cloned create-react-app from GitHub and have been browsing the code but have not yet been enlightened.我从 GitHub 上克隆了 create-react-app,一直在浏览代码,但还没有得到启发。
Does anyone have any suggestions as to what I'm doing wrong?有人对我做错了什么有任何建议吗?
If the other answers aren't working for you, there's also a homepage
field in package.json
.如果其他答案对您不起作用,那么
package.json
中还有一个homepage
字段。 After running npm run build
you should get a message like the following:运行
npm run build
后,您应该会收到如下消息:
The project was built assuming it is hosted at the server root.
To override this, specify the homepage in your package.json.
For example, add this to build it for GitHub Pages:
"homepage" : "http://myname.github.io/myapp",
You would just add it as one of the root fields in package.json
, eg您只需将其添加为
package.json
中的根字段之一,例如
{
// ...
"scripts": {
// ...
},
"homepage": "https://example.com"
}
When it's successfully set, either via homepage
or PUBLIC_URL
, you should instead get a message like this:通过
homepage
或PUBLIC_URL
成功设置后,您应该收到如下消息:
The project was built assuming it is hosted at https://example.com.
You can control this with the homepage field in your package.json.
People like me who are looking for something like this in in build:像我这样在构建中寻找类似东西的人:
<script type="text/javascript" src="https://dsomething.cloudfront.net/static/js/main.ec7f8972.js">
Then setting https://dsomething.cloudfront.net
to homepage
in package.json
will not work.然后将
https://dsomething.cloudfront.net
设置为package.json
中的homepage
将不起作用。
Build your project like this:像这样构建您的项目:
(windows) (视窗)
set PUBLIC_URL=https://dsomething.cloudfront.net&&npm run build
(linux/mac) (Linux/Mac)
PUBLIC_URL=https://dsomething.cloudfront.net npm run build
And you will get你会得到
<script type="text/javascript" src="https://dsomething.cloudfront.net/static/js/main.ec7f8972.js">
in your built index.html在您构建的 index.html 中
Create a file called .env
at your project root(same place where package.json is located).在您的项目根目录(与 package.json 所在的位置相同)创建一个名为
.env
的文件。
In this file write this(no quotes around the url):在这个文件中写下这个(在 url 周围没有引号):
PUBLIC_URL=https://dsomething.cloudfront.net
Build your project as usual ( npm run build
)像往常一样构建你的项目(
npm run build
)
This will also generate index.html with:这也将生成 index.html :
<script type="text/javascript" src="https://dsomething.cloudfront.net/static/js/main.ec7f8972.js">
Add this in your package.json在你的 package.json 中添加这个
"homepage": "http://://dsomething.cloudfront.net", "主页": "http://dsomething.cloudfront.net",
Then index.html will be generated with:然后 index.html 将生成:
<script type="text/javascript" src="//dsomething.cloudfront.net/static/js/main.ec7f8972.js">
Which is basically the same as:这与以下内容基本相同:
<script type="text/javascript" src="https://dsomething.cloudfront.net/static/js/main.ec7f8972.js">
in my understanding.在我的理解中。
That is not how the PUBLIC_URL variable is used.这不是 PUBLIC_URL 变量的使用方式。 According to the documentation , you can use the PUBLIC_URL in your HTML:
根据文档,您可以在 HTML 中使用 PUBLIC_URL:
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
Or in your JavaScript:或者在你的 JavaScript 中:
render() {
// Note: this is an escape hatch and should be used sparingly!
// Normally we recommend using `import` for getting asset URLs
// as described in “Adding Images and Fonts” above this section.
return <img src={process.env.PUBLIC_URL + '/img/logo.png'} />;
}
The PUBLIC_URL is not something you set to a value of your choosing, it is a way to store files in your deployment outside of Webpack's build system. PUBLIC_URL 不是您设置为您选择的值的东西,它是一种在 Webpack 构建系统之外的部署中存储文件的方式。
To view this, run your CRA app and add this to the src/index.js
file:要查看此内容,请运行您的 CRA 应用并将其添加到
src/index.js
文件中:
console.log('public url: ', process.env.PUBLIC_URL)
You'll see the URL already exists.您会看到 URL 已经存在。
Actually the way of setting environment variables is different between different Operating System.实际上,不同操作系统之间设置环境变量的方式是不同的。
set PUBLIC_URL=http://xxxx.com&&npm start
(Note: the lack of whitespace is intentional.) (注意:缺少空格是故意的。)
PUBLIC_URL=http://xxxx.com npm start
cross-env
cross-env
{
"scripts": {
"serve": "cross-env PUBLIC_URL=http://xxxx.com npm start"
}
}
ref: create-react-app/README.md#adding-temporary-environment-variables-in-your-shell at master · facebookincubator/create-react-app ref: create-react-app/README.md#adding-temporary-environment-variables-in-your-shell at master · facebookincubator/create-react-app
Have a look at the documentation .看看文档。 You can have a .env file which picks up the PUBLIC_URL
你可以有一个 .env 文件来获取 PUBLIC_URL
Although you should remember that what its used for -尽管您应该记住它的用途-
You may use this variable to force assets to be referenced verbatim to the url you provide (hostname included).
您可以使用此变量强制将资产逐字引用到您提供的 url(包括主机名)。 This may be particularly useful when using a CDN to host your application.
这在使用 CDN 托管您的应用程序时可能特别有用。
If you see there source code they check if process.env.NODE_ENV === 'development'
returns true
, and they automatically removes host URL and only return path.如果您看到那里的源代码,他们会检查
process.env.NODE_ENV === 'development'
是否返回true
,并且他们会自动删除主机 URL 并且只返回路径。
For example, if you set like below例如,如果您设置如下
PUBLIC_URL=http://example.com/static/
They will remove http://example.com
and only return /static
.他们将删除
http://example.com
并且只返回/static
。
However since you only set root URL like http://example.com
, they will just return an empty string since there no subpath in your URL string.但是,由于您只设置了像
http://example.com
这样的根 URL,因此它们只会返回一个空字符串,因为您的 URL 字符串中没有子路径。
This only happens if you call react-scripts start
, and if you call react-scripts build
then isEnvDevelopment
will be false
, so it will just return http://example.com
as what you set in the .env
file.仅当您调用
react-scripts start
时才会发生这种情况,并且如果您调用react-scripts build
则isEnvDevelopment
将为false
,因此它只会返回http://example.com
作为您在.env
文件中设置的内容。
Here is the source code of getPublicUrlOrPath.js .这是getPublicUrlOrPath.js的源代码。
/**
* Returns a URL or a path with slash at the end
* In production can be URL, abolute path, relative path
* In development always will be an absolute path
* In development can use `path` module functions for operations
*
* @param {boolean} isEnvDevelopment
* @param {(string|undefined)} homepage a valid url or pathname
* @param {(string|undefined)} envPublicUrl a valid url or pathname
* @returns {string}
*/
function getPublicUrlOrPath(isEnvDevelopment, homepage, envPublicUrl) {
const stubDomain = 'https://create-react-app.dev';
if (envPublicUrl) {
// ensure last slash exists
envPublicUrl = envPublicUrl.endsWith('/')
? envPublicUrl
: envPublicUrl + '/';
// validate if `envPublicUrl` is a URL or path like
// `stubDomain` is ignored if `envPublicUrl` contains a domain
const validPublicUrl = new URL(envPublicUrl, stubDomain);
return isEnvDevelopment
? envPublicUrl.startsWith('.')
? '/'
: validPublicUrl.pathname
: // Some apps do not use client-side routing with pushState.
// For these, "homepage" can be set to "." to enable relative asset paths.
envPublicUrl;
}
if (homepage) {
// strip last slash if exists
homepage = homepage.endsWith('/') ? homepage : homepage + '/';
// validate if `homepage` is a URL or path like and use just pathname
const validHomepagePathname = new URL(homepage, stubDomain).pathname;
return isEnvDevelopment
? homepage.startsWith('.')
? '/'
: validHomepagePathname
: // Some apps do not use client-side routing with pushState.
// For these, "homepage" can be set to "." to enable relative asset paths.
homepage.startsWith('.')
? homepage
: validHomepagePathname;
}
return '/';
}
What you are doing wrong, is to expect the PUBLIC_URL and process.env.PUBLIC_URL would have same value. 你做错了,是期望PUBLIC_URL和process.env.PUBLIC_URL具有相同的值。
create-react-app has two different PUBLIC_URL: create-react-app有两个不同的PUBLIC_URL:
The process environment PUBLIC_URL overrides any package.json homepage. 进程环境PUBLIC_URL会覆盖任何package.json主页。 It can be full URL with scheme, host and path.
它可以是带有方案,主机和路径的完整URL。 The host would be used to give correct deployment instructions.
主机将用于提供正确的部署说明。
The process.env.PUBLIC_URL is only the path from process environment PUBLIC_URL or homepage. process.env.PUBLIC_URL仅是进程环境PUBLIC_URL或主页的路径。
Therefore, when you run 因此,当你跑步
PUBLIC_URL=http://example.com npm run build
In React you'll have 在React你会有
process.env.PUBLIC_URL === ''
If you had 如果你有
PUBLIC_URL=http://example.com/foo npm run build
In React you'd have 在React你有
process.env.PUBLIC_URL === '/foo'
Not sure why you aren't able to set it.不知道为什么你不能设置它。 In the source ,
PUBLIC_URL
takes precedence over homepage
在源代码中,
PUBLIC_URL
优先于homepage
const envPublicUrl = process.env.PUBLIC_URL;
...
const getPublicUrl = appPackageJson =>
envPublicUrl || require(appPackageJson).homepage;
You can try setting breakpoints in their code to see what logic is overriding your environment variable.您可以尝试在他们的代码中设置断点,以查看哪些逻辑覆盖了您的环境变量。
如此处所述, create-react-app 只会导入以REACT_APP_
开头的环境变量,因此我相信PUBLIC_URL
,正如@redbmk 所提到的,来自package.json
文件中的homepage
设置。
This problem becomes apparent when you try to host a react app in github pages.当您尝试在 github 页面中托管一个 react 应用程序时,这个问题变得很明显。
How I fixed this,我是如何解决这个问题的,
In in my main application file, called app.tsx
, where I include the router.在我的名为
app.tsx
的主应用程序文件中,我在其中包含了路由器。 I set the basename, eg, <BrowserRouter basename="/Seans-TypeScript-ReactJS-Redux-Boilerplate/">
我设置了基本名称,例如
<BrowserRouter basename="/Seans-TypeScript-ReactJS-Redux-Boilerplate/">
Note that it is a relative url, this completely simplifies the ability to run locally and hosted.请注意,它是一个相对 url,这完全简化了在本地运行和托管的能力。 The basename value, matches the repository title on GitHub.
basename 值与 GitHub 上的存储库标题匹配。 This is the path that GitHub pages will auto create.
这是 GitHub 页面将自动创建的路径。
That is all I needed to do.这就是我需要做的。
See working example hosted on GitHub pages at请参阅托管在 GitHub 页面上的工作示例
https://sean-bradley.github.io/Seans-TypeScript-ReactJS-Redux-Boilerplate/ https://sean-bradley.github.io/Seas-TypeScript-ReactJS-Redux-Boilerplate/
This solution works on a Linux bash command line:此解决方案适用于 Linux bash 命令行:
PUBLIC_URL
changed:PUBLIC_URL
发生了变化:> export PUBLIC_URL=https://example.com
> npm run build
If the PUBLIC_URL
environment variable has no effect, it may be due to this issue , which causes PUBLIC_URL
to be ignored in development.如果
PUBLIC_URL
环境变量没有影响,可能是由于这个问题,导致开发中忽略了PUBLIC_URL
。 It was fixed in create-react-app version 3.4.0 .它已在 create-react-app 版本3.4.0中修复。
If your app has routing, try like below如果您的应用程序有路由,请尝试如下
Create a file called .env at your project root where package.json is located, then add your production URL like below在 package.json 所在的项目根目录创建一个名为 .env 的文件,然后添加您的生产 URL,如下所示
PUBLIC_URL=https://something.com
add basename to BrowserRouter in the route configure (in App.js/ App.jsx)在路由配置中将basename添加到BrowserRouter (在 App.js/App.jsx 中)
<BrowserRouter basename="https://something.com">
First of all the react compiled code is "pure java script".首先反应编译的代码是“纯java脚本”。 As such, from an html page, it is possible to reference this code using something like:
因此,从 html 页面中,可以使用以下方式引用此代码:
< script src="my_compiled_component.js" >< /script >
The creation of react components must not depend on the main website hyperlink. React 组件的创建不能依赖于主网站的超链接。 From react code, to locate the website your components are running from use something like:
从反应代码,找到您的组件正在运行的网站,使用类似:
window.location.protocol + '//'+ window.location.hostname + ':' + window.location.port
Following this pattern it is important to understand that some folders might need to have modified permissions so everybody can find your components through html calls.遵循此模式,重要的是要了解某些文件夹可能需要修改权限,以便每个人都可以通过 html 调用找到您的组件。 How to define where to place the compiled react code?
如何定义将编译后的反应代码放在哪里? This could be done from manually to using something like webpack that allows you to set this output.
这可以从手动完成,也可以使用 webpack 之类的允许您设置此输出的东西来完成。
Open Command Prompt inside your Application's source. 在应用程序源中打开命令提示符。 Run the Command
运行命令
npm run eject
npm运行弹出
Open your scripts/build.js file and add this at the beginning of the file after 'use strict' line 打开您的scripts / build.js文件,并将其添加到“使用严格”行之后的文件开头
'use strict';
....
process.env.PUBLIC_URL = './'
// Provide the (current) path which you want to set here.
.....
Run 跑
npm run build
npm运行构建
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.