Webpack 模式更改 Heroku 暂存 URL

问题描述 投票:0回答:1

我最近启动了一个带有临时和生产环境的 Heroku 管道。我的应用程序是使用 React、NodeJS 和 Webpack 构建的。

当我部署到 staging 时,我的 baseURL 是生产 url,但它应该与前端 staging url 相同。

我已经能够将问题专门隔离到 Webpack 模式上。我无法控制用于暂存的 baseURL,因为 Webpack 模式和 Heroku 似乎需要开发或生产。设置 NODE_ENV=staging 似乎没有改变任何东西。

错误:

我在我的暂存控制台中看到此错误:

xhr.js:258 Refused to connect to 'http://localhost:4000/api/users/login' because it violates the following Content Security Policy directive: "connect-src 'self' https://stagingapp.herokuapp.com".

这个正在生产中:

Access to XMLHttpRequest at 'https://stagingapp.herokuapp.com/api/users/login' from origin 'https://prodapp.herokuapp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'https://stagingapp.herokuapp.com' that is not equal to the supplied origin.

这使得它看起来像是 CORS 和 CSP 问题,因为确实如此。但这只是一个问题,因为我的 Webpack 破坏了 baseURL。当这些对齐时,一切都会按预期进行。

这是我所做的:

  1. 在 Heroku 中,我添加了配置变量(环境变量)——NODE_ENV=staging 用于暂存,NODE_ENV=product 用于生产。

  2. 我尝试了各种调整 Webpack 模式的方法

  3. 我尝试更改我的构建脚本,但 Heroku 只接受构建或 heroku-postbuild 等。我似乎无法使用特定于暂存的脚本

  4. 我尝试使用 Axios 控制 baseURL,但似乎我的 Axios 配置根本没有做太多事情,因为 baseUrl 是在我的构建中确定的,而 Axios 在运行时工作。如果我能让我的 Axios 处理 URL,我认为这就能解决问题,但 Webpack 一直在阻碍。

  5. 我还将我的暂存环境更改为生产环境,看看是否有帮助。现在我的暂存环境可以工作,但我的产品环境也有同样的问题,它调用我的暂存 URL 作为基本 URL,而不是产品 url。

  6. 我也多次阅读了所有文档,但关于如何处理 Heroku 上的 Webpack 构建的内容并不多。

这是我的代码的相关部分:

网页包配置:

mode: process.env.NODE_ENV === 'production' ? 'production' : 'development'

PACKAGE.JSON 构建脚本: 这已经是一百万件事了,我已经尝试过使用 NODE_ENV=staging 并且没有 --mode 生产标签。

"build": "webpack --mode production"

AXIOS CONFIG - 这似乎在生产或登台中没有做任何事情

import axios from 'axios';

// Define base URLs for different environments
const baseURLs = {
  development: 'LOCAL HOST URL',
  staging: 'STAGING URL',
  production: 'PROD URL',
};

// Determine the environment based on NODE_ENV
const environment = process.env.NODE_ENV;

// Create an instance of Axios with a custom configuration
const instance = axios.create({
  // Set the base URL for requests
  baseURL: baseURLs[environment],
  withCredentials: true,
});

export default instance;

服务器 CORS:

const setupCORS = () => {
  // Define allowed origins based on environment
  let allowedOrigin;
  if (process.env.NODE_ENV === 'development') {
    allowedOrigin = 'LOCAL HOST URL';
  } else if (process.env.NODE_ENV === 'staging') {
    allowedOrigin = 'STAGING URL';
  } else if (process.env.NODE_ENV === 'production') {
    allowedOrigin = 'PROD URL';
  }
  // Handle CORS for all routes
  app.use(
    cors({
      origin: allowedOrigin,
      credentials: true,
    }),
  );
};

// Invoke the CORS setup function
setupCORS();

服务器 CSP:

