无法使用自定义PUBLIC_URL构建create-react-app项目


73

我正在努力

PUBLIC_URL=http://example.com npm run build

使用最新的create-react-script构建的项目。

但是,%PUBLIC_URL%in的出现public/index.html被替换为空字符串,而不是期望值PUBLIC_URL

public/index.html 包含类似的代码

<script src="%PUBLIC_URL%/static/js/jarvis.widget.min.js"></script>

数小时的互联网搜索和堆栈溢出表明几乎没有写关于 PUBLIC_URL。我从GitHub克隆了create-react-app,并且一直在浏览代码,但尚未获得启发。

有人对我做错了什么建议吗?


网址应为字符串```PUBLIC_URL =“ example.com ” npm run build
d_bhatnagar

Answers:


57

如果其他答案对您没有帮助,则中还有一个homepage字段package.json。运行后,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",

您只需将其添加为中的根字段之一package.json,例如

{
  // ...
  "scripts": {
    // ...
  },
  "homepage": "https://example.com"
}

成功设置后,可通过homepagePUBLIC_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.

1
目前,实际上存在一个阻止其按预期工作的错误:github.com/facebook/create-react-app/issues/8813
redbmk

2
当我回到react-scripts 3.3.0时,这对我有用。
仔细思考

据我所知,设置homepage似乎覆盖了PUBLIC_URL
Jacksonkr

45

像我这样的人正在构建中寻找这样的东西:

<script type="text/javascript" src="https://dsomething.cloudfront.net/static/js/main.ec7f8972.js">

然后设置https://dsomething.cloudfront.nethomepageinpackage.json将不起作用。

1.快速解决方案

像这样构建项目:
(Windows)

set PUBLIC_URL=https://dsomething.cloudfront.net&&npm run build

(Linux / Mac)

PUBLIC_URL=https://dsomething.cloudfront.net npm run build

你会得到

<script type="text/javascript" src="https://dsomething.cloudfront.net/static/js/main.ec7f8972.js">

在您建立的index.html中

2.永久和推荐的解决方案

.env在项目根目录(package.json所在的位置)创建一个名为的文件。
在此文件中编写以下内容(URL两端不要加引号):

PUBLIC_URL=https://dsomething.cloudfront.net

像往常一样构建您的项目(npm run build
这还将生成带有以下内容的index.html:

<script type="text/javascript" src="https://dsomething.cloudfront.net/static/js/main.ec7f8972.js">

3.奇怪的解决方案(在最新的react-scripts版本中将不起作用)

将此添加到您的package.json中
“主页”中:“ http://://dsomething.cloudfront.net”,

然后将使用以下命令生成index.html:

<script type="text/javascript" src="//dsomething.cloudfront.net/static/js/main.ec7f8972.js">

基本上与以下内容相同:

<script type="text/javascript" src="https://dsomething.cloudfront.net/static/js/main.ec7f8972.js">

以我的理解。

Github问题 Github评论


1
我不太确定为什么他们要解决这个问题。您建议的唯一适用于我的解决方案是第三个解决方案,它的确确实看起来很奇怪。因此,我仍然认为这是一个错误。或者有人可以向我解释在此问题结束之前的最后评论的含义吗?
人:MarosBeťko

在最新的react脚本版本中将无法使用,请使用.env方法。
Gautam Krishna R

20

那不是使用PUBLIC_URL变量的方式。根据文档,您可以在HTML中使用PUBLIC_URL:

<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">

或在您的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'} />;
}

并不是将PUBLIC_URL设置为您选择的值,而是将文件存储在Webpack构建系统之外的部署中的一种方法。

要查看此内容,请运行您的CRA应用并将其添加到src/index.js文件中:

console.log('public url: ', process.env.PUBLIC_URL)

您会看到该URL已经存在。

CRA文档中了解更多信息。


7

实际上,在不同的操作系统之间,设置环境变量的方式是不同的。

Windows(cmd.exe)

set PUBLIC_URL=http://xxxx.com&&npm start

(注意:缺少空格是有意的。)

Linux,macOS(Bash)

 PUBLIC_URL=http://xxxx.com npm start

推荐的: cross-env

{
  "scripts": {
    "serve": "cross-env PUBLIC_URL=http://xxxx.com npm start"
  }
}

参考:create-react-app / README.md#在主机上的外壳中添加临时环境变量·facebookincubator / create-react-app


1
为什么npm startbuild脚本中有?
罗什迪

{“ scripts”:{“ start”:“ npm run serve”}}
JimmyLv19年

6

看一下文档。您可以拥有一个.env文件来拾取PUBLIC_URL

尽管您应该记住它的用途-

您可以使用此变量强制将资产逐字引用到您提供的网址(包括主机名)。当使用CDN托管应用程序时,这可能特别有用。


2

当您尝试在github页面中托管react应用时,此问题变得很明显。

我是怎么解决的

在我的主应用程序文件中,app.tsx该文件中包含路由器。我设置了基本名称,例如, <BrowserRouter basename="/Seans-TypeScript-ReactJS-Redux-Boilerplate/">

请注意,这是一个相对URL,这完全简化了在本地运行和托管的功能。基本名称值与GitHub上的存储库标题匹配。这是GitHub页面将自动创建的路径。

这就是我要做的。

查看托管在GitHub页面上的工作示例,网址为:

https://sean-bradley.github.io/Seans-TypeScript-ReactJS-Redux-Boilerplate/


但是在硬刷新页面转到404错误页面之后
Vigneshwaran Chandrasekaran

是我的答案有问题还是反应有问题?
肖恩·布拉德利

我只是问是否有解决该硬刷新问题的解决方案?
Vigneshwaran Chandrasekaran

1

不知道为什么您无法设置它。在源代码中PUBLIC_URL优先于homepage

const envPublicUrl = process.env.PUBLIC_URL;
...
const getPublicUrl = appPackageJson =>
  envPublicUrl || require(appPackageJson).homepage;

您可以尝试在他们的代码中设置断点,以查看哪些逻辑覆盖了您的环境变量。


0

作为记录在这里创建反应的,应用程序将仅进口环境变量开头的REACT_APP_,所以PUBLIC_URL,我相信,通过@redbmk提到,来自homepage中设置package.json文件。


0

如果您看到那里的源代码,他们将检查是否process.env.NODE_ENV === 'development'返回true,并且它们会自动删除主机URL,仅返回路径。

例如,如果您设置如下

PUBLIC_URL=http://example.com/static/

他们将删除http://example.com并仅返回/static

但是,由于您仅将root URL设置为http://example.com,所以它们将仅返回空字符串,因为URL字符串中没有子路径。

这只有当你调用发生react-scripts start,如果你打电话react-scripts build,然后isEnvDevelopmentfalse,所以它会立即http://example.com为你的设置中的.env文件。

这是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 '/';
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.