@tech-wizards/favicons-webpack-plugin
Version:
Let webpack generate all your favicons and icons for you
119 lines (112 loc) • 4.71 kB
JavaScript
;
var path = require('path');
var SingleEntryPlugin = require('webpack/lib/SingleEntryPlugin');
module.exports.compileTemplate = function compileTemplate (options, context, compilation) {
// The entry file is just an empty helper as the dynamic template
// require is added in "loader.js"
var outputOptions = {
filename: options.statsFilename,
publicPath: compilation.outputOptions.publicPath
};
// Create an additional child compiler which takes the template
// and turns it into an Node.JS html factory.
// This allows us to use loaders during the compilation
var compilerName = getCompilerName(context, outputOptions.filename);
var childCompiler = compilation.createChildCompiler(compilerName, outputOptions);
childCompiler.context = context;
var singleEntryPlugin = new SingleEntryPlugin(context, '!!' + require.resolve('./favicons.js') + '?' +
JSON.stringify({
outputFilePrefix: options.prefix,
icons: options.icons,
background: options.background,
persistentCache: options.persistentCache,
appName: options.title
}) + '!' + options.logo);
(compilation.hooks ? singleEntryPlugin.apply(childCompiler) : childCompiler.apply(singleEntryPlugin));
// Fix for "Uncaught TypeError: __webpack_require__(...) is not a function"
// Hot module replacement requires that every child compiler has its own
// cache. @see https://github.com/ampedandwired/html-webpack-plugin/pull/179
// (webpack 4 compliant + back compat)
(childCompiler.hooks
? childCompiler.hooks.compilation.tap.bind(childCompiler.hooks.compilation, 'FaviconsWebpackPluginCompilation')
: childCompiler.plugin.bind(childCompiler, 'compilation')
)((compilation) => {
if (compilation.cache) {
if (!compilation.cache[compilerName]) {
compilation.cache[compilerName] = {};
}
compilation.cache = compilation.cache[compilerName];
}
(compilation.hooks
? compilation.hooks.optimizeChunkAssets.tapAsync.bind(compilation.hooks.optimizeChunkAssets, 'FaviconsWebpackPluginOptimizeChunkAssets')
: compilation.plugin.bind(compilation, 'optimize-chunk-assets')
)((chunks, callback) => {
if (!chunks[0]) {
return callback(compilation.errors[0] || 'Favicons generation failed');
}
var resultFile = chunks[0].files[0];
var resultCode = compilation.assets[resultFile].source();
var resultJson;
try {
/* eslint no-eval:0 */
var result = eval(resultCode);
resultJson = JSON.stringify(result);
} catch (e) {
return callback(e);
}
compilation.assets[resultFile] = {
source: function () {
return resultJson;
},
size: function () {
return resultJson.length;
}
};
callback(null);
});
});
// Compile and return a promise
return new Promise(function (resolve, reject) {
childCompiler.runAsChild(function (err, entries, childCompilation) {
if (err) {
return reject(err);
}
// Replace [hash] placeholders in filename
// In webpack 4 the plugin interface changed, so check for available fns
var outputName = compilation.mainTemplate.getAssetPath
? compilation.mainTemplate.hooks.assetPath.call(outputOptions.filename, {
hash: childCompilation.hash,
chunk: entries[0]
})
: compilation.mainTemplate.applyPluginsWaterfall(
'asset-path',
outputOptions.filename,
{
hash: childCompilation.hash,
chunk: entries[0]
});
// Resolve / reject the promise
if (childCompilation && childCompilation.errors && childCompilation.errors.length) {
var errorDetails = childCompilation.errors.map(function (error) {
return error.message + (error.error ? ':\n' + error.error : '');
}).join('\n');
reject(new Error('Child compilation failed:\n' + errorDetails));
} else if (err) {
reject(err);
} else {
resolve({
outputName: outputName,
stats: JSON.parse(childCompilation.assets[outputName].source())
});
}
});
});
};
/**
* Returns the child compiler name e.g. 'html-webpack-plugin for "index.html"'
*/
function getCompilerName (context, filename) {
var absolutePath = path.resolve(context, filename);
var relativePath = path.relative(context, absolutePath);
return 'favicons-webpack-plugin for "' + (absolutePath.length < relativePath.length ? absolutePath : relativePath) + '"';
}