Skip to content

Commit 5ef1e7b

Browse files
fix: avoid unnecessary stringify (#1920)
1 parent d32aeda commit 5ef1e7b

File tree

8 files changed

+170
-67
lines changed

8 files changed

+170
-67
lines changed

.github/workflows/nodejs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ jobs:
5757
matrix:
5858
os: [ubuntu-latest, windows-latest, macos-latest]
5959
node-version: [10.x, 12.x, 14.x]
60-
webpack-version: [next, latest]
60+
webpack-version: [webpack-4, latest]
6161

6262
steps:
6363
- uses: actions/checkout@v2

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,4 @@ test/**/**/binary/**
6565
test/**/dist
6666
test/**/**/dist
6767
test/**/**/**/dist
68+
test/**/stats.json

packages/webpack-cli/lib/utils/Compiler.js

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -55,49 +55,38 @@ class Compiler {
5555
});
5656
}
5757

58-
generateOutput(outputOptions, stats) {
59-
logger.raw(`${stats.toString(this.compilerOptions.stats)}\n`);
60-
if (outputOptions.watch) {
61-
logger.info('watching files for updates...');
62-
}
63-
}
64-
65-
compilerCallback(err, stats, lastHash, options, outputOptions) {
66-
const statsErrors = [];
67-
68-
if (!outputOptions.watch || err) {
69-
// Do not keep cache anymore
70-
this.compiler.purgeInputFileSystem();
71-
}
72-
if (err) {
58+
compilerCallback(error, stats, lastHash, options, outputOptions) {
59+
if (error) {
7360
lastHash = null;
74-
logger.error(err.stack || err);
61+
logger.error(error);
7562
process.exit(1);
7663
}
64+
7765
if (!outputOptions.watch && stats.hasErrors()) {
7866
process.exitCode = 1;
7967
}
80-
if (outputOptions.json === true) {
81-
process.stdout.write(JSON.stringify(stats.toJson(outputOptions), null, 2) + '\n');
82-
} else if (stats.hash !== lastHash) {
68+
69+
if (stats.hash !== lastHash) {
8370
lastHash = stats.hash;
84-
if (stats.compilation && stats.compilation.errors.length !== 0) {
85-
const errors = stats.compilation.errors;
86-
errors.forEach((statErr) => {
87-
const errLoc = statErr.module ? statErr.module.resource : null;
88-
statsErrors.push({ name: statErr.message, loc: errLoc });
89-
});
90-
}
91-
const JSONStats = JSON.stringify(stats.toJson(outputOptions), null, 2);
92-
if (typeof outputOptions.json === 'string') {
71+
72+
if (outputOptions.json === true) {
73+
process.stdout.write(JSON.stringify(stats.toJson(outputOptions), null, 2) + '\n');
74+
} else if (typeof outputOptions.json === 'string') {
75+
const JSONStats = JSON.stringify(stats.toJson(outputOptions), null, 2);
76+
9377
try {
9478
writeFileSync(outputOptions.json, JSONStats);
9579
logger.success(`stats are successfully stored as json to ${outputOptions.json}`);
9680
} catch (err) {
9781
logger.error(err);
9882
}
83+
} else {
84+
logger.raw(`${stats.toString(this.compilerOptions.stats)}\n`);
85+
}
86+
87+
if (outputOptions.watch) {
88+
logger.info('watching files for updates...');
9989
}
100-
return this.generateOutput(outputOptions, stats, statsErrors);
10190
}
10291
}
10392

@@ -107,20 +96,22 @@ class Compiler {
10796
await this.compiler.run((err, stats) => {
10897
if (this.compiler.close) {
10998
this.compiler.close(() => {
110-
const content = this.compilerCallback(err, stats, lastHash, options, outputOptions);
111-
resolve(content);
99+
this.compilerCallback(err, stats, lastHash, options, outputOptions);
100+
101+
resolve();
112102
});
113103
} else {
114-
const content = this.compilerCallback(err, stats, lastHash, options, outputOptions);
115-
resolve(content);
104+
this.compilerCallback(err, stats, lastHash, options, outputOptions);
105+
106+
resolve();
116107
}
117108
});
118109
});
119110
}
120111

121112
async invokeWatchInstance(lastHash, options, outputOptions, watchOptions) {
122113
return this.compiler.watch(watchOptions, (err, stats) => {
123-
return this.compilerCallback(err, stats, lastHash, options, outputOptions);
114+
this.compilerCallback(err, stats, lastHash, options, outputOptions);
124115
});
125116
}
126117

test/build-errors/errors.test.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
'use strict';
2+
const { run } = require('../utils/test-utils');
3+
const { stat, readFile } = require('fs');
4+
const { resolve } = require('path');
5+
6+
describe('errors', () => {
7+
it('should output by default', () => {
8+
const { stdout, exitCode } = run(__dirname);
9+
10+
expect(stdout).toMatch(/ERROR in/);
11+
expect(stdout).toMatch(/Error: Can't resolve/);
12+
expect(exitCode).toBe(1);
13+
});
14+
15+
it('should output JSON with the "json" flag', () => {
16+
const { stdout, exitCode } = run(__dirname, ['--json']);
17+
18+
expect(() => JSON.parse(stdout)).not.toThrow();
19+
expect(exitCode).toBe(1);
20+
21+
const json = JSON.parse(stdout);
22+
23+
expect(json['hash']).toBeDefined();
24+
expect(json['errors']).toHaveLength(1);
25+
// `message` for `webpack@5`
26+
expect(json['errors'][0].message ? json['errors'][0].message : json['errors'][0]).toMatch(/Can't resolve/);
27+
});
28+
29+
it('should store json to a file', (done) => {
30+
const { stdout, exitCode } = run(__dirname, ['--json', 'stats.json']);
31+
32+
expect(stdout).toContain('stats are successfully stored as json to stats.json');
33+
expect(exitCode).toBe(1);
34+
35+
stat(resolve(__dirname, './stats.json'), (err, stats) => {
36+
expect(err).toBe(null);
37+
expect(stats.isFile()).toBe(true);
38+
39+
readFile(resolve(__dirname, 'stats.json'), 'utf-8', (error, data) => {
40+
expect(error).toBe(null);
41+
expect(() => JSON.parse(data)).not.toThrow();
42+
43+
const json = JSON.parse(data);
44+
45+
expect(json['hash']).toBeDefined();
46+
expect(json['errors']).toHaveLength(1);
47+
// `message` for `webpack@5`
48+
expect(json['errors'][0].message ? json['errors'][0].message : json['errors'][0]).toMatch(/Can't resolve/);
49+
50+
done();
51+
});
52+
});
53+
});
54+
});

test/build-errors/src/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import unknown from './unknown.mjs';
2+
3+
export default unknown

test/build-warnings/src/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
let obj;
2+
3+
try {
4+
obj = require('unknown');
5+
} catch (e) {
6+
// Ignore
7+
}
8+
9+
export default obj
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
'use strict';
2+
const { run } = require('../utils/test-utils');
3+
const { stat, readFile } = require('fs');
4+
const { resolve } = require('path');
5+
6+
describe('warnings', () => {
7+
it('should output by default', () => {
8+
const { stdout, exitCode } = run(__dirname);
9+
10+
expect(stdout).toMatch(/WARNING in/);
11+
expect(stdout).toMatch(/Error: Can't resolve/);
12+
expect(exitCode).toBe(0);
13+
});
14+
15+
it('should output JSON with the "json" flag', () => {
16+
const { stdout, exitCode } = run(__dirname, ['--json']);
17+
18+
expect(() => JSON.parse(stdout)).not.toThrow();
19+
expect(exitCode).toBe(0);
20+
21+
const json = JSON.parse(stdout);
22+
23+
expect(json['hash']).toBeDefined();
24+
expect(json['warnings']).toHaveLength(1);
25+
// `message` for `webpack@5`
26+
expect(json['warnings'][0].message ? json['warnings'][0].message : json['warnings'][0]).toMatch(/Can't resolve/);
27+
});
28+
29+
it('should store json to a file', (done) => {
30+
const { stdout, exitCode } = run(__dirname, ['--json', 'stats.json']);
31+
32+
expect(stdout).toContain('stats are successfully stored as json to stats.json');
33+
expect(exitCode).toBe(0);
34+
35+
stat(resolve(__dirname, './stats.json'), (err, stats) => {
36+
expect(err).toBe(null);
37+
expect(stats.isFile()).toBe(true);
38+
39+
readFile(resolve(__dirname, 'stats.json'), 'utf-8', (error, data) => {
40+
expect(error).toBe(null);
41+
expect(() => JSON.parse(data)).not.toThrow();
42+
43+
const json = JSON.parse(data);
44+
45+
expect(json['hash']).toBeDefined();
46+
expect(json['warnings']).toHaveLength(1);
47+
// `message` for `webpack@5`
48+
expect(json['warnings'][0].message ? json['warnings'][0].message : json['warnings'][0]).toMatch(/Can't resolve/);
49+
50+
done();
51+
});
52+
});
53+
});
54+
});

test/json/json.test.js

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,49 +5,40 @@ const { resolve } = require('path');
55

66
describe('json flag', () => {
77
it('should return valid json', () => {
8-
const { stdout } = run(__dirname, ['--json']);
9-
10-
// helper function to check if JSON is valid
11-
const parseJson = () => {
12-
return JSON.parse(stdout);
13-
};
14-
// check the JSON is valid.
15-
expect(JSON.parse(stdout)['hash']).toBeTruthy();
16-
expect(JSON.parse(stdout)['version']).toBeTruthy();
17-
expect(JSON.parse(stdout)['time']).toBeTruthy();
18-
expect(parseJson).not.toThrow();
8+
const { stdout, exitCode } = run(__dirname, ['--json']);
9+
10+
expect(() => JSON.parse(stdout)).not.toThrow();
11+
expect(exitCode).toBe(0);
12+
13+
expect(JSON.parse(stdout)['hash']).toBeDefined();
1914
});
2015

2116
it('should store json to a file', (done) => {
22-
const { stdout } = run(__dirname, ['--json', 'stats.json']);
17+
const { stdout, exitCode } = run(__dirname, ['--json', 'stats.json']);
2318

2419
expect(stdout).toContain('stats are successfully stored as json to stats.json');
20+
expect(exitCode).toBe(0);
21+
2522
stat(resolve(__dirname, './stats.json'), (err, stats) => {
2623
expect(err).toBe(null);
2724
expect(stats.isFile()).toBe(true);
28-
done();
29-
});
30-
readFile(resolve(__dirname, 'stats.json'), 'utf-8', (err, data) => {
31-
expect(err).toBe(null);
32-
expect(JSON.parse(data)['hash']).toBeTruthy();
33-
expect(JSON.parse(data)['version']).toBeTruthy();
34-
expect(JSON.parse(data)['time']).toBeTruthy();
35-
expect(() => JSON.parse(data)).not.toThrow();
36-
done();
25+
26+
readFile(resolve(__dirname, 'stats.json'), 'utf-8', (err, data) => {
27+
expect(err).toBe(null);
28+
expect(JSON.parse(data)['hash']).toBeTruthy();
29+
expect(JSON.parse(data)['version']).toBeTruthy();
30+
expect(JSON.parse(data)['time']).toBeTruthy();
31+
expect(() => JSON.parse(data)).not.toThrow();
32+
done();
33+
});
3734
});
3835
});
3936

4037
it('should return valid json with -j alias', () => {
41-
const { stdout } = run(__dirname, ['-j']);
42-
43-
// helper function to check if JSON is valid
44-
const parseJson = () => {
45-
return JSON.parse(stdout);
46-
};
47-
// check the JSON is valid.
48-
expect(JSON.parse(stdout)['hash']).toBeTruthy();
49-
expect(JSON.parse(stdout)['version']).toBeTruthy();
50-
expect(JSON.parse(stdout)['time']).toBeTruthy();
51-
expect(parseJson).not.toThrow();
38+
const { stdout, exitCode } = run(__dirname, ['-j']);
39+
expect(() => JSON.parse(stdout)).not.toThrow();
40+
expect(exitCode).toBe(0);
41+
42+
expect(JSON.parse(stdout)['hash']).toBeDefined();
5243
});
5344
});

0 commit comments

Comments
 (0)