const setupSecurityHeaders = () => {
  // CSP middleware based on environment
  if (process.env.NODE_ENV === 'development') {
    app.use(
      helmet.contentSecurityPolicy({
        directives: {
          defaultSrc: ["'self'"],
          scriptSrc: ["'self'", 'LOCAL HOST URL'],
          connectSrc: ["'self'", 'LOCAL HOST URL'],
        },
      }),
    );
    console.log('setupSecurityHeaders in development');
  } else if (process.env.NODE_ENV === 'staging') {
    app.use(
      helmet.contentSecurityPolicy({
        directives: {
          defaultSrc: ["'self'"],
          scriptSrc: ["'self'", 'STAGING URL'],
          connectSrc: ["'self'", 'STAGING URL'],
          formAction: ["'self'", 'FORM URL'],
        },
      }),
    );
    console.log('setupSecurityHeaders in staging');
  } else if (process.env.NODE_ENV === 'production') {
    // Apply more restrictive CSP for production
    app.use(
      helmet.contentSecurityPolicy({
        directives: {
          defaultSrc: ["'self'"],
          scriptSrc: ["'self'", 'PROD URL'],
          connectSrc: ["'self'", 'PROD URL'],
          formAction: ["'self'", 'FORM URL'],
        },
      }),
    );
    console.log('setupSecurityHeaders in production');
  }
};

// Invoke the security headers function
setupSecurityHeaders();
node.js heroku webpack environment-variables
1个回答
0
投票

在站在马桶上挂钟时滑倒并撞到头后,我找到了答案。和往常一样,这很简单。这就是我所做的:

  1. 在暂存和生产中创建一个

    NODE_ENV
    配置变量并将其设置为“生产”

  2. 创建一个

    TARGET_ENV
    配置变量,并将其设置为暂存中的“暂存”和(你猜对了)生产中的“生产”。确保在 .env 文件中将其设置为“development”。

  3. 将配置文件中的 Webpack 模式设置为以下内容:

mode: process.NODE_ENV === 'production' ? 'production' : 'development',
  1. 如果由于某种原因您还没有导入/需要 webpack,请确保在您的 webpack 配置文件中导入/需要 webpack,并将其添加到您的插件中:
  plugins: [
    new webpack.DefinePlugin({
      TARGET_ENV: JSON.stringify(process.env.TARGET_ENV),
    }),
  ],
};

这将在构建时使用您的配置变量创建一个全局变量。

  1. 在 package.json 中保持构建脚本简单:

    "build": "webpack",

  2. 在 axiosConfig.js(或存储 baseUrl 的任何位置)中,使用

    TARGET_ENV
    ,而不附加
    process.env
    。 (另外,我尝试了
    process.env.REACT_APP_BLAH_BLAH
    ,但没有成功,仅供参考。)

import axios from 'axios';

// Define base URLs for different environments
const baseURLs = {
  development: 'http://localhost:4000',
  staging: 'https://staging.herokuapp.com',
  production: 'https://prod.herokuapp.com',
};

// Determine the environment based on NODE_ENV
const environment = TARGET_ENV;

// Create an instance of Axios with a custom configuration
const instance = axios.create({
  // Set the base URL for requests
  baseURL: baseURLs[environment],
  withCredentials: true,
});

export default instance;

  1. 在管道中,将暂存环境设置为在推送到暂存分支时自动部署,将生产分支设置为在推送到主分支时自动部署。

  2. 从控制台或 Github PR 分别直接推送到每个分支。这将为每个环境创建一个单独的构建。它对我有用,我希望它对你有用。祝你好运。

哦,我还有一个悬而未决的问题:

我不确定在运行初始生产版本后,Heroku 仪表板中的“升级到生产”按钮是否会起作用。

它只会推送最近的暂存更改,还是会覆盖我的生产版本?我最终会测试一下,但如果有人知道,请随时发表评论。

© www.soinside.com 2019 - 2024. All rights reserved.