WIP - Allow to use __dirname and __filename in template files (webpack 2 only)

This commit is contained in:
Jan Nicklas 2016-10-29 08:47:05 +02:00
parent 0474662b01
commit 2ea554518a
10 changed files with 97 additions and 61 deletions

View File

@ -44,22 +44,13 @@
/* 0 */
/***/ function(module, exports, __webpack_require__) {
eval("__webpack_require__(1);\n\nvar universal = __webpack_require__(5);\nvar h1 = document.createElement('h1');\nh1.innerHTML = universal();\n\ndocument.body.appendChild(h1);\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./example.js\n// module id = 0\n// module chunks = 0\n//# sourceURL=webpack:///./example.js?");
eval("__webpack_require__(!(function webpackMissingModule() { var e = new Error(\"Cannot find module \\\"./main.css\\\"\"); e.code = 'MODULE_NOT_FOUND'; throw e; }()));\n\nvar universal = __webpack_require__(1);\nvar h1 = document.createElement('h1');\nh1.innerHTML = universal();\n\ndocument.body.appendChild(h1);\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./example.js\n// module id = 0\n// module chunks = 0\n//# sourceURL=webpack:///./example.js?");
/***/ },
/* 1 */
/***/ function(module, exports) {
eval("// removed by extract-text-webpack-plugin\n\n//////////////////\n// WEBPACK FOOTER\n// ./main.css\n// module id = 1\n// module chunks = 0\n//# sourceURL=webpack:///./main.css?");
/***/ },
/* 2 */,
/* 3 */,
/* 4 */,
/* 5 */
/***/ function(module, exports) {
eval("// This file is used for frontend and backend\n'use strict';\n\n// If compiled by the html-webpack-plugin\n// HTML_WEBPACK_PLUGIN is set to true:\nvar backend = typeof HTML_WEBPACK_PLUGIN !== 'undefined';\n\nmodule.exports = function () {\n return 'Hello World from ' + (backend ? 'backend' : 'frontend');\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./universial.js\n// module id = 5\n// module chunks = 0\n//# sourceURL=webpack:///./universial.js?");
eval("// This file is used for frontend and backend\n'use strict';\n\n// If compiled by the html-webpack-plugin\n// HTML_WEBPACK_PLUGIN is set to true:\nvar backend = typeof HTML_WEBPACK_PLUGIN !== 'undefined';\n\nmodule.exports = function () {\n return 'Hello World from ' + (backend ? 'backend' : 'frontend');\n};\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./universial.js\n// module id = 1\n// module chunks = 0\n//# sourceURL=webpack:///./universial.js?");
/***/ }
/******/ ]);

View File

@ -1,2 +1,2 @@
<html><head><title>Webpack App</title><link href="styles.css" rel="stylesheet"></head><body>Hello World from backend - <h2>Partial</h2>
<html><head><title>/index.js: Webpack App</title></head><body>Hello World from backend - <h2>Partial</h2>
<img src="0714810ae3fb211173e2964249507195.png"><script type="text/javascript" src="bundle.js"></script></body></html>

View File

@ -1,3 +0,0 @@
body {
background: snow;
}

View File

@ -45,6 +45,15 @@
/******/ });
/******/ };
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };

View File

@ -1,2 +1,2 @@
<html><head><title>Webpack App</title><link href="styles.css" rel="stylesheet"></head><body>Hello World from backend - <h2>Partial</h2>
<html><head><title>template.js: Webpack App</title><link href="styles.css" rel="stylesheet"></head><body>Hello World from backend - <h2>Partial</h2>
<img src="0714810ae3fb211173e2964249507195.png"><script type="text/javascript" src="bundle.js"></script></body></html>

View File

