From 2ea554518a6eef0e6b81adf2727aee79dfcf6826 Mon Sep 17 00:00:00 2001 From: Jan Nicklas Date: Sat, 29 Oct 2016 08:47:05 +0200 Subject: [PATCH] WIP - Allow to use __dirname and __filename in template files (webpack 2 only) --- .../dist/webpack-1/bundle.js | 13 +- .../dist/webpack-1/index.html | 2 +- .../dist/webpack-1/styles.css | 3 - .../dist/webpack-2/bundle.js | 9 ++ .../dist/webpack-2/index.html | 2 +- examples/javascript-advanced/template.js | 3 +- .../javascript-advanced/webpack.config.js | 2 +- examples/javascript/dist/webpack-1/index.html | 2 +- lib/compiler.js | 114 ++++++++++++------ spec/fixtures/templateParam.js | 8 +- 10 files changed, 97 insertions(+), 61 deletions(-) delete mode 100644 examples/javascript-advanced/dist/webpack-1/styles.css diff --git a/examples/javascript-advanced/dist/webpack-1/bundle.js b/examples/javascript-advanced/dist/webpack-1/bundle.js index 8a83022..1892252 100644 --- a/examples/javascript-advanced/dist/webpack-1/bundle.js +++ b/examples/javascript-advanced/dist/webpack-1/bundle.js @@ -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?"); /***/ } /******/ ]); \ No newline at end of file diff --git a/examples/javascript-advanced/dist/webpack-1/index.html b/examples/javascript-advanced/dist/webpack-1/index.html index 61d6408..f5e9ebf 100644 --- a/examples/javascript-advanced/dist/webpack-1/index.html +++ b/examples/javascript-advanced/dist/webpack-1/index.html @@ -1,2 +1,2 @@ -Webpack AppHello World from backend -

Partial

+/index.js: Webpack AppHello World from backend -

Partial

\ No newline at end of file diff --git a/examples/javascript-advanced/dist/webpack-1/styles.css b/examples/javascript-advanced/dist/webpack-1/styles.css deleted file mode 100644 index 232a2cd..0000000 --- a/examples/javascript-advanced/dist/webpack-1/styles.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: snow; -} \ No newline at end of file diff --git a/examples/javascript-advanced/dist/webpack-2/bundle.js b/examples/javascript-advanced/dist/webpack-2/bundle.js index 902bd24..3415fae 100644 --- a/examples/javascript-advanced/dist/webpack-2/bundle.js +++ b/examples/javascript-advanced/dist/webpack-2/bundle.js @@ -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); }; diff --git a/examples/javascript-advanced/dist/webpack-2/index.html b/examples/javascript-advanced/dist/webpack-2/index.html index 61d6408..0c4ada0 100644 --- a/examples/javascript-advanced/dist/webpack-2/index.html +++ b/examples/javascript-advanced/dist/webpack-2/index.html @@ -1,2 +1,2 @@ -Webpack AppHello World from backend -

Partial

+template.js: Webpack AppHello World from backend -

Partial

\ No newline at end of file diff --git a/examples/javascript-advanced/template.js b/examples/javascript-advanced/template.js index bd0f705..5b3d951 100644 --- a/examples/javascript-advanced/template.js +++ b/examples/javascript-advanced/template.js @@ -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 = '' + - '' + templateParams.htmlWebpackPlugin.options.title + '' + + '' + filename + ': ' + templateParams.htmlWebpackPlugin.options.title + '' + '' + universal() + ' - ' + partial + ''; return html; diff --git a/examples/javascript-advanced/webpack.config.js b/examples/javascript-advanced/webpack.config.js index 965697b..281d8f0 100644 --- a/examples/javascript-advanced/webpack.config.js +++ b/examples/javascript-advanced/webpack.config.js @@ -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' } ] diff --git a/examples/javascript/dist/webpack-1/index.html b/examples/javascript/dist/webpack-1/index.html index 0ab3bbd..39b2b8a 100644 --- a/examples/javascript/dist/webpack-1/index.html +++ b/examples/javascript/dist/webpack-1/index.html @@ -1,2 +1,2 @@ -Hello World from backend2016-10-29T07:02:05.646Z

Partial

+Hello World from backend2016-10-29T07:11:51.268Z

Partial

\ No newline at end of file diff --git a/lib/compiler.js b/lib/compiler.js index 9c8a224..756a94a 100644 --- a/lib/compiler.js +++ b/lib/compiler.js @@ -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; +} diff --git a/spec/fixtures/templateParam.js b/spec/fixtures/templateParam.js index 5574186..2f957ee 100644 --- a/spec/fixtures/templateParam.js +++ b/spec/fixtures/templateParam.js @@ -1,3 +1,7 @@ module.exports = function (templateParams) { - return 'templateParams.compilation exists: ' + !!templateParams.compilation; -}; + return { + compilation: typeof templateParams.compilation, + dirname: __dirname, + filename: __filename + }; +}; \ No newline at end of file