Skip to content

Commit 1087060

Browse files
authored
Merge pull request #3 from xometry/component-build
Add Component Build Command
2 parents 828a8f0 + db511b6 commit 1087060

File tree

4 files changed

+242
-2
lines changed

4 files changed

+242
-2
lines changed

packages/react-scripts/bin/react-scripts.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const scriptIndex = args.findIndex(
2424
const script = scriptIndex === -1 ? args[0] : args[scriptIndex];
2525
const nodeArgs = scriptIndex > 0 ? args.slice(0, scriptIndex) : [];
2626

27-
if (['build', 'eject', 'start', 'test'].includes(script)) {
27+
if (['build', 'eject', 'start', 'test', 'build-component'].includes(script)) {
2828
const result = spawn.sync(
2929
'node',
3030
nodeArgs

packages/react-scripts/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "xometry-react-scripts",
3-
"version": "3.3.1",
3+
"version": "3.4.0",
44
"description": "Xometry configuration and scripts for Create React App.",
55
"repository": {
66
"type": "git",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
// @remove-on-eject-begin
2+
/**
3+
* Copyright (c) 2015-present, Facebook, Inc.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
// @remove-on-eject-end
9+
'use strict';
10+
11+
// Do this as the first thing so that any code reading it knows the right env.
12+
process.env.BABEL_ENV = 'production';
13+
process.env.NODE_ENV = 'production';
14+
15+
// Makes the script crash on unhandled rejections instead of silently
16+
// ignoring them. In the future, promise rejections that are not handled will
17+
// terminate the Node.js process with a non-zero exit code.
18+
process.on('unhandledRejection', err => {
19+
throw err;
20+
});
21+
22+
// Ensure environment variables are read.
23+
require('../config/env');
24+
// @remove-on-eject-begin
25+
// Do the preflight checks (only happens before eject).
26+
const verifyPackageTree = require('./utils/verifyPackageTree');
27+
if (process.env.SKIP_PREFLIGHT_CHECK !== 'true') {
28+
verifyPackageTree();
29+
}
30+
const verifyTypeScriptSetup = require('./utils/verifyTypeScriptSetup');
31+
verifyTypeScriptSetup();
32+
// @remove-on-eject-end
33+
34+
const path = require('path');
35+
const chalk = require('react-dev-utils/chalk');
36+
const fs = require('fs-extra');
37+
const webpack = require('webpack');
38+
const configFactory = require('../config/webpack.config');
39+
const paths = require('../config/paths');
40+
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
41+
const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages');
42+
const printHostingInstructions = require('react-dev-utils/printHostingInstructions');
43+
const FileSizeReporter = require('react-dev-utils/FileSizeReporter');
44+
const printBuildError = require('react-dev-utils/printBuildError');
45+
46+
const measureFileSizesBeforeBuild =
47+
FileSizeReporter.measureFileSizesBeforeBuild;
48+
const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild;
49+
const useYarn = fs.existsSync(paths.yarnLockFile);
50+
51+
// These sizes are pretty large. We'll warn for bundles exceeding them.
52+
const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
53+
const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
54+
55+
const isInteractive = process.stdout.isTTY;
56+
57+
// Warn and crash if required files are missing
58+
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
59+
process.exit(1);
60+
}
61+
62+
// Generate configuration
63+
const config = configFactory('production');
64+
65+
config.optimization.runtimeChunk = false;
66+
config.optimization.splitChunks = {
67+
cacheGroups: {
68+
default: false,
69+
},
70+
};
71+
config.output.filename = 'main.js';
72+
73+
// We require that you explicitly set browsers and do not fall back to
74+
// browserslist defaults.
75+
const { checkBrowsers } = require('react-dev-utils/browsersHelper');
76+
checkBrowsers(paths.appPath, isInteractive)
77+
.then(() => {
78+
// First, read the current file sizes in build directory.
79+
// This lets us display how much they changed later.
80+
return measureFileSizesBeforeBuild(paths.appBuild);
81+
})
82+
.then(previousFileSizes => {
83+
// Remove all content but keep the directory so that
84+
// if you're in it, you don't end up in Trash
85+
fs.emptyDirSync(paths.appBuild);
86+
// Merge with the public folder
87+
copyPublicFolder();
88+
// Start the webpack build
89+
return build(previousFileSizes);
90+
})
91+
.then(
92+
({ stats, previousFileSizes, warnings }) => {
93+
if (warnings.length) {
94+
console.log(chalk.yellow('Compiled with warnings.\n'));
95+
console.log(warnings.join('\n\n'));
96+
console.log(
97+
'\nSearch for the ' +
98+
chalk.underline(chalk.yellow('keywords')) +
99+
' to learn more about each warning.'
100+
);
101+
console.log(
102+
'To ignore, add ' +
103+
chalk.cyan('// eslint-disable-next-line') +
104+
' to the line before.\n'
105+
);
106+
} else {
107+
console.log(chalk.green('Compiled successfully.\n'));
108+
}
109+
110+
console.log('File sizes after gzip:\n');
111+
printFileSizesAfterBuild(
112+
stats,
113+
previousFileSizes,
114+
paths.appBuild,
115+
WARN_AFTER_BUNDLE_GZIP_SIZE,
116+
WARN_AFTER_CHUNK_GZIP_SIZE
117+
);
118+
console.log();
119+
120+
const appPackage = require(paths.appPackageJson);
121+
const publicUrl = paths.publicUrl;
122+
const publicPath = config.output.publicPath;
123+
const buildFolder = path.relative(process.cwd(), paths.appBuild);
124+
printHostingInstructions(
125+
appPackage,
126+
publicUrl,
127+
publicPath,
128+
buildFolder,
129+
useYarn
130+
);
131+
},
132+
err => {
133+
const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true';
134+
if (tscCompileOnError) {
135+
console.log(
136+
chalk.yellow(
137+
'Compiled with the following type errors (you may want to check these before deploying your app):\n'
138+
)
139+
);
140+
printBuildError(err);
141+
} else {
142+
console.log(chalk.red('Failed to compile.\n'));
143+
printBuildError(err);
144+
process.exit(1);
145+
}
146+
}
147+
)
148+
.catch(err => {
149+
if (err && err.message) {
150+
console.log(err.message);
151+
}
152+
process.exit(1);
153+
});
154+
155+
// Create the production build and print the deployment instructions.
156+
function build(previousFileSizes) {
157+
// We used to support resolving modules according to `NODE_PATH`.
158+
// This now has been deprecated in favor of jsconfig/tsconfig.json
159+
// This lets you use absolute paths in imports inside large monorepos:
160+
if (process.env.NODE_PATH) {
161+
console.log(
162+
chalk.yellow(
163+
'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.'
164+
)
165+
);
166+
console.log();
167+
}
168+
169+
console.log('Creating an optimized production component build...');
170+
171+
const compiler = webpack(config);
172+
return new Promise((resolve, reject) => {
173+
compiler.run((err, stats) => {
174+
let messages;
175+
if (err) {
176+
if (!err.message) {
177+
return reject(err);
178+
}
179+
180+
let errMessage = err.message;
181+
182+
// Add additional information for postcss errors
183+
if (Object.prototype.hasOwnProperty.call(err, 'postcssNode')) {
184+
errMessage +=
185+
'\nCompileError: Begins at CSS selector ' +
186+
err['postcssNode'].selector;
187+
}
188+
189+
messages = formatWebpackMessages({
190+
errors: [errMessage],
191+
warnings: [],
192+
});
193+
} else {
194+
messages = formatWebpackMessages(
195+
stats.toJson({
196+
all: false,
197+
warnings: true,
198+
errors: true,
199+
})
200+
);
201+
}
202+
if (messages.errors.length) {
203+
// Only keep the first error. Others are often indicative
204+
// of the same problem, but confuse the reader with noise.
205+
if (messages.errors.length > 1) {
206+
messages.errors.length = 1;
207+
}
208+
return reject(new Error(messages.errors.join('\n\n')));
209+
}
210+
if (
211+
process.env.CI &&
212+
(typeof process.env.CI !== 'string' ||
213+
process.env.CI.toLowerCase() !== 'false') &&
214+
messages.warnings.length
215+
) {
216+
console.log(
217+
chalk.yellow(
218+
'\nTreating warnings as errors because process.env.CI = true.\n' +
219+
'Most CI servers set it automatically.\n'
220+
)
221+
);
222+
return reject(new Error(messages.warnings.join('\n\n')));
223+
}
224+
225+
return resolve({
226+
stats,
227+
previousFileSizes,
228+
warnings: messages.warnings,
229+
});
230+
});
231+
});
232+
}
233+
234+
function copyPublicFolder() {
235+
fs.copySync(paths.appPublic, paths.appBuild, {
236+
dereference: true,
237+
filter: file => file !== paths.appHtml,
238+
});
239+
}

packages/react-scripts/scripts/init.js

+1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ module.exports = function(
127127
{
128128
start: 'react-scripts start',
129129
build: 'react-scripts build',
130+
'build-component': 'react-scripts build-component',
130131
test: 'react-scripts test',
131132
eject: 'react-scripts eject',
132133
},

0 commit comments

Comments
 (0)