【问题标题】:Can't build create-react-app project with custom PUBLIC_URL无法使用自定义 PUBLIC_URL 构建 create-react-app 项目
【发布时间】:2017-07-29 21:29:28
【问题描述】:

我在努力

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

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

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

public/index.html 包含类似代码

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

数小时的互联网搜索和堆栈溢出表明,关于PUBLIC_URL 的文章很少。我从 GitHub 克隆了 create-react-app ,一直在浏览代码但还没有开悟。

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

【问题讨论】:

  • url 应该在字符串 ```PUBLIC_URL="example.com" npm run build

标签: javascript reactjs create-react-app


【解决方案1】:

如果其他答案不适合您,package.json 中还有一个 homepage 字段。运行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"
}

通过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.

【讨论】:

【解决方案2】:

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

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

然后在package.json 中将https://dsomething.cloudfront.net 设置为homepage 将不起作用。

1。快速解决方案

像这样构建您的项目:
(窗口)

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。永久和推荐的解决方案

在您的项目根目录(与 package.json 所在的位置相同)创建一个名为 .env 的文件。
在这个文件中写下这个(网址周围没有引号):

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 Issue Github Comment

【讨论】:

  • 我不太确定他们为什么要关闭这个问题。唯一对我有用的解决方案是您建议的第三个解决方案,它确实看起来很奇怪。因此,我仍然认为这是一个错误。或者有人可以在问题关闭之前向我解释最后评论的含义吗?
  • 最新的react scripts版本不支持,请使用.env方式。
  • @Vaibhav 嗨!我面临一个不同的问题。我想将/static/js 路径更改为/static/dashboard/js/。但我在互联网上找不到任何关于如何做到这一点的解决方案。任何想法?我什至也问过一个问题。在这里查看stackoverflow.com/questions/66655025/…
  • 这个答案是对github.com/facebook/create-react-app/issues/8813 中描述的反应错误的解决方案。对此我感激不尽。
【解决方案3】:

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

&lt;link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"&gt;

或者在你的 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 docs阅读更多内容。

【讨论】:

    【解决方案4】:

    其实不同操作系统设置环境变量的方式是不一样的。

    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#adding-temporary-environment-variables-in-your-shell at master · facebookincubator/create-react-app

    【讨论】:

    • 为什么npm start 在build 脚本中?
    • { "scripts": { "start": "npm run serve" } }
    【解决方案5】:

    看看documentation。你可以有一个 .env 文件来获取 PUBLIC_URL

    虽然你应该记住它的用途 -

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

    【讨论】:

      【解决方案6】:

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

      例如,如果你像下面这样设置

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

      他们将删除http://example.com,只返回/static。

      但是,由于您只设置了像 http://example.com 这样的根 URL,它们只会返回一个空字符串,因为您的 URL 字符串中没有子路径。

      只有当你调用react-scripts start时才会发生这种情况,如果你调用react-scripts build,那么isEnvDevelopment将是false,所以它只会返回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 '/';
      }
      

      【讨论】:

        【解决方案7】:

        不知道为什么你不能设置它。在source中,PUBLIC_URL优先于homepage

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

        你可以尝试在他们的代码中设置断点,看看是什么逻辑覆盖了你的环境变量。

        【讨论】:

          【解决方案8】:

          因为documented here create-react-app 只会导入以REACT_APP_ 开头的环境变量,所以我相信@redbmk 提到的PUBLIC_URL 来自package.json 中的homepage 设置文件。

          【讨论】:

            【解决方案9】:

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

            我是如何解决这个问题的,

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

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

            这就是我需要做的。

            查看托管在 GitHub 页面上的工作示例

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

            【讨论】:

            • 但是硬刷新后页面进入404错误页面
            • 这是我的回答有问题,还是反应有问题?
            • 我只是想问有没有解决这个硬刷新问题的方法?
            【解决方案10】:

            此解决方案适用于 Linux bash 命令行:

            1. 转到您的 react 项目根目录。
            2. 在该目录中打开 bash 终端。
            3. 之后运行以下两个命令,您会看到PUBLIC_URL 发生了变化:
            > export PUBLIC_URL=https://example.com
            > npm run build
            

            【讨论】:

              【解决方案11】:

              如果PUBLIC_URL环境变量没有作用,可能是因为this issue,导致PUBLIC_URL在开发中被忽略了。它已在 create-react-app 版本 3.4.0 中修复。

              【讨论】:

                【解决方案12】:

                如果您的应用有路由,请尝试如下方式

                1. 在 package.json 所在的项目根目录中创建一个名为 .env 的文件,然后添加您的生产 URL,如下所示

                  PUBLIC_URL=https://something.com
                  
                2. 在路由配置中将basename添加到BrowserRouter(在App.js/App.jsx中)

                  <BrowserRouter basename="https://something.com">
                  

                【讨论】:

                  猜你喜欢
                  • 2020-06-14
                  • 2017-12-05
                  • 2019-11-16
                  • 1970-01-01
                  • 2020-09-16
                  • 2017-05-20
                  • 2019-02-07
                  • 2018-07-21
                  • 2020-10-10
                  相关资源
                  最近更新 更多