feat: init
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
'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');
|
||||
|
||||
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();
|
||||
// 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.publicUrlOrPath;
|
||||
const publicPath = config.output.publicPath;
|
||||
const buildFolder = path.relative(process.cwd(), paths.appBuild);
|
||||
printHostingInstructions(appPackage, publicUrl, publicPath, buildFolder, useYarn);
|
||||
},
|
||||
err => {
|
||||
const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true';
|
||||
if (tscCompileOnError) {
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
'Compiled with the following type errors (you may want to check these before deploying your app):\n',
|
||||
),
|
||||
);
|
||||
printBuildError(err);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
|
||||
let errMessage = err.message;
|
||||
|
||||
// Add additional information for postcss errors
|
||||
if (Object.prototype.hasOwnProperty.call(err, 'postcssNode')) {
|
||||
errMessage += '\nCompileError: Begins at CSS selector ' + err['postcssNode'].selector;
|
||||
}
|
||||
|
||||
messages = formatWebpackMessages({
|
||||
errors: [errMessage],
|
||||
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,
|
||||
});
|
||||
}
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
var exec = require('child_process').exec;
|
||||
const fs = require('fs');
|
||||
|
||||
var args = process.argv.slice(2);
|
||||
const oldVersionDetails = args[0];
|
||||
const newVersionDetails = args[1];
|
||||
const newVersion = args[2];
|
||||
|
||||
const relativeEnvironment = './src/app/environment/version.ts';
|
||||
const relativeIndex = './public/index.html';
|
||||
|
||||
exec('cat ' + relativeEnvironment, (err, stdout, stderr) => {
|
||||
stdout = stdout.replace("'" + oldVersionDetails + "'", "'" + newVersionDetails + "'");
|
||||
stdout = stdout.replace("'" + oldVersionDetails.substr(0, 3) + "'", "'" + newVersion + "'");
|
||||
fs.writeFileSync(relativeEnvironment, stdout);
|
||||
});
|
||||
|
||||
exec('cat ' + relativeIndex, (err, stdout, stderr) => {
|
||||
stdout = stdout.replace(oldVersionDetails, newVersionDetails);
|
||||
fs.writeFileSync(relativeIndex, stdout);
|
||||
});
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
const fs = require('fs');
|
||||
const Path = require('path');
|
||||
const _ = require('lodash');
|
||||
|
||||
const appUrl = '../src/app';
|
||||
const componentsUrl = `${appUrl}/components`;
|
||||
const modelsUrl = `${appUrl}/models`;
|
||||
const scenesUrl = `${appUrl}/scenes`;
|
||||
const servicesUrl = `${appUrl}/services`;
|
||||
|
||||
const routes = new Map();
|
||||
|
||||
const isDirectory = path => fs.lstatSync(path).isDirectory();
|
||||
|
||||
// pwd must start with 'src/...'
|
||||
const getAbsolutePath = (path, pwd = appUrl) => {
|
||||
if (path[0] === '.') {
|
||||
const mergePath = Path.resolve(pwd, path);
|
||||
|
||||
console.log({ pwd, path, resolve: mergePath });
|
||||
return mergePath;
|
||||
}
|
||||
|
||||
path = path.replace(/^app\//, appUrl + '/');
|
||||
path = path.replace(/^environment\//, appUrl + '/environment/');
|
||||
path = path.replace(/^common\//, appUrl + '/common/');
|
||||
path = path.replace(/^components\//, appUrl + '/components/');
|
||||
path = path.replace(/^services\//, appUrl + '/services/');
|
||||
path = path.replace(/^scenes\//, appUrl + '/scenes/');
|
||||
path = path.replace(/^apps\//, appUrl + '/apps/');
|
||||
|
||||
return Path.resolve(path);
|
||||
};
|
||||
const renameItem = item => {
|
||||
// Keywords that should be skipped
|
||||
const toSkip = [
|
||||
'.',
|
||||
'..',
|
||||
'feather',
|
||||
'README.md',
|
||||
'react-feather',
|
||||
'unicons.eot',
|
||||
'unicons.svg',
|
||||
'unicons.ttf',
|
||||
'unicons.woff',
|
||||
'unicons.woff2',
|
||||
];
|
||||
|
||||
const name = item.split('.')[0];
|
||||
const extension = item.split('.')[1] ? `.${item.split('.')[1]}` : undefined;
|
||||
|
||||
return toSkip.includes(item)
|
||||
? item
|
||||
: `${_.lowerCase(name).replace(/ /g, '-')}${extension ? extension : ''}`;
|
||||
};
|
||||
|
||||
const updateMap = (rootUrl, fileOrFolderPath = false) => {
|
||||
let newFileOrFolderPath = rootUrl;
|
||||
if (fileOrFolderPath) {
|
||||
const oldFileOrFolderPath = `${rootUrl}/${fileOrFolderPath}`;
|
||||
newFileOrFolderPath = `${rootUrl}/${fileOrFolderPath}`;
|
||||
routes.set(getAbsolutePath(oldFileOrFolderPath, '.'), true);
|
||||
}
|
||||
|
||||
if (isDirectory(newFileOrFolderPath)) {
|
||||
const files = fs.readdirSync(newFileOrFolderPath);
|
||||
files.forEach(fileOrFolderPath => {
|
||||
updateMap(newFileOrFolderPath, fileOrFolderPath);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const processRename = (rootUrl, fileOrFolderPath = false) => {
|
||||
let newFileOrFolderPath = rootUrl;
|
||||
|
||||
if (fileOrFolderPath) {
|
||||
const newFileOrFolderName = renameItem(fileOrFolderPath);
|
||||
const oldFileOrFolderPath = `${rootUrl}/${fileOrFolderPath}`;
|
||||
newFileOrFolderPath = `${rootUrl}/${newFileOrFolderName}`;
|
||||
|
||||
fs.renameSync(oldFileOrFolderPath, newFileOrFolderPath);
|
||||
}
|
||||
|
||||
if (isDirectory(newFileOrFolderPath)) {
|
||||
const files = fs.readdirSync(newFileOrFolderPath);
|
||||
files.forEach(fileOrFolderPath => {
|
||||
processRename(newFileOrFolderPath, fileOrFolderPath);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const recursiveWatchingImports = (rootPath, fileOrFolderPath = false) => {
|
||||
const nextPath = fileOrFolderPath ? `${rootPath}/${fileOrFolderPath}` : rootPath;
|
||||
if (!isDirectory(nextPath)) {
|
||||
let content = fs.readFileSync(nextPath, { encoding: 'utf-8' });
|
||||
|
||||
if (nextPath.includes('/environment/')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const importedPaths = Array.from(
|
||||
content.matchAll(/^(import|export .*?from) .*?('|")(.*?)('|").*?$/gm),
|
||||
).map(s => s[3]);
|
||||
|
||||
importedPaths.forEach(path => {
|
||||
const absolutePath = getAbsolutePath(path, rootPath);
|
||||
|
||||
//Test if absolutePath is in map
|
||||
if (
|
||||
routes.has(absolutePath) ||
|
||||
routes.has(absolutePath + '.js') ||
|
||||
routes.has(absolutePath + '.jsx') ||
|
||||
routes.has(absolutePath + '.ts') ||
|
||||
routes.has(absolutePath + '.tsx') ||
|
||||
routes.has(absolutePath + '.scss') ||
|
||||
routes.has(absolutePath + '.less')
|
||||
) {
|
||||
const newPath = path.split('/').map(renameItem).join('/');
|
||||
content = content.replace(path, newPath);
|
||||
}
|
||||
});
|
||||
|
||||
fs.writeFileSync(nextPath, content);
|
||||
} else {
|
||||
const files = fs.readdirSync(nextPath);
|
||||
files.forEach(fileOrFolderPath => {
|
||||
recursiveWatchingImports(nextPath, fileOrFolderPath);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const cleanFiles = async () => {
|
||||
//Fill up map with all the files we gonna rename
|
||||
updateMap(componentsUrl);
|
||||
|
||||
// Now we should look at each files to see if there is a match with the previous changes and modify the related imports
|
||||
recursiveWatchingImports(appUrl);
|
||||
|
||||
//Rename files and folders recursivelly
|
||||
processRename(componentsUrl);
|
||||
};
|
||||
|
||||
cleanFiles();
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
var connect = require('connect');
|
||||
var serveStatic = require('serve-static');
|
||||
connect()
|
||||
.use(serveStatic(__dirname + '/../public/'), {
|
||||
fallthrough: true,
|
||||
})
|
||||
.use((req, res, next) => {
|
||||
req.path = req.url = '/index.html';
|
||||
serveStatic(__dirname + '/../public/')(req, res, next);
|
||||
})
|
||||
.listen(8080, function() {
|
||||
console.log('Server running on 8080...');
|
||||
});
|
||||
@@ -0,0 +1,138 @@
|
||||
'use strict';
|
||||
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
process.env.BABEL_ENV = 'development';
|
||||
process.env.NODE_ENV = 'development';
|
||||
|
||||
// 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');
|
||||
|
||||
const fs = require('fs');
|
||||
const chalk = require('react-dev-utils/chalk');
|
||||
const webpack = require('webpack');
|
||||
const WebpackDevServer = require('webpack-dev-server');
|
||||
const clearConsole = require('react-dev-utils/clearConsole');
|
||||
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
|
||||
const {
|
||||
choosePort,
|
||||
createCompiler,
|
||||
prepareProxy,
|
||||
prepareUrls,
|
||||
} = require('react-dev-utils/WebpackDevServerUtils');
|
||||
const openBrowser = require('react-dev-utils/openBrowser');
|
||||
const paths = require('../config/paths');
|
||||
const configFactory = require('../config/webpack.config');
|
||||
const createDevServerConfig = require('../config/webpackDevServer.config');
|
||||
|
||||
const useYarn = fs.existsSync(paths.yarnLockFile);
|
||||
const isInteractive = process.stdout.isTTY;
|
||||
|
||||
// Warn and crash if required files are missing
|
||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Tools like Cloud9 rely on this.
|
||||
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
|
||||
const HOST = process.env.HOST || '0.0.0.0';
|
||||
|
||||
if (process.env.HOST) {
|
||||
console.log(
|
||||
chalk.cyan(
|
||||
`Attempting to bind to HOST environment variable: ${chalk.yellow(
|
||||
chalk.bold(process.env.HOST),
|
||||
)}`,
|
||||
),
|
||||
);
|
||||
console.log(`If this was unintentional, check that you haven't mistakenly set it in your shell.`);
|
||||
console.log(`Learn more here: ${chalk.yellow('https://bit.ly/CRA-advanced-config')}`);
|
||||
console.log();
|
||||
}
|
||||
|
||||
// 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(() => {
|
||||
// We attempt to use the default port but if it is busy, we offer the user to
|
||||
// run on a different port. `choosePort()` Promise resolves to the next free port.
|
||||
return choosePort(HOST, DEFAULT_PORT);
|
||||
})
|
||||
.then(port => {
|
||||
if (port == null) {
|
||||
// We have not found a port.
|
||||
return;
|
||||
}
|
||||
|
||||
const config = configFactory('development');
|
||||
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
|
||||
const appName = require(paths.appPackageJson).name;
|
||||
const useTypeScript = fs.existsSync(paths.appTsConfig);
|
||||
const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true';
|
||||
const urls = prepareUrls(protocol, HOST, port, paths.publicUrlOrPath.slice(0, -1));
|
||||
const devSocket = {
|
||||
warnings: warnings => devServer.sockWrite(devServer.sockets, 'warnings', warnings),
|
||||
errors: errors => devServer.sockWrite(devServer.sockets, 'errors', errors),
|
||||
};
|
||||
// Create a webpack compiler that is configured with custom messages.
|
||||
const compiler = createCompiler({
|
||||
appName,
|
||||
config,
|
||||
devSocket,
|
||||
urls,
|
||||
useYarn,
|
||||
useTypeScript,
|
||||
tscCompileOnError,
|
||||
webpack,
|
||||
});
|
||||
// Load proxy config
|
||||
const proxySetting = require(paths.appPackageJson).proxy;
|
||||
const proxyConfig = prepareProxy(proxySetting, paths.appPublic, paths.publicUrlOrPath);
|
||||
// Serve webpack assets generated by the compiler over a web server.
|
||||
const serverConfig = createDevServerConfig(proxyConfig, urls.lanUrlForConfig);
|
||||
const devServer = new WebpackDevServer(compiler, serverConfig);
|
||||
// Launch WebpackDevServer.
|
||||
devServer.listen(port, HOST, err => {
|
||||
if (err) {
|
||||
return console.log(err);
|
||||
}
|
||||
if (isInteractive) {
|
||||
clearConsole();
|
||||
}
|
||||
|
||||
// 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(chalk.cyan('Starting the development server...\n'));
|
||||
openBrowser(urls.localUrlForBrowser);
|
||||
});
|
||||
|
||||
['SIGINT', 'SIGTERM'].forEach(function (sig) {
|
||||
process.on(sig, function () {
|
||||
devServer.close();
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
if (err && err.message) {
|
||||
console.log(err.message);
|
||||
}
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,53 @@
|
||||
'use strict';
|
||||
|
||||
// Do this as the first thing so that any code reading it knows the right env.
|
||||
process.env.BABEL_ENV = 'test';
|
||||
process.env.NODE_ENV = 'test';
|
||||
process.env.PUBLIC_URL = '';
|
||||
|
||||
// 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');
|
||||
|
||||
|
||||
const jest = require('jest');
|
||||
const execSync = require('child_process').execSync;
|
||||
let argv = process.argv.slice(2);
|
||||
|
||||
function isInGitRepository() {
|
||||
try {
|
||||
execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isInMercurialRepository() {
|
||||
try {
|
||||
execSync('hg --cwd . root', { stdio: 'ignore' });
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Watch unless on CI or explicitly running all tests
|
||||
if (
|
||||
!process.env.CI &&
|
||||
argv.indexOf('--watchAll') === -1 &&
|
||||
argv.indexOf('--watchAll=false') === -1
|
||||
) {
|
||||
// https://github.com/facebook/create-react-app/issues/5210
|
||||
const hasSourceControl = isInGitRepository() || isInMercurialRepository();
|
||||
argv.push(hasSourceControl ? '--watch' : '--watchAll');
|
||||
}
|
||||
|
||||
|
||||
jest.run(argv);
|
||||
Reference in New Issue
Block a user