Add `__entry` and `__entryPath` to the global template variables

This commit is contained in:
Jan Nicklas 2016-09-09 15:05:38 +02:00
parent 263b5b6bde
commit 7e1af7b89c
5 changed files with 87 additions and 27 deletions

View File

@ -204,6 +204,14 @@ HtmlWebpackPlugin.prototype.apply = function (compiler) {
});
};
/**
* Resolves a request to a real file path
*/
HtmlWebpackPlugin.prototype.getResolvedFilename = function (request, compiler) {
var requestWithoutLoaders = this.options.template.replace(/^.+!/, '').replace(/\?.+$/, '');
return Promise.promisify(compiler.resolvers.normal.resolve)(compiler.context, requestWithoutLoaders);
};
/**
* Evaluates the child compilation result
* Returns a promise
@ -212,23 +220,32 @@ HtmlWebpackPlugin.prototype.evaluateCompilationResult = function (compilation, s
if (!source) {
return Promise.reject('The child compilation didn\'t provide a result');
}
return this.getResolvedFilename(this.options.template, compilation.compiler)
.then(function (templatePath) {
// The LibraryTemplatePlugin stores the template result in a local variable.
// To extract the result during the evaluation this part has to be removed.
source = source.replace('var HTML_WEBPACK_PLUGIN_RESULT =', '');
// The LibraryTemplatePlugin stores the template result in a local variable.
// To extract the result during the evaluation this part has to be removed.
source = source.replace('var HTML_WEBPACK_PLUGIN_RESULT =', '');
var template = this.options.template.replace(/^.+!/, '').replace(/\?.+$/, '');
var vmContext = vm.createContext(_.extend({HTML_WEBPACK_PLUGIN: true, require: require}, global));
var vmScript = new vm.Script(source, {filename: template});
// Evaluate code and cast to string
var newSource;
try {
newSource = vmScript.runInContext(vmContext);
} catch (e) {
return Promise.reject(e);
}
return typeof newSource === 'string' || typeof newSource === 'function'
? Promise.resolve(newSource)
: Promise.reject('The loader "' + this.options.template + '" didn\'t return html.');
var vmContext = vm.createContext(_.extend({
HTML_WEBPACK_PLUGIN: true,
require: require,
__entry: templatePath,
__entryPath: path.dirname(templatePath)
}, global));
var vmScript = new vm.Script(source, {filename: path.basename(templatePath)});
// Evaluate code and cast to string
var newSource;
try {
newSource = vmScript.runInContext(vmContext);
} catch (templateEvaluationError) {
return Promise.reject(templateEvaluationError);
}
// Verify that the template result is a template function or a template string
return typeof newSource === 'string' || typeof newSource === 'function'
? Promise.resolve(newSource)
: Promise.reject('The loader "' + this.options.template + '" didn\'t return html.');
});
};
/**

View File

@ -13,6 +13,7 @@ var NodeTargetPlugin = require('webpack/lib/node/NodeTargetPlugin');
var LoaderTargetPlugin = require('webpack/lib/LoaderTargetPlugin');
var LibraryTemplatePlugin = require('webpack/lib/LibraryTemplatePlugin');
var SingleEntryPlugin = require('webpack/lib/SingleEntryPlugin');
var NodeStuffPlugin = require('webpack/lib/NodeStuffPlugin');
/**
* Compiles the template into a nodejs factory, adds its to the compilation.assets
@ -46,11 +47,15 @@ module.exports.compileTemplate = function compileTemplate (template, context, ou
var childCompiler = compilation.createChildCompiler(compilerName, outputOptions);
childCompiler.context = context;
childCompiler.apply(
new NodeTemplatePlugin(outputOptions),
new NodeTargetPlugin(),
new LibraryTemplatePlugin('HTML_WEBPACK_PLUGIN_RESULT', 'var'),
new SingleEntryPlugin(this.context, template),
new LoaderTargetPlugin('node')
new NodeTemplatePlugin(outputOptions),
new NodeTargetPlugin(),
new LoaderTargetPlugin('node'),
new NodeStuffPlugin({
__dirname: false,
__filename: false
})
);
// Fix for "Uncaught TypeError: __webpack_require__(...) is not a function"

View File

@ -12,7 +12,7 @@
"prepublish": "npm run test",
"pretest": "semistandard",
"build-examples": "node examples/build-examples.js",
"test": "jasmine"
"test": "jasmine --verbose --captureExceptions"
},
"repository": {
"type": "git",
@ -37,28 +37,29 @@
},
"devDependencies": {
"appcache-webpack-plugin": "^1.3.0",
"css-loader": "^0.23.1",
"dir-compare": "1.0.1",
"css-loader": "^0.25.0",
"dir-compare": "1.1.0",
"es6-promise": "^3.2.1",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.9.0",
"html-loader": "^0.4.3",
"jade": "^1.11.0",
"jade-loader": "^0.8.0",
"jasmine": "^2.4.1",
"jasmine": "^2.5.1",
"jasmine-console-reporter": "^1.2.7",
"rimraf": "^2.5.4",
"semistandard": "^8.0.0",
"style-loader": "^0.13.1",
"underscore-template-loader": "^0.7.3",
"url-loader": "^0.5.7",
"webpack": "^1.13.1",
"webpack": "^1.13.2",
"webpack-recompilation-simulator": "^1.3.0"
},
"dependencies": {
"bluebird": "^3.4.1",
"bluebird": "^3.4.6",
"html-minifier": "^3.0.2",
"loader-utils": "^0.2.15",
"lodash": "^4.14.2",
"lodash": "^4.15.0",
"pretty-error": "^2.0.0",
"toposort": "^1.0.0"
},

View File

@ -21,6 +21,14 @@ var HtmlWebpackPlugin = require('../index.js');
var OUTPUT_DIR = path.join(__dirname, '../dist');
jasmine.getEnv().defaultTimeoutInterval = 30000;
var JasmineConsoleReporter = require('jasmine-console-reporter');
jasmine.getEnv().addReporter(new JasmineConsoleReporter({
colors: 1,
cleanStack: 1,
verbosity: 4,
listStyle: 'indent',
activity: false
}));
function testHtmlPlugin (webpackConfig, expectedResults, outputFile, done, expectErrors, expectWarnings) {
outputFile = outputFile || 'index.html';
@ -1114,7 +1122,7 @@ describe('HtmlWebpackPlugin', function () {
template: path.join(__dirname, 'fixtures/non-existing-template.html')
})
]
}, ['Child compilation failed:\n Entry module not found:'], null, done, true);
}, ['Error: Cannot resolve'], null, done, true);
});
it('should sort the chunks in auto mode', function (done) {
@ -1240,6 +1248,28 @@ describe('HtmlWebpackPlugin', function () {
}, ['templateParams.compilation exists: true'], null, done);
});
it('should provide globals to the template compilation', function (done) {
var template = path.resolve(__dirname, 'fixtures/templateGlobals.js');
var templatePath = path.dirname(template);
testHtmlPlugin({
entry: path.join(__dirname, 'fixtures/index.js'),
output: {
path: OUTPUT_DIR,
filename: 'index_bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
template: template,
inject: false
})
]
}, [
'"__entry":"' + template + '"',
'"__entryPath":"' + templatePath + '"',
'"HTML_WEBPACK_PLUGIN":true'
], null, done);
});
it('should not treat templateContent set to an empty string as missing', function (done) {
testHtmlPlugin({
entry: {app: path.join(__dirname, 'fixtures/index.js')},

7
spec/fixtures/templateGlobals.js vendored Normal file
View File

@ -0,0 +1,7 @@
module.exports = function (templateParams) {
return JSON.stringify({
__entry: global.__entry,
__entryPath: global.__entryPath,
HTML_WEBPACK_PLUGIN: global.HTML_WEBPACK_PLUGIN
});
};