Skip to content

Commit

Permalink
feat(interop): extract-text-webpack-plugin & html-webpack-plugin interop
Browse files Browse the repository at this point in the history
  • Loading branch information
kisenka committed May 7, 2017
1 parent ef8a4e0 commit a38fdcc
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 105 deletions.
12 changes: 9 additions & 3 deletions lib/configurator.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module.exports = function configurator({ config, context }) {
const target = context.options.target;
const module = context._module;
const compiler = context._compiler;
const compilerName = compiler.name;

const autoConfigured = {
spriteModule: target === 'web' ? loaderDefaults.spriteModule : isomorphicSpriteModule,
Expand All @@ -27,11 +28,16 @@ module.exports = function configurator({ config, context }) {
const finalConfig = merge.all([loaderDefaults, autoConfigured, config || {}]);

/**
* Fix for extract-text-webpack-plugin loader which executes module source as node module,
* so export should be always in commonjs style
* esModule should be `false` when compiles via extract-text-webpack-plugin or html-webpack-plugin.
* Because this compilers executes module as usual node module so export should be always in commonjs style.
* This could be dropped when Node.js will support ES modules natively :)
* @see https://git.io/vS7Sn
* @see https://git.io/v9w60
*/
if (compiler.name === defaults.EXTRACT_TEXT_PLUGIN_COMPILER_NAME) {
if (compilerName && (
compilerName.includes('extract-text-webpack-plugin') ||
compilerName.includes('html-webpack-plugin')
)) {
finalConfig.esModule = false;
}

Expand Down
31 changes: 20 additions & 11 deletions lib/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const Chunk = require('webpack/lib/Chunk');
const SVGCompiler = require('svg-baker');
const Sprite = require('svg-baker/lib/sprite');
const { NAMESPACE } = require('./config');
const { MappedList, replaceInModuleSource } = require('./utils');
const { MappedList, replaceInModuleSource, replaceSpritePlaceholder } = require('./utils');

class SVGSpritePlugin {
constructor() {
Expand All @@ -19,6 +19,7 @@ class SVGSpritePlugin {
return NAMESPACE;
}

// TODO optimize MappedList instantiation in each hook
apply(compiler) {
const plugin = this;
const { symbols } = this.svgCompiler;
Expand All @@ -33,14 +34,14 @@ class SVGSpritePlugin {
// Replace placeholders with real URL to symbol (in modules processed by sprite-loader)
compilation.plugin('after-optimize-chunks', function replacePlaceholdersInModules() {
const map = new MappedList(symbols, this);
const replacements = map.groupSpritesBySymbol((acc, item) => acc[item.resource] = item.url);
const replacements = map.groupItemsBySymbolFile((acc, item) => acc[item.resource] = item.url);
map.items.forEach(item => replaceInModuleSource(item.module, replacements));
});

// Replace placeholders with real URL to symbol (in modules extracted by extract-text-webpack-plugin)
// Hook into extract-text-webpack-plugin event to replace placeholders with real URL to symbol
compilation.plugin('optimize-extracted-chunks', function replacePlaceholdersInExtractedChunks(chunks) {
const map = new MappedList(symbols, this);
const replacements = map.groupSpritesBySymbol((acc, item) => acc[item.resource] = item.useUrl);
const replacements = map.groupItemsBySymbolFile((acc, item) => acc[item.resource] = item.useUrl);

chunks.forEach((chunk) => {
chunk.modules
Expand All @@ -51,23 +52,31 @@ class SVGSpritePlugin {
});
});

// Hook into html-webpack-plugin event to replace placeholders with real URL to symbol
compilation.plugin('html-webpack-plugin-before-html-processing', function htmlPluginHook(htmlPluginData, done) {
const map = new MappedList(symbols, this);
const replacements = map.groupItemsBySymbolFile((acc, item) => acc[item.resource] = item.useUrl);
htmlPluginData.html = replaceSpritePlaceholder(htmlPluginData.html, replacements);
done(null, htmlPluginData);
});

// Create sprite chunk
compilation.plugin('additional-assets', function emitSpriteChunks(done) {
const map = new MappedList(symbols, this);
const sprites = map.groupSymbolsBySprite();
const filenames = Object.keys(sprites);
const itemsBySprite = map.groupItemsBySpriteFilename();
const filenames = Object.keys(itemsBySprite);

return Promise.map(filenames, (spriteFilename) => {
const spriteSymbols = sprites[spriteFilename];
return Promise.map(filenames, (filename) => {
const spriteSymbols = itemsBySprite[filename].map(item => item.symbol);

return Sprite.create({ symbols: spriteSymbols })
.then((sprite) => {
const content = sprite.render();
const chunk = new Chunk(spriteFilename);
const chunk = new Chunk(filename);
chunk.ids = [];
chunk.files.push(spriteFilename);
chunk.files.push(filename);

compilation.assets[spriteFilename] = {
compilation.assets[filename] = {
source() { return content; },
size() { return content.length; }
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require('./styles.css');
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require('./styles.css');
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require('./styles.css');
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.img {
background-image: url('../../img/image.svg');
}
10 changes: 10 additions & 0 deletions test/fixtures/html-webpack-plugin/template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<img src="../img/image.svg" alt="">
<body>
</body>
</html>
Loading

0 comments on commit a38fdcc

Please sign in to comment.