【问题标题】:Use static JSON file after build on create-react-app在 create-react-app 上构建后使用静态 JSON 文件
【发布时间】:2019-12-04 15:17:04
【问题描述】:

我正在编写一个 create-react-app 网络应用程序,它将为不同的客户、不同的域、具有相同的代码库、仅更改一个 JSON 配置文件以自定义标题、标签、主题等。

问题是当我构建时,config.json 文件夹中不存在 build (可能是由于 Webpack 的捆绑包)。这意味着我不能简单地更改构建应用程序上的配置文件,从而难以部署到多个域。

有没有办法让我的config.json 在构建后不会消失?

【问题讨论】:

    标签: reactjs webpack create-react-app


    【解决方案1】:

    在构建之前将您的 config.json 放在公共文件夹中会将其复制到“/build/config.json”。

    但是,'public/manifest.json' 文件已经在构建中复制并保存了环境变量,例如 {"short_name": "React App"}。我会考虑将配置选项移到“public/manifest.json”文件中。

    或者,您可以使用构建脚本的修改副本,请参阅:'node_modules/react-scripts/scripts/build.js'。我做了一些快速编辑让您开始:

    // @remove-on-eject-begin
    /**
     * Copyright (c) 2015-present, Facebook, Inc.
     *
     * This source code is licensed under the MIT license found in the
     * LICENSE file in the root directory of this source tree.
     */
    // @remove-on-eject-end
    'use strict';
    
    // Do this as the first thing so that any code reading it knows the right env.
    process.env.BABEL_ENV = 'production';
    process.env.NODE_ENV = 'production';
    
    // Makes the script crash on unhandled rejections instead of silently
    // ignoring them. In the future, promise rejections that are not handled will
    // terminate the Node.js process with a non-zero exit code.
    process.on('unhandledRejection', err => {
      throw err;
    });
    
    // Ensure environment variables are read.
    require('../config/env');
    // @remove-on-eject-begin
    // Do the preflight checks (only happens before eject).
    const verifyPackageTree = require('./utils/verifyPackageTree');
    if (process.env.SKIP_PREFLIGHT_CHECK !== 'true') {
      verifyPackageTree();
    }
    const verifyTypeScriptSetup = require('./utils/verifyTypeScriptSetup');
    verifyTypeScriptSetup();
    // @remove-on-eject-end
    
    const path = require('path');
    const chalk = require('react-dev-utils/chalk');
    const fs = require('fs-extra');
    const webpack = require('webpack');
    const configFactory = require('../config/webpack.config');
    const paths = require('../config/paths');
    const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
    const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
    const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
    const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
    const printBuildError = require('react-dev-utils/printBuildError');
    
    const measureFileSizesBeforeBuild =
      FileSizeReporter.measureFileSizesBeforeBuild;
    const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
    const useYarn = fs.existsSync(paths.yarnLockFile);
    
    // These sizes are pretty large. We'll warn for bundles exceeding them.
    const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
    const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
    
    const isInteractive = process.stdout.isTTY;
    
    // Warn and crash if required files are missing
    if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
      process.exit(1);
    }
    
    // Generate configuration
    const config = configFactory('production');
    
    // We require that you explicitly set browsers and do not fall back to
    // browserslist defaults.
    const { checkBrowsers } = require('react-dev-utils/browsersHelper');
    checkBrowsers(paths.appPath, isInteractive)
      .then(() => {
        // First, read the current file sizes in build directory.
        // This lets us display how much they changed later.
        return measureFileSizesBeforeBuild(paths.appBuild);
      })
      .then(previousFileSizes => {
        // Remove all content but keep the directory so that
        // if you're in it, you don't end up in Trash
        fs.emptyDirSync(paths.appBuild);
        // Merge with the public folder
        copyPublicFolder();
        // Copy the config file
        copyConfigJson();
        // Start the webpack build
        return build(previousFileSizes);
      })
      .then(
        ({ stats, previousFileSizes, warnings }) => {
          if (warnings.length) {
            console.log(chalk.yellow('Compiled with warnings.\n'));
            console.log(warnings.join('\n\n'));
            console.log(
              '\nSearch for the ' +
                chalk.underline(chalk.yellow('keywords')) +
                ' to learn more about each warning.'
            );
            console.log(
              'To ignore, add ' +
                chalk.cyan('// eslint-disable-next-line') +
                ' to the line before.\n'
            );
          } else {
            console.log(chalk.green('Compiled successfully.\n'));
          }
    
          console.log('File sizes after gzip:\n');
          printFileSizesAfterBuild(
            stats,
            previousFileSizes,
            paths.appBuild,
            WARN_AFTER_BUNDLE_GZIP_SIZE,
            WARN_AFTER_CHUNK_GZIP_SIZE
          );
          console.log();
    
          const appPackage = require(paths.appPackageJson);
          const publicUrl = paths.publicUrl;
          const publicPath = config.output.publicPath;
          const buildFolder = path.relative(process.cwd(), paths.appBuild);
          printHostingInstructions(
            appPackage,
            publicUrl,
            publicPath,
            buildFolder,
            useYarn
          );
        },
        err => {
          console.log(chalk.red('Failed to compile.\n'));
          printBuildError(err);
          process.exit(1);
        }
      )
      .catch(err => {
        if (err && err.message) {
          console.log(err.message);
        }
        process.exit(1);
      });
    
    // Create the production build and print the deployment instructions.
    function build(previousFileSizes) {
      // We used to support resolving modules according to `NODE_PATH`.
      // This now has been deprecated in favor of jsconfig/tsconfig.json
      // This lets you use absolute paths in imports inside large monorepos:
      if (process.env.NODE_PATH) {
        console.log(
          chalk.yellow(
            'Setting NODE_PATH to resolve modules absolutely has been deprecated in favor of setting baseUrl in jsconfig.json (or tsconfig.json if you are using TypeScript) and will be removed in a future major release of create-react-app.'
          )
        );
        console.log();
      }
    
      console.log('Creating an optimized production build...');
    
      const compiler = webpack(config);
      return new Promise((resolve, reject) => {
        compiler.run((err, stats) => {
          let messages;
          if (err) {
            if (!err.message) {
              return reject(err);
            }
            messages = formatWebpackMessages({
              errors: [err.message],
              warnings: [],
            });
          } else {
            messages = formatWebpackMessages(
              stats.toJson({ all: false, warnings: true, errors: true })
            );
          }
          if (messages.errors.length) {
            // Only keep the first error. Others are often indicative
            // of the same problem, but confuse the reader with noise.
            if (messages.errors.length > 1) {
              messages.errors.length = 1;
            }
            return reject(new Error(messages.errors.join('\n\n')));
          }
          if (
            process.env.CI &&
            (typeof process.env.CI !== 'string' ||
              process.env.CI.toLowerCase() !== 'false') &&
            messages.warnings.length
          ) {
            console.log(
              chalk.yellow(
                '\nTreating warnings as errors because process.env.CI = true.\n' +
                  'Most CI servers set it automatically.\n'
              )
            );
            return reject(new Error(messages.warnings.join('\n\n')));
          }
    
          return resolve({
            stats,
            previousFileSizes,
            warnings: messages.warnings,
          });
        });
      });
    }
    
    function copyPublicFolder() {
      fs.copySync(paths.appPublic, paths.appBuild, {
        dereference: true,
        filter: file => file !== paths.appHtml,
      });
    }
    
    // CUSTOM FUNCTION TO COPY CONFIG.JSON
    function copyConfigJson() {
        fs.copy(
            path.resolve(paths.appPath, PATH_TO_CONFIG),
            path.resolve(paths.appBuild, PATH_TO_DESTINATION),
            {dereference: true},
        });
    }
    

    【讨论】:

      猜你喜欢
      • 2018-12-29
      • 2019-02-18
      • 1970-01-01
      • 2019-11-07
      • 2019-04-27
      • 2020-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多