Skip to content

Commit b743c7d

Browse files
committed
fix: Restore old webpack 4 code path to fix hmr after refresh
Related to storybookjs/storybook#15233.
1 parent 31ce4e8 commit b743c7d

1 file changed

Lines changed: 134 additions & 43 deletions

File tree

src/plugin.ts

Lines changed: 134 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,18 @@ export default class DocgenPlugin implements webpack.WebpackPluginInstance {
143143
}
144144

145145
apply(compiler: webpack.Compiler): void {
146+
// Property compiler.version is set only starting from webpack 5
147+
const webpackVersion = compiler.webpack?.version || "";
148+
const isWebpack5 = parseInt(webpackVersion.split(".")[0], 10) >= 5;
149+
150+
if (isWebpack5) {
151+
this.applyWebpack5(compiler);
152+
} else {
153+
this.applyWebpack4(compiler);
154+
}
155+
}
156+
157+
applyWebpack5(compiler: webpack.Compiler): void {
146158
const pluginName = "DocGenPlugin";
147159
const {
148160
docgenOptions,
@@ -156,29 +168,24 @@ export default class DocgenPlugin implements webpack.WebpackPluginInstance {
156168
const { exclude = [], include = ["**/**.tsx"] } = this.options;
157169
const isExcluded = matchGlob(exclude);
158170
const isIncluded = matchGlob(include);
159-
// Property compiler.version is set only starting from webpack 5
160-
const webpackVersion = compiler.webpack?.version || "";
161-
const isWebpack5 = parseInt(webpackVersion.split(".")[0], 10) >= 5;
162171

163172
compiler.hooks.compilation.tap(
164173
pluginName,
165174
(compilation: webpack.Compilation) => {
166-
if (isWebpack5) {
167-
// Since this file is needed only for webpack 5, load it only then
168-
// to simplify the implementation of the file.
169-
//
170-
// eslint-disable-next-line
171-
const { DocGenDependency } = require("./dependency");
175+
// Since this file is needed only for webpack 5, load it only then
176+
// to simplify the implementation of the file.
177+
//
178+
// eslint-disable-next-line
179+
const { DocGenDependency } = require("./dependency");
172180

173-
compilation.dependencyTemplates.set(
174-
// eslint-disable-next-line
175-
// @ts-ignore: Webpack 4 type
176-
DocGenDependency,
177-
// eslint-disable-next-line
178-
// @ts-ignore: Webpack 4 type
179-
new DocGenDependency.Template()
180-
);
181-
}
181+
compilation.dependencyTemplates.set(
182+
// eslint-disable-next-line
183+
// @ts-ignore: Webpack 4 type
184+
DocGenDependency,
185+
// eslint-disable-next-line
186+
// @ts-ignore: Webpack 4 type
187+
new DocGenDependency.Template()
188+
);
182189

183190
compilation.hooks.seal.tap(pluginName, () => {
184191
const modulesToProcess: [string, webpack.Module][] = [];
@@ -217,38 +224,122 @@ export default class DocgenPlugin implements webpack.WebpackPluginInstance {
217224
// 3. Process and parse each module and add the type information
218225
// as a dependency
219226
modulesToProcess.forEach(([name, module]) => {
220-
if (isWebpack5) {
221-
// Since this file is needed only for webpack 5, load it only then
222-
// to simplify the implementation of the file.
223-
//
227+
// Since this file is needed only for webpack 5, load it only then
228+
// to simplify the implementation of the file.
229+
//
230+
// eslint-disable-next-line
231+
const { DocGenDependency } = require("./dependency");
232+
233+
module.addDependency(
224234
// eslint-disable-next-line
225-
const { DocGenDependency } = require("./dependency");
226-
227-
module.addDependency(
228-
// eslint-disable-next-line
229-
// @ts-ignore: Webpack 4 type
230-
new DocGenDependency(
231-
generateDocgenCodeBlock({
232-
filename: name,
233-
source: name,
234-
componentDocs: docGenParser.parseWithProgramProvider(
235-
name,
236-
() => tsProgram
237-
),
238-
...generateOptions,
239-
}).substring(name.length)
240-
)
241-
);
242-
} else {
243-
// Assume webpack 4 or earlier
244-
processModule(docGenParser, module, tsProgram, generateOptions);
245-
}
235+
// @ts-ignore: Webpack 4 type
236+
new DocGenDependency(
237+
generateDocgenCodeBlock({
238+
filename: name,
239+
source: name,
240+
componentDocs: docGenParser.parseWithProgramProvider(
241+
name,
242+
() => tsProgram
243+
),
244+
...generateOptions,
245+
}).substring(name.length)
246+
)
247+
);
246248
});
247249
});
248250
}
249251
);
250252
}
251253

254+
applyWebpack4(compiler: webpack.Compiler): void {
255+
const { docgenOptions, compilerOptions } = this.getOptions();
256+
const parser = docGen.withCompilerOptions(compilerOptions, docgenOptions);
257+
const { exclude = [], include = ["**/**.tsx"] } = this.options;
258+
const isExcluded = matchGlob(exclude);
259+
const isIncluded = matchGlob(include);
260+
261+
compiler.hooks.make.tap(this.name, (compilation) => {
262+
compilation.hooks.seal.tap(this.name, () => {
263+
const modulesToProcess: webpack.Module[] = [];
264+
265+
compilation.modules.forEach((module: webpack.Module) => {
266+
// eslint-disable-next-line
267+
// @ts-ignore: Webpack 4 type
268+
if (!module.built) {
269+
// eslint-disable-next-line
270+
// @ts-ignore: Webpack 4 type
271+
debugExclude(`Ignoring un-built module: ${module.userRequest}`);
272+
return;
273+
}
274+
275+
// eslint-disable-next-line
276+
// @ts-ignore: Webpack 4 type
277+
if (module.external) {
278+
// eslint-disable-next-line
279+
// @ts-ignore: Webpack 4 type
280+
debugExclude(`Ignoring external module: ${module.userRequest}`);
281+
return;
282+
}
283+
284+
// eslint-disable-next-line
285+
// @ts-ignore: Webpack 4 type
286+
if (!module.rawRequest) {
287+
debugExclude(
288+
// eslint-disable-next-line
289+
// @ts-ignore: Webpack 4 type
290+
`Ignoring module without "rawRequest": ${module.userRequest}`
291+
);
292+
return;
293+
}
294+
295+
// eslint-disable-next-line
296+
// @ts-ignore: Webpack 4 type
297+
if (isExcluded(module.userRequest)) {
298+
debugExclude(
299+
// eslint-disable-next-line
300+
// @ts-ignore: Webpack 4 type
301+
`Module not matched in "exclude": ${module.userRequest}`
302+
);
303+
return;
304+
}
305+
306+
// eslint-disable-next-line
307+
// @ts-ignore: Webpack 4 type
308+
if (!isIncluded(module.userRequest)) {
309+
debugExclude(
310+
// eslint-disable-next-line
311+
// @ts-ignore: Webpack 4 type
312+
`Module not matched in "include": ${module.userRequest}`
313+
);
314+
return;
315+
}
316+
317+
// eslint-disable-next-line
318+
// @ts-ignore: Webpack 4 type
319+
debugInclude(module.userRequest);
320+
modulesToProcess.push(module);
321+
});
322+
323+
const tsProgram = ts.createProgram(
324+
// eslint-disable-next-line
325+
// @ts-ignore: Webpack 4 type
326+
modulesToProcess.map((v) => v.userRequest),
327+
compilerOptions
328+
);
329+
330+
modulesToProcess.forEach((m) =>
331+
processModule(parser, m, tsProgram, {
332+
docgenCollectionName: "STORYBOOK_REACT_CLASSES",
333+
setDisplayName: true,
334+
typePropName: "type",
335+
})
336+
);
337+
338+
cache.save();
339+
});
340+
});
341+
}
342+
252343
getOptions(): {
253344
docgenOptions: docGen.ParserOptions;
254345
generateOptions: {

0 commit comments

Comments
 (0)