Skip to content

Commit eb60b34

Browse files
committed
refactor: lazy loading for html-wepback-plugin
1 parent fd5d9ce commit eb60b34

File tree

2 files changed

+61
-24
lines changed

2 files changed

+61
-24
lines changed

app-config-webpack/src/index.test.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { resolve, join } from 'path';
2-
import webpack from 'webpack';
2+
import webpack, { Compiler } from 'webpack';
33
import HtmlPlugin from 'html-webpack-plugin';
44
import AppConfigPlugin, { regex, loader, Options } from './index';
55

@@ -47,6 +47,37 @@ describe('frontend-webpack-project example', () => {
4747
});
4848
});
4949

50+
it('should throw an error if html-webpack-plugin is not available and headerInjection is true', () => {
51+
process.env.APP_CONFIG = JSON.stringify({ externalApiUrl: 'https://localhost:3999' });
52+
jest.isolateModules(async () => {
53+
jest.mock('html-webpack-plugin', () => {
54+
throw new Error('html-webpack-plugin not found');
55+
});
56+
57+
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
58+
59+
try {
60+
await new Promise<void>((done, reject) => {
61+
webpack([createOptions({ headerInjection: true })], (err, stats) => {
62+
if (err) return reject(err);
63+
if (!stats) return reject(new Error('no stats'));
64+
if (stats.hasErrors()) reject(stats.toString());
65+
done();
66+
});
67+
});
68+
} catch (err) {
69+
expect(consoleErrorSpy).toHaveBeenCalledTimes(3);
70+
expect(consoleErrorSpy).toHaveBeenCalledWith('html-webpack-plugin not found');
71+
expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to resolve html-webpack-plugin');
72+
expect(consoleErrorSpy).toHaveBeenCalledWith(
73+
'Either include the module in your dependencies and enable the webpack plugin, or set headerInjection to false in your configuration.',
74+
);
75+
} finally {
76+
consoleErrorSpy.mockRestore();
77+
}
78+
});
79+
});
80+
5081
it('reads environment variable for app-config', async () => {
5182
process.env.APP_CONFIG = JSON.stringify({ externalApiUrl: 'https://localhost:3999' });
5283

app-config-webpack/src/index.ts

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { join } from 'path';
22
import { Compiler } from 'webpack';
3-
import HtmlWebpackPlugin, { HtmlTagObject } from 'html-webpack-plugin';
43
import type { ConfigLoadingOptions, SchemaLoadingOptions } from '@app-config/main';
54

65
import { regex } from './loader';
@@ -87,28 +86,35 @@ export default class AppConfigPlugin implements Options {
8786

8887
injectHead(compiler: Compiler) {
8988
compiler.hooks.compilation.tap('AppConfigPlugin', (compilation) => {
90-
HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapPromise(
91-
'AppConfigPlugin',
92-
async ({ headTags, ...html }) => {
93-
// remove placeholder <script id="app-config"></script> if it exists
94-
const newTags: HtmlTagObject[] = headTags.filter(
95-
({ attributes }) => attributes.id !== 'app-config',
96-
);
97-
98-
newTags.push({
99-
tagName: 'script',
100-
attributes: { id: 'app-config', type: 'text/javascript' },
101-
innerHTML: ``,
102-
voidTag: false,
103-
meta: {},
104-
});
105-
106-
return {
107-
...html,
108-
headTags: newTags,
109-
};
110-
},
111-
);
89+
import('html-webpack-plugin').then((module) => {
90+
const HtmlWebpackPlugin = module.default;
91+
HtmlWebpackPlugin.getHooks(compilation).alterAssetTagGroups.tapPromise(
92+
'AppConfigPlugin',
93+
async ({ headTags, ...html }) => {
94+
// remove placeholder <script id="app-config"></script> if it exists
95+
const newTags = headTags.filter(
96+
({ attributes }) => attributes.id !== 'app-config',
97+
);
98+
99+
newTags.push({
100+
tagName: 'script',
101+
attributes: { id: 'app-config', type: 'text/javascript' },
102+
innerHTML: ``,
103+
voidTag: false,
104+
meta: {},
105+
});
106+
107+
return {
108+
...html,
109+
headTags: newTags,
110+
};
111+
},
112+
);
113+
}).catch((error) => {
114+
console.error(error.message);
115+
console.error('Failed to resolve html-webpack-plugin');
116+
console.error('Either include the module in your dependencies and enable the webpack plugin, or set headerInjection to false in your configuration.');
117+
});
112118
});
113119
}
114120
}

0 commit comments

Comments
 (0)