@ -5,8 +5,9 @@ var universal = require('./universial.js');
// Export a function / promise / or a string:
// This function has to return a string or promised string:
module.exports = function (templateParams) {
var filename = __filename;
var html = '<html><head>' +
'<title>' + templateParams.htmlWebpackPlugin.options.title + '</title>' +
'<title>' + filename + ': ' + templateParams.htmlWebpackPlugin.options.title + '</title>' +
'</head><body>' + universal() + ' - ' + partial + '</body></html>';
return html;

View File

@ -11,7 +11,7 @@ module.exports = {
},
module: {
loaders: [
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
{ test: /\.css$/, loader: ExtractTextPlugin.extract({loader: 'css-loader'}) },
{ test: /\.png$/, loader: 'file-loader' },
{ test: /\.html$/, loader: 'html-loader' }
]

View File

@ -1,2 +1,2 @@
<head><link href="styles.css" rel="stylesheet"></head>Hello World from backend2016-10-29T07:02:05.646Z<h2>Partial</h2>
<head><link href="styles.css" rel="stylesheet"></head>Hello World from backend2016-10-29T07:11:51.268Z<h2>Partial</h2>
<img src="0714810ae3fb211173e2964249507195.png"><script type="text/javascript" src="bundle.js"></script>

View File

@ -53,51 +53,41 @@ module.exports.compileTemplate = function compileTemplate (template, context, ou
new LoaderTargetPlugin('node')
);
// 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
childCompiler.plugin('compilation', function (compilation) {
if (compilation.cache) {
if (!compilation.cache[compilerName]) {
compilation.cache[compilerName] = {};
}
compilation.cache = compilation.cache[compilerName];
}
initializeChildCompilerCache(childCompiler);
// Allow full access to __filename and __dirname for the template compilation
childCompilerNodeSettings({
__filename: true,
__dirname: true
});
// Compile and return a promise
return new Promise(function (resolve, reject) {
childCompiler.runAsChild(function (err, entries, childCompilation) {
// 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 {
// Replace [hash] placeholders in filename
var outputName = compilation.mainTemplate.applyPluginsWaterfall('asset-path', outputOptions.filename, {
hash: childCompilation.hash,
chunk: entries[0]
});
// Restore the parent compilation to the state like it
// was before the child compilation
compilation.assets[outputName] = assetsBeforeCompilation[outputName];
if (assetsBeforeCompilation[outputName] === undefined) {
// If it wasn't there - delete it
delete compilation.assets[outputName];
}
resolve({
// Hash of the template entry point
hash: entries[0].hash,
// Output name
outputName: outputName,
// Compiled code
content: childCompilation.assets[outputName].source()
});
childCompiler.runAsChild(function onCompilationComplete(err, entries, childCompilation) {
err = normalizeCompilationErrors(err, childCompilation);
if (err)
return reject(err);
}
// Replace [hash] placeholders in filename
var outputName = compilation.mainTemplate.applyPluginsWaterfall('asset-path', outputOptions.filename, {
hash: childCompilation.hash,
chunk: entries[0]
});
// Restore the parent compilation to the state like it
// was before the child compilation
compilation.assets[outputName] = assetsBeforeCompilation[outputName];
if (assetsBeforeCompilation[outputName] === undefined) {
// If it wasn't there - delete it
delete compilation.assets[outputName];
}
resolve({
// Hash of the template entry point
hash: entries[0].hash,
// Output name
outputName: outputName,
// Compiled code
content: childCompilation.assets[outputName].source()
});
});
});
};
@ -110,3 +100,47 @@ function getCompilerName (context, filename) {
var relativePath = path.relative(context, absolutePath);
return 'html-webpack-plugin for "' + (absolutePath.length < relativePath.length ? absolutePath : relativePath) + '"';
}
/**
* Fix for "Uncaught TypeError: __webpack_require__(...) is not a function"
* Hot module replacement requires that every child compiler has its own
* @see https://github.com/ampedandwired/html-webpack-plugin/pull/179
*/
function initializeChildCompilerCache(childCompiler) {
childCompiler.plugin('compilation', function (compilation) {
if (compilation.cache) {
if (!compilation.cache[compilerName]) {
compilation.cache[compilerName] = {};
}
compilation.cache = compilation.cache[compilerName];
}
});
}
/**
* Configure the parser
* This is a workaround as NodeStuffPlugin can't be use in a child compiler
* @see https://github.com/webpack/webpack/issues/2978
*/
function setupChildCompilerNodeStuff(childCompiler, nodeStuffPluginOptions) {
childCompiler.plugin('normal-module-factory', function (normalModuleFactory) {
normalModuleFactory.plugin('parser-options', function (parserOptions) {
parserOptions.node = _.merge(parserOptions.node || {}, nodeStuffPluginOptions);
return parserOptions;
});
});
}
/**
* Returns all compilation errors in one error
*/
function normalizeCompilationErrors(compilationErrorObject, compilation) {
// Gather internal errors
if (childCompilation && childCompilation.errors && childCompilation.errors.length) {
var errorDetails = childCompilation.errors.map(function (error) {
return error.message + (error.error ? ':\n' + error.error : '');
}).join('\n');
return new Error(errorDetails);
}
return compilationErrorObject;
}

View File

@ -1,3 +1,7 @@
module.exports = function (templateParams) {
return 'templateParams.compilation exists: ' + !!templateParams.compilation;
};
return {
compilation: typeof templateParams.compilation,
dirname: __dirname,
filename: __filename
};
};