Skip to content

Commit

Permalink
Add Support for CRA 5
Browse files Browse the repository at this point in the history
  • Loading branch information
jaxyeh committed Nov 18, 2021
1 parent 776922c commit 9f3faa7
Show file tree
Hide file tree
Showing 9 changed files with 10,106 additions and 13,740 deletions.
15 changes: 6 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

**C**reate **R**eact **A**pp **C**onfiguration **O**verride is an easy and comprehensible configuration layer for create-react-app.

Get all the benefits of create-react-app **and** customization without using 'eject' by adding a single configuration (e.g. `craco.config.js`) file at the root of your application and customize your eslint, babel, postcss configurations and many more.
Get all the benefits of create-react-app **and** customization without using 'eject' by adding a single `craco.config.js` file at the root of your application and customize your eslint, babel, postcss configurations and many more.

All you have to do is create your app using [create-react-app](https://github.com/facebook/create-react-app/) and customize the configuration file.
All you have to do is create your app using [create-react-app](https://github.com/facebook/create-react-app/) and customize the configuration with a `craco.config.js` file.

## Support

Expand All @@ -22,7 +22,7 @@ All you have to do is create your app using [create-react-app](https://github.co
- [Configuration File](#configuration-file)
- [Configuration Helpers](#configuration-helpers)
- [Exporting your Configuration](#exporting-your-configuration)
- [Setting a Custom Location for the configuration file](#setting-a-custom-location-for-cracoconfigjs)
- [Setting a Custom Location for `craco.config.js`](#setting-a-custom-location-for-cracoconfigjs)
- [CRA toolchain for Beginners](#cra-toolchain-for-beginners)
- [Notes on CRA Configurations and Problem Solving](#notes-on-cra-configurations-and-problem-solving)
- [Ejecting CRA to Learn](#ejecting-cra-to-learn)
Expand Down Expand Up @@ -99,16 +99,13 @@ $ npm run build

## Configuration

CRACO is configured with a `craco.config.ts`, `craco.config.js`, `.cracorc.ts`, `.cracorc.js` or `.cracorc` file, or [a file specified in `package.json`](#setting-a-custom-location-for-cracoconfigjs). This file is divided into sections representing the major parts of what makes up the default create react app.
CRACO is configured with a `craco.config.js`, `.cracorc.js` or `.cracorc` file. This file is divided into sections representing the major parts of what makes up the default create react app.

If there are multiple configuration files in the same directory, CRACO will only use one. The priority order is:

1. `package.json`
1. `craco.config.ts`
1. `craco.config.js`
1. `.cracorc.ts`
1. `.cracorc.js`
1. `.cracorc`
2. `.cracorc.js`
3. `.cracorc`

### Configuration File

Expand Down
63 changes: 9 additions & 54 deletions lib/config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
const { cosmiconfigSync } = require("cosmiconfig");
const { default: tsLoader } = require("@endemolshinegroup/cosmiconfig-typescript-loader");

const path = require("path");

const { getArgs } = require("./args");
const { configFilePath } = require("./paths");
const { isFunction, isArray, deepMergeWithArray } = require("./utils");
const { log } = require("./logger");
const { projectRoot } = require("./paths");
const { deepMergeWithArray, isArray, isFunction, isString } = require("./utils");
const { applyCracoConfigPlugins } = require("./features/plugins");
const { POSTCSS_MODES } = require("./features/webpack/style/postcss");
const { ESLINT_MODES } = require("./features/webpack/eslint");
Expand All @@ -29,21 +23,6 @@ const DEFAULT_CONFIG = {
}
};

const moduleName = "craco";
const explorer = cosmiconfigSync(moduleName, {
searchPlaces: [
"package.json",
`${moduleName}.config.ts`,
`${moduleName}.config.js`,
`.${moduleName}rc.ts`,
`.${moduleName}rc.js`,
`.${moduleName}rc`
],
loaders: {
".ts": tsLoader
}
});

function ensureConfigSanity(cracoConfig) {
if (isArray(cracoConfig.plugins)) {
cracoConfig.plugins.forEach((x, index) => {
Expand All @@ -61,39 +40,15 @@ function processCracoConfig(cracoConfig, context) {
return applyCracoConfigPlugins(resultingCracoConfig, context);
}

function getConfigPath() {
const args = getArgs();

if (args.config.isProvided) {
return path.resolve(projectRoot, args.config.value);
} else {
const packageJsonPath = path.join(projectRoot, "package.json");

const package = require(packageJsonPath);

if (package.cracoConfig && isString(package.cracoConfig)) {
// take it as the path to the config file if it's path-like, otherwise assume it contains the config content below
return path.resolve(projectRoot, package.cracoConfig);
} else {
const result = explorer.search(projectRoot);

if (result === null) {
throw new Error(
"craco: Config file not found. check if file exists at root (craco.config.ts, craco.config.js, .cracorc.js, .cracorc.json, .cracorc.yaml, .cracorc)"
);
}

return result.filepath;
}
}
}

function getConfigAsObject(context) {
const configFilePath = getConfigPath();
log("Config file path resolved to: ", configFilePath);
const result = explorer.load(configFilePath);
if (configFilePath == undefined || configFilePath.length == 0) {
throw new Error("craco: Config file not found. check if file exists at root (craco.config.js, .cracorc.js, .cracorc)");
}

log("Found craco config file at: ", configFilePath);

const configAsObject = isFunction(result.config) ? result.config(context) : result.config;
const config = require(configFilePath);
const configAsObject = isFunction(config) ? config(context) : config;

if (!configAsObject) {
throw new Error("craco: Config function didn't return a config object.");
Expand Down
2 changes: 1 addition & 1 deletion lib/features/jest/create-jest-babel-transform.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const babelJest = require("babel-jest");
const babelJest = require("babel-jest").default;

const { isArray } = require("../../utils");
/**
Expand Down
7 changes: 5 additions & 2 deletions lib/features/jest/jest-babel-transform.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const { loadCracoConfigAsync } = require("../../config");
const { createJestBabelTransform } = require("./create-jest-babel-transform");

let jestBabelTransform;
Expand All @@ -7,9 +8,11 @@ let jestBabelTransform;
// uses that to process files.
module.exports = {
...createJestBabelTransform(),
process(src, filename, config, transformOptions) {
async processAsync(src, filename, config, transformOptions) {
if (!jestBabelTransform) {
jestBabelTransform = createJestBabelTransform(config.globals._cracoConfig);
const context = { env: process.env.NODE_ENV };
const cracoConfig = await loadCracoConfigAsync(context);
jestBabelTransform = createJestBabelTransform(cracoConfig);
}

return jestBabelTransform.process(src, filename, config, transformOptions);
Expand Down
9 changes: 2 additions & 7 deletions lib/features/jest/merge-jest-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@ const { projectRoot } = require("../../paths");

const BABEL_TRANSFORM_ENTRY_KEY = "^.+\\.(js|jsx|mjs|cjs|ts|tsx)$";

function overrideBabelTransform(jestConfig, cracoConfig, transformKey) {
// The cracoConfig needs to be available within the jest-babel-transform in order to honor its settings.
// This approach is based on https://github.com/facebook/jest/issues/1468#issuecomment-384825178
jestConfig.globals = jestConfig.globals || {};
jestConfig.globals._cracoConfig = cracoConfig;

function overrideBabelTransform(jestConfig, transformKey) {
jestConfig.transform[transformKey] = require.resolve("./jest-babel-transform");

log("Overrided Jest Babel transformer.");
Expand All @@ -27,7 +22,7 @@ function configureBabel(jestConfig, cracoConfig) {

if (isArray(presets) || isArray(plugins)) {
if (jestConfig.transform[BABEL_TRANSFORM_ENTRY_KEY]) {
overrideBabelTransform(jestConfig, cracoConfig, BABEL_TRANSFORM_ENTRY_KEY);
overrideBabelTransform(jestConfig, BABEL_TRANSFORM_ENTRY_KEY);
} else {
throw new Error(`craco: Cannot find Jest transform entry for Babel ${BABEL_TRANSFORM_ENTRY_KEY}.`);
}
Expand Down
4 changes: 3 additions & 1 deletion lib/features/webpack/style/postcss.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ function extendsPostcss(match, { plugins, env }) {
}

if (plugins) {
postcssPlugins = typeof plugins === "function" ? plugins(postcssPlugins) : postcssPlugins.concat(plugins);
postcssPlugins = typeof plugins === "function"
? plugins(postcssPlugins)
: postcssPlugins.concat(plugins);

log("Added PostCSS plugins.");
}
Expand Down
39 changes: 38 additions & 1 deletion lib/paths.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,47 @@
const path = require("path");
const fs = require("fs");
const { getArgs } = require("./args");
const { log } = require("./logger");
const { isString } = require("./utils");

const projectRoot = fs.realpathSync(process.cwd());
const packageJsonPath = path.join(projectRoot, "package.json");

log("Project root path resolved to: ", projectRoot);

let configFilePath = "";

const configFilenames = ["craco.config.js", ".cracorc.js", ".cracorc"];

const args = getArgs();

if (args.config.isProvided) {
configFilePath = path.resolve(projectRoot, args.config.value);
} else {
const package = require(packageJsonPath);

if (package.cracoConfig) {
if (!isString(package.cracoConfig)) {
throw new Error("craco: 'cracoConfig' value must be a string.");
}

configFilePath = path.resolve(projectRoot, package.cracoConfig);
} else {
for (const filename of configFilenames) {
const filePath = path.join(projectRoot, filename);

if (fs.existsSync(filePath)) {
configFilePath = filePath;
break;
}
}
}
}

log("Config file path resolved to: ", configFilePath);

module.exports = {
projectRoot
projectRoot,
packageJsonPath,
configFilePath
};
Loading

0 comments on commit 9f3faa7

Please sign in to comment.