Skip to content

Commit 011fb19

Browse files
feat: migrate from Create React App to Webpack (#5572)
Co-authored-by: Robert Hebel <[email protected]>
1 parent d82cde2 commit 011fb19

25 files changed

+14713
-12227
lines changed

.eslintrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"@typescript-eslint"
3030
],
3131
"rules": {
32+
"import/no-extraneous-dependencies": ["error", {"devDependencies": true}],
3233
"import/order": ["error", {
3334
"groups": [
3435
["builtin", "external", "internal"],

.gitmodules

Lines changed: 0 additions & 3 deletions
This file was deleted.

README.md

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# SwaggerEditor
22

3-
SwaggerEditor is using [**forked** Create React App](https://github.com/swagger-api/swagger-editor-cra/) as it's building infrastructure.
4-
53
## Table of Contents
64

75
- [Anonymized analytics](#anonymized-analytics)
@@ -309,8 +307,6 @@ Run the following commands to set up the repository for local development:
309307
$ git clone https://github.com/swagger-api/swagger-editor.git
310308
$ cd swagger-editor
311309
$ git checkout next
312-
$ git submodule init
313-
$ git submodule update
314310
$ npm i
315311
$ npm start
316312
```

config/env.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
import dotenv from 'dotenv';
4+
import dotenvExpand from 'dotenv-expand';
5+
6+
import paths from './paths.js';
7+
import { require } from './util.js';
8+
9+
// Make sure that including paths.js after env.js will read .env variables.
10+
delete require.cache[require.resolve('./paths')];
11+
12+
const { NODE_ENV } = process.env;
13+
if (!NODE_ENV) {
14+
throw new Error('The NODE_ENV environment variable is required but was not specified.');
15+
}
16+
17+
// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use
18+
const dotenvFiles = [
19+
`${paths.dotenv}.${NODE_ENV}.local`,
20+
// Don't include `.env.local` for `test` environment
21+
// since normally you expect tests to produce the same
22+
// results for everyone
23+
NODE_ENV !== 'test' && `${paths.dotenv}.local`,
24+
`${paths.dotenv}.${NODE_ENV}`,
25+
paths.dotenv,
26+
].filter(Boolean);
27+
28+
// Load environment variables from .env* files. Suppress warnings using silent
29+
// if this file is missing. dotenv will never modify any environment variables
30+
// that have already been set. Variable expansion is supported in .env files.
31+
// https://github.com/motdotla/dotenv
32+
// https://github.com/motdotla/dotenv-expand
33+
dotenvFiles.forEach((dotenvFile) => {
34+
if (fs.existsSync(dotenvFile)) {
35+
dotenvExpand(
36+
dotenv.config({
37+
path: dotenvFile,
38+
})
39+
);
40+
}
41+
});
42+
43+
// We support resolving modules according to `NODE_PATH`.
44+
// This lets you use absolute paths in imports inside large monorepos:
45+
// https://github.com/facebook/create-react-app/issues/253.
46+
// It works similar to `NODE_PATH` in Node itself:
47+
// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
48+
// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored.
49+
// Otherwise, we risk importing Node.js core modules into an app instead of webpack shims.
50+
// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421
51+
// We also resolve them to make sure all tools using them work consistently.
52+
const appDirectory = fs.realpathSync(process.cwd());
53+
process.env.NODE_PATH = (process.env.NODE_PATH || '')
54+
.split(path.delimiter)
55+
.filter((folder) => folder && !path.isAbsolute(folder))
56+
.map((folder) => path.resolve(appDirectory, folder))
57+
.join(path.delimiter);
58+
59+
// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be
60+
// injected into the application via DefinePlugin in webpack configuration.
61+
const REACT_APP = /^REACT_APP_/i;
62+
63+
function getClientEnvironment(publicUrl) {
64+
const raw = Object.keys(process.env)
65+
.filter((key) => REACT_APP.test(key))
66+
.reduce(
67+
(env, key) => {
68+
return {
69+
...env,
70+
[key]: process.env[key],
71+
};
72+
},
73+
{
74+
// Useful for determining whether we're running in production mode.
75+
// Most importantly, it switches React into the correct mode.
76+
NODE_ENV: process.env.NODE_ENV || 'development',
77+
// Useful for resolving the correct path to static assets in `public`.
78+
// For example, <img src={process.env.PUBLIC_URL + '/img/logo.png'} />.
79+
// This should only be used as an escape hatch. Normally you would put
80+
// images into the `src` and `import` them in code to get their paths.
81+
PUBLIC_URL: publicUrl,
82+
// We support configuring the sockjs pathname during development.
83+
// These settings let a developer run multiple simultaneous projects.
84+
// They are used as the connection `hostname`, `pathname` and `port`
85+
// in webpackHotDevClient. They are used as the `sockHost`, `sockPath`
86+
// and `sockPort` options in webpack-dev-server.
87+
WDS_SOCKET_HOST: process.env.WDS_SOCKET_HOST,
88+
WDS_SOCKET_PATH: process.env.WDS_SOCKET_PATH,
89+
WDS_SOCKET_PORT: process.env.WDS_SOCKET_PORT,
90+
// Whether or not react-refresh is enabled.
91+
// It is defined here so it is available in the webpackHotDevClient.
92+
FAST_REFRESH: process.env.FAST_REFRESH !== 'false',
93+
}
94+
);
95+
// Stringify all values so we can feed into webpack DefinePlugin
96+
const stringified = {
97+
'process.env': Object.keys(raw).reduce((env, key) => {
98+
return { ...env, [key]: JSON.stringify(raw[key]) };
99+
}, {}),
100+
};
101+
102+
return { raw, stringified };
103+
}
104+
105+
export default getClientEnvironment;

config/getHttpsConfig.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import fs from 'fs';
2+
import path from 'path';
3+
import crypto from 'crypto';
4+
import chalk from 'chalk';
5+
6+
import paths from './paths.js';
7+
8+
// Ensure the certificate and key provided are valid and if not
9+
// throw an easy to debug error
10+
function validateKeyAndCerts({ cert, key, keyFile, crtFile }) {
11+
let encrypted;
12+
try {
13+
// publicEncrypt will throw an error with an invalid cert
14+
encrypted = crypto.publicEncrypt(cert, Buffer.from('test'));
15+
} catch (err) {
16+
throw new Error(`The certificate "${chalk.yellow(crtFile)}" is invalid.\n${err.message}`);
17+
}
18+
19+
try {
20+
// privateDecrypt will throw an error with an invalid key
21+
crypto.privateDecrypt(key, encrypted);
22+
} catch (err) {
23+
throw new Error(`The certificate key "${chalk.yellow(keyFile)}" is invalid.\n${err.message}`);
24+
}
25+
}
26+
27+
// Read file and throw an error if it doesn't exist
28+
function readEnvFile(file, type) {
29+
if (!fs.existsSync(file)) {
30+
throw new Error(
31+
`You specified ${chalk.cyan(
32+
type
33+
)} in your env, but the file "${chalk.yellow(file)}" can't be found.`
34+
);
35+
}
36+
return fs.readFileSync(file);
37+
}
38+
39+
// Get the https config
40+
// Return cert files if provided in env, otherwise just true or false
41+
function getHttpsConfig() {
42+
const { SSL_CRT_FILE, SSL_KEY_FILE, HTTPS } = process.env;
43+
const isHttps = HTTPS === 'true';
44+
45+
if (isHttps && SSL_CRT_FILE && SSL_KEY_FILE) {
46+
const crtFile = path.resolve(paths.appPath, SSL_CRT_FILE);
47+
const keyFile = path.resolve(paths.appPath, SSL_KEY_FILE);
48+
const config = {
49+
cert: readEnvFile(crtFile, 'SSL_CRT_FILE'),
50+
key: readEnvFile(keyFile, 'SSL_KEY_FILE'),
51+
};
52+
53+
validateKeyAndCerts({ ...config, keyFile, crtFile });
54+
return config;
55+
}
56+
return isHttps;
57+
}
58+
59+
export default getHttpsConfig;

config/jest/babelTransform.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import babelJest from 'babel-jest';
2+
3+
import { require } from '../util.js';
4+
5+
const hasJsxRuntime = (() => {
6+
if (process.env.DISABLE_NEW_JSX_TRANSFORM === 'true') {
7+
return false;
8+
}
9+
10+
try {
11+
require.resolve('react/jsx-runtime');
12+
return true;
13+
} catch (e) {
14+
return false;
15+
}
16+
})();
17+
18+
export default babelJest.default.createTransformer({
19+
presets: [
20+
[
21+
require.resolve('babel-preset-react-app'),
22+
{
23+
runtime: hasJsxRuntime ? 'automatic' : 'classic',
24+
},
25+
],
26+
],
27+
plugins: ['@babel/plugin-transform-class-static-block'],
28+
babelrc: false,
29+
configFile: false,
30+
});

config/jest/cssTransform.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// This is a custom Jest transformer turning style imports into empty objects.
2+
// http://facebook.github.io/jest/docs/en/webpack.html
3+
4+
export default {
5+
process() {
6+
return 'module.exports = {};';
7+
},
8+
getCacheKey() {
9+
// The output is always the same.
10+
return 'cssTransform';
11+
},
12+
};

config/jest/fileTransform.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import path from 'path';
2+
import camelcase from 'camelcase';
3+
4+
// This is a custom Jest transformer turning file imports into filenames.
5+
// http://facebook.github.io/jest/docs/en/webpack.html
6+
7+
export default {
8+
process(src, filename) {
9+
const assetFilename = JSON.stringify(path.basename(filename));
10+
11+
if (filename.match(/\.svg$/)) {
12+
// Based on how SVGR generates a component name:
13+
// https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6
14+
const pascalCaseFilename = camelcase(path.parse(filename).name, {
15+
pascalCase: true,
16+
});
17+
const componentName = `Svg${pascalCaseFilename}`;
18+
return `const React = require('react');
19+
module.exports = {
20+
__esModule: true,
21+
default: ${assetFilename},
22+
ReactComponent: React.forwardRef(function ${componentName}(props, ref) {
23+
return {
24+
$$typeof: Symbol.for('react.element'),
25+
type: 'svg',
26+
ref: ref,
27+
key: null,
28+
props: Object.assign({}, props, {
29+
children: ${assetFilename}
30+
})
31+
};
32+
}),
33+
};`;
34+
}
35+
36+
return `module.exports = ${assetFilename};`;
37+
},
38+
};

0 commit comments

Comments
 (0)