Skip to content

Commit 8a2d63e

Browse files
committed
feat: better html-webpack-plugin interop in extract mode
Now html-webpack-plugin's template context contains htmlWebpackPlugin.files.sprites property (Object<filename:string, content:string>). It can be used to inline extracted sprite content directly in page markup. See test/fixtures/html-webpack-plugin/template.ejs for example. ISSUES CLOSED: #194
1 parent 06bf968 commit 8a2d63e

4 files changed

Lines changed: 35 additions & 15 deletions

File tree

lib/plugin.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ class SVGSpritePlugin {
5959
loaderContext[NAMESPACE] = plugin;
6060
});
6161

62-
// Replace placeholders with real URL to symbol (in modules processed by sprite-loader)
62+
// Replace placeholders with real URL to symbol (in modules processed by svg-sprite-loader)
6363
compilation.plugin('after-optimize-chunks', function replacePlaceholdersInModules() {
6464
const map = new MappedList(symbols, this);
6565
const replacements = map.groupItemsBySymbolFile((acc, item) => acc[item.resource] = item.useUrl);
6666
map.items.forEach(item => replaceInModuleSource(item.module, replacements));
6767
});
6868

69-
// Hook into extract-text-webpack-plugin event to replace placeholders with real URL to symbol
69+
// Hook into extract-text-webpack-plugin to replace placeholders with real URL to symbol
7070
compilation.plugin('optimize-extracted-chunks', function replacePlaceholdersInExtractedChunks(chunks) {
7171
const map = new MappedList(symbols, this);
7272
const replacements = map.groupItemsBySymbolFile((acc, item) => acc[item.resource] = item.useUrl);
@@ -82,7 +82,21 @@ class SVGSpritePlugin {
8282
});
8383
});
8484

85-
// Hook into html-webpack-plugin event to replace placeholders with real URL to symbol
85+
// Hook into html-webpack-plugin to add `sprites` variable into template context
86+
compilation.plugin('html-webpack-plugin-before-html-generation', function htmlPluginHook(htmlPluginData, done) {
87+
const { assets } = this;
88+
const map = new MappedList(symbols, this);
89+
const itemsBySprite = map.groupItemsBySpriteFilename();
90+
const sprites = Object.keys(itemsBySprite).reduce((acc, filename) => {
91+
acc[filename] = assets[filename].source();
92+
return acc;
93+
}, {});
94+
95+
htmlPluginData.assets.sprites = sprites;
96+
done(null, htmlPluginData);
97+
});
98+
99+
// Hook into html-webpack-plugin to replace placeholders with real URL to symbol
86100
compilation.plugin('html-webpack-plugin-before-html-processing', function htmlPluginHook(htmlPluginData, done) {
87101
const map = new MappedList(symbols, this);
88102
const replacements = map.groupItemsBySymbolFile((acc, item) => acc[item.resource] = item.useUrl);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="UTF-8">
5+
<title><%= htmlWebpackPlugin.options.title %></title>
6+
</head>
7+
<body>
8+
<% if (htmlWebpackPlugin.files.sprites) { %>
9+
<% for (var spriteFileName in htmlWebpackPlugin.files.sprites) { %>
10+
<%= htmlWebpackPlugin.files.sprites[spriteFileName] %>
11+
<% } %>
12+
<% } %>
13+
14+
<img src="../img/image.svg" alt="">
15+
</body>
16+
</html>

test/fixtures/html-webpack-plugin/template.html

Lines changed: 0 additions & 10 deletions
This file was deleted.

test/loader.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,15 +258,15 @@ describe('loader and plugin', () => {
258258
module: rules(
259259
svgRule({ extract: true }),
260260
rule({
261-
test: /\.html$/,
261+
test: /template\.ejs$/,
262262
loader: 'html-loader'
263263
})
264264
),
265265
plugins: [
266266
new SpritePlugin(),
267267
new HtmlPlugin({
268268
filename: 'index.html',
269-
template: path.resolve(fixturesPath, 'html-webpack-plugin/template.html')
269+
template: path.resolve(fixturesPath, 'html-webpack-plugin/template.ejs')
270270
})
271271
]
272272
});

0 commit comments

Comments
 (0)