Skip to content

Commit 9d56786

Browse files
committed
Fix how assets are obtained in the pipeline
1 parent 278cc18 commit 9d56786

3 files changed

Lines changed: 192 additions & 38 deletions

File tree

lib/index.js

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ function getAssetPath(compilation, name) {
1717
return path.join(compilation.getPath(compilation.compiler.outputPath), name.split('?')[0]);
1818
}
1919

20-
function getSource(compilation, name) {
21-
const path = getAssetPath(compilation, name);
22-
return fs.readFileSync(path, { encoding: 'utf-8' });
20+
function getSource(asset) {
21+
return asset.source.source();
2322
}
2423

2524
/**
@@ -144,45 +143,41 @@ class BundleTrackerPlugin {
144143
}
145144

146145
/**
147-
* Hook to inject the webpack compilation object
146+
* Hook to handle the assets when they are ready to be emitted
147+
* @param {Compilation} compilation
148148
*/
149-
_handleThisCompilation(compilation) {
150-
this._compilation = compilation;
151-
}
152-
153-
/**
154-
* Hook to handle each compiled asset and set their
155-
* info into the output object
156-
*/
157-
_handleAssetEmitted(assetName) {
158-
const fileInfo = {
159-
name: assetName,
160-
path: getAssetPath(this._compilation, assetName),
161-
};
149+
_handleEmit(compilation) {
150+
Object.keys(compilation.assets).forEach(assetName => {
151+
const fileInfo = {
152+
name: assetName,
153+
path: getAssetPath(compilation, assetName),
154+
};
162155

163-
if (this.options.integrity === true) {
164-
fileInfo.integrity = this._computeIntegrity(getSource(this._compilation, assetName));
165-
}
156+
if (this.options.integrity === true) {
157+
const asset = compilation.getAsset(assetName);
158+
fileInfo.integrity = this._computeIntegrity(getSource(asset));
159+
}
166160

167-
if (this.options.publicPath) {
168-
if (this.options.publicPath === 'auto') {
169-
fileInfo.publicPath = 'auto';
170-
} else {
171-
fileInfo.publicPath = this.options.publicPath + assetName;
161+
if (this.options.publicPath) {
162+
if (this.options.publicPath === 'auto') {
163+
fileInfo.publicPath = 'auto';
164+
} else {
165+
fileInfo.publicPath = this.options.publicPath + assetName;
166+
}
172167
}
173-
}
174168

175-
if (this.options.relativePath === true) {
176-
fileInfo.path = path.relative(this.outputChunkDir, fileInfo.path);
177-
}
169+
if (this.options.relativePath === true) {
170+
fileInfo.path = path.relative(this.outputChunkDir, fileInfo.path);
171+
}
178172

179-
// @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'.
180-
if (this._compilation.assetsInfo) {
181173
// @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'.
182-
fileInfo.sourceFilename = this._compilation.assetsInfo.get(assetName).sourceFilename;
183-
}
174+
if (compilation.assetsInfo) {
175+
// @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'.
176+
fileInfo.sourceFilename = compilation.assetsInfo.get(assetName).sourceFilename;
177+
}
184178

185-
this.assets[assetName] = fileInfo;
179+
this.assets[assetName] = fileInfo;
180+
});
186181
}
187182

188183
/**
@@ -227,10 +222,7 @@ class BundleTrackerPlugin {
227222
apply(compiler) {
228223
this._setParamsFromCompiler(compiler);
229224
compiler.hooks.compile.tap(this.name, this._handleCompile.bind(this));
230-
// The thisCompilation hook is required here because webpack4 does not properly
231-
// inject the stats object with the compilation data into the assetEmitted hook
232-
compiler.hooks.thisCompilation.tap(this.name, this._handleThisCompilation.bind(this));
233-
compiler.hooks.assetEmitted.tap(this.name, this._handleAssetEmitted.bind(this));
225+
compiler.hooks.emit.tap(this.name, this._handleEmit.bind(this));
234226
compiler.hooks.done.tap(this.name, this._handleDone.bind(this));
235227
}
236228
}

tests/base.test.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,87 @@ describe('BundleTrackerPlugin bases tests', () => {
6464
);
6565
});
6666

67+
it('It should generate the stats file when the plugin runs twice and the output assets already exist', done => {
68+
const expectErrors = null;
69+
const expectWarnings = getWebpack4WarningMessage();
70+
71+
// 1st run
72+
testPlugin(
73+
webpack,
74+
{
75+
context: __dirname,
76+
entry: path.resolve(__dirname, 'fixtures', 'index.js'),
77+
output: {
78+
path: OUTPUT_DIR,
79+
filename: 'js/[name].js',
80+
publicPath: 'http://localhost:3000/assets/',
81+
},
82+
plugins: [
83+
new BundleTrackerPlugin({
84+
path: OUTPUT_DIR,
85+
filename: 'webpack-stats.json',
86+
}),
87+
],
88+
},
89+
{
90+
status: 'done',
91+
publicPath: 'http://localhost:3000/assets/',
92+
chunks: {
93+
main: ['js/main.js'],
94+
},
95+
assets: {
96+
'js/main.js': {
97+
name: 'js/main.js',
98+
path: OUTPUT_DIR + '/js/main.js',
99+
publicPath: 'http://localhost:3000/assets/js/main.js',
100+
},
101+
},
102+
},
103+
'webpack-stats.json',
104+
jest.fn(),
105+
expectErrors,
106+
expectWarnings,
107+
);
108+
109+
// 2nd run
110+
testPlugin(
111+
webpack,
112+
{
113+
context: __dirname,
114+
entry: path.resolve(__dirname, 'fixtures', 'index.js'),
115+
output: {
116+
path: OUTPUT_DIR,
117+
filename: 'js/[name].js',
118+
publicPath: 'http://localhost:3000/assets/',
119+
},
120+
plugins: [
121+
new BundleTrackerPlugin({
122+
path: OUTPUT_DIR,
123+
filename: 'webpack-stats.json',
124+
}),
125+
],
126+
},
127+
{
128+
status: 'done',
129+
publicPath: 'http://localhost:3000/assets/',
130+
chunks: {
131+
main: ['js/main.js'],
132+
},
133+
assets: {
134+
'js/main.js': {
135+
name: 'js/main.js',
136+
path: OUTPUT_DIR + '/js/main.js',
137+
publicPath: 'http://localhost:3000/assets/js/main.js',
138+
},
139+
},
140+
},
141+
'webpack-stats.json',
142+
done,
143+
expectErrors,
144+
expectWarnings,
145+
);
146+
});
147+
67148
it('It should add log time when option is set', done => {
68149
const expectErrors = null;
69150
const expectWarnings = getWebpack4WarningMessage();

tests/webpack5.test.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,87 @@ describe('BundleTrackerPlugin bases tests', () => {
6464
);
6565
});
6666

67+
it('It should generate the stats file when the plugin runs twice and the output assets already exist', done => {
68+
const expectErrors = null;
69+
const expectWarnings = getWebpack5WarningMessage();
70+
71+
// 1st run
72+
testPlugin(
73+
webpack5,
74+
{
75+
context: __dirname,
76+
entry: path.resolve(__dirname, 'fixtures', 'index.js'),
77+
output: {
78+
path: OUTPUT_DIR,
79+
filename: 'js/[name].js',
80+
publicPath: 'http://localhost:3000/assets/',
81+
},
82+
plugins: [
83+
new BundleTrackerPlugin({
84+
path: OUTPUT_DIR,
85+
filename: 'webpack-stats.json',
86+
}),
87+
],
88+
},
89+
{
90+
status: 'done',
91+
publicPath: 'http://localhost:3000/assets/',
92+
chunks: {
93+
main: ['js/main.js'],
94+
},
95+
assets: {
96+
'js/main.js': {
97+
name: 'js/main.js',
98+
path: OUTPUT_DIR + '/js/main.js',
99+
publicPath: 'http://localhost:3000/assets/js/main.js',
100+
},
101+
},
102+
},
103+
'webpack-stats.json',
104+
jest.fn(),
105+
expectErrors,
106+
expectWarnings,
107+
);
108+
109+
// 2nd run
110+
testPlugin(
111+
webpack5,
112+
{
113+
context: __dirname,
114+
entry: path.resolve(__dirname, 'fixtures', 'index.js'),
115+
output: {
116+
path: OUTPUT_DIR,
117+
filename: 'js/[name].js',
118+
publicPath: 'http://localhost:3000/assets/',
119+
},
120+
plugins: [
121+
new BundleTrackerPlugin({
122+
path: OUTPUT_DIR,
123+
filename: 'webpack-stats.json',
124+
}),
125+
],
126+
},
127+
{
128+
status: 'done',
129+
publicPath: 'http://localhost:3000/assets/',
130+
chunks: {
131+
main: ['js/main.js'],
132+
},
133+
assets: {
134+
'js/main.js': {
135+
name: 'js/main.js',
136+
path: OUTPUT_DIR + '/js/main.js',
137+
publicPath: 'http://localhost:3000/assets/js/main.js',
138+
},
139+
},
140+
},
141+
'webpack-stats.json',
142+
done,
143+
expectErrors,
144+
expectWarnings,
145+
);
146+
});
147+
67148
it('It should add log time when option is set', done => {
68149
const expectErrors = null;
69150
const expectWarnings = getWebpack5WarningMessage();

0 commit comments

Comments
 (0)