html-webpack-plugin
Advanced tools
Comparing version 1.1.0 to 1.2.0
108
index.js
@@ -0,3 +1,5 @@ | ||
'use strict'; | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var _ = require('lodash'); | ||
var tmpl = require('blueimp-tmpl').tmpl; | ||
@@ -11,9 +13,11 @@ | ||
var self = this; | ||
compiler.plugin('emit', function(compiler, callback) { | ||
var webpackStatsJson = compiler.getStats().toJson(); | ||
compiler.plugin('emit', function(compilation, callback) { | ||
var webpackStatsJson = compilation.getStats().toJson(); | ||
var templateParams = {}; | ||
templateParams.webpack = webpackStatsJson; | ||
templateParams.htmlWebpackPlugin = {}; | ||
templateParams.htmlWebpackPlugin.assets = self.htmlWebpackPluginAssets(compiler, webpackStatsJson); | ||
templateParams.htmlWebpackPlugin.assets = self.htmlWebpackPluginLegacyAssets(compilation, webpackStatsJson); | ||
templateParams.htmlWebpackPlugin.files = self.htmlWebpackPluginAssets(compilation, webpackStatsJson, self.options.hash); | ||
templateParams.htmlWebpackPlugin.options = self.options; | ||
templateParams.webpackConfig = compilation.options; | ||
@@ -23,6 +27,7 @@ var outputFilename = self.options.filename || 'index.html'; | ||
if (self.options.templateContent && self.options.template) { | ||
compiler.errors.push(new Error('HtmlWebpackPlugin: cannot specify both template and templateContent options')); | ||
compilation.errors.push(new Error('HtmlWebpackPlugin: cannot specify both template and templateContent options')); | ||
callback(); | ||
} else if (self.options.templateContent) { | ||
self.emitHtml(compiler, self.options.templateContent, templateParams, outputFilename); | ||
var templateContent = typeof self.options.templateContent === 'function' ? self.options.templateContent(templateParams, compiler) : self.options.templateContent; | ||
self.emitHtml(compilation, templateContent, templateParams, outputFilename); | ||
callback(); | ||
@@ -34,8 +39,9 @@ } else { | ||
} | ||
compilation.fileDependencies.push(templateFile); | ||
fs.readFile(templateFile, 'utf8', function(err, htmlTemplateContent) { | ||
if (err) { | ||
compiler.errors.push(new Error('HtmlWebpackPlugin: Unable to read HTML template "' + templateFile + '"')); | ||
compilation.errors.push(new Error('HtmlWebpackPlugin: Unable to read HTML template "' + templateFile + '"')); | ||
} else { | ||
self.emitHtml(compiler, htmlTemplateContent, templateParams, outputFilename); | ||
self.emitHtml(compilation, htmlTemplateContent, templateParams, outputFilename); | ||
} | ||
@@ -48,5 +54,10 @@ callback(); | ||
HtmlWebpackPlugin.prototype.emitHtml = function(compiler, htmlTemplateContent, templateParams, outputFilename) { | ||
var html = tmpl(htmlTemplateContent, templateParams); | ||
compiler.assets[outputFilename] = { | ||
HtmlWebpackPlugin.prototype.emitHtml = function(compilation, htmlTemplateContent, templateParams, outputFilename) { | ||
var html; | ||
try { | ||
html = tmpl(htmlTemplateContent, templateParams); | ||
} catch(e) { | ||
compilation.errors.push(new Error('HtmlWebpackPlugin: template error ' + e)); | ||
} | ||
compilation.assets[outputFilename] = { | ||
source: function() { | ||
@@ -61,22 +72,75 @@ return html; | ||
HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compiler, webpackStatsJson) { | ||
var assets = {}; | ||
for (var chunk in webpackStatsJson.assetsByChunkName) { | ||
var chunkValue = webpackStatsJson.assetsByChunkName[chunk]; | ||
// Webpack outputs an array for each chunk when using sourcemaps | ||
if (chunkValue instanceof Array) { | ||
// Is the main bundle always the first element? | ||
chunkValue = chunkValue[0]; | ||
HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webpackStatsJson, appendHash) { | ||
var publicPath = compilation.options.output.publicPath || ''; | ||
var queryString = appendHash ? '?' + webpackStatsJson.hash : ''; | ||
var assets = { | ||
// Will contain all js & css files by chunk | ||
chunks: {}, | ||
// Will contain all js files | ||
js: [], | ||
// Will contain all css files | ||
css: [], | ||
// Will contain the html5 appcache manifest files if it exists | ||
manifest: Object.keys(compilation.assets).filter(function(assetFile){ | ||
return path.extname(assetFile) === '.appcache'; | ||
}).map(function(assetFile) { | ||
return assetFile + queryString; | ||
})[0] | ||
}; | ||
var chunks = webpackStatsJson.chunks.sort(function orderEntryLast(a, b) { | ||
if (a.entry !== b.entry) { | ||
return b.entry ? 1 : -1; | ||
} else { | ||
return b.id - a.id; | ||
} | ||
}); | ||
if (compiler.options.output.publicPath) { | ||
chunkValue = compiler.options.output.publicPath + chunkValue; | ||
} | ||
assets[chunk] = chunkValue; | ||
for (var i = 0; i < chunks.length; i++) { | ||
var chunk = chunks[i]; | ||
var chunkName = chunk.names[0]; | ||
assets.chunks[chunkName] = {}; | ||
// Prepend the public path to all chunk files | ||
var chunkFiles = [].concat(chunk.files).map(function(chunkFile) { | ||
return publicPath + chunkFile + queryString; | ||
}); | ||
// Webpack outputs an array for each chunk when using sourcemaps | ||
// But we need only the entry file | ||
var entry = chunkFiles[0]; | ||
assets.chunks[chunkName].entry = entry; | ||
assets.js.push(entry); | ||
// Gather all css files | ||
var css = chunkFiles.filter(function(chunkFile){ | ||
return path.extname(chunkFile) === '.css'; | ||
}); | ||
assets.chunks[chunkName].css = css; | ||
assets.css = assets.css.concat(css); | ||
} | ||
// Duplicate css assets can occur on occasion if more than one chunk | ||
// requires the same css. | ||
assets.css = _.uniq(assets.css); | ||
return assets; | ||
}; | ||
/** | ||
* A helper to support the templates written for html-webpack-plugin <= 1.1.0 | ||
*/ | ||
HtmlWebpackPlugin.prototype.htmlWebpackPluginLegacyAssets = function(compilation, webpackStatsJson) { | ||
var assets = this.htmlWebpackPluginAssets(compilation, webpackStatsJson); | ||
var legacyAssets = {}; | ||
Object.keys(assets.chunks).forEach(function(chunkName){ | ||
legacyAssets[chunkName] = assets.chunks[chunkName].entry; | ||
}); | ||
return legacyAssets; | ||
}; | ||
module.exports = HtmlWebpackPlugin; |
{ | ||
"name": "html-webpack-plugin", | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"description": "Simplifies creation of HTML files to serve your webpack bundles", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "node_modules/.bin/jshint *.js spec && node_modules/.bin/jasmine-node --captureExceptions spec" | ||
"test": "jshint -c .jshintrc *.js spec && jasmine-node --captureExceptions spec" | ||
}, | ||
@@ -32,4 +32,5 @@ "repository": { | ||
"dependencies": { | ||
"blueimp-tmpl": "~2.5.4" | ||
"blueimp-tmpl": "~2.5.4", | ||
"lodash": "~3.6.0" | ||
} | ||
} |
@@ -41,3 +41,3 @@ HTML Webpack Plugin | ||
<head> | ||
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/> | ||
<meta charset="UTF-8"> | ||
<title>Webpack App</title> | ||
@@ -54,3 +54,7 @@ </head> | ||
If you have any css assets in webpack's output (for example, css extracted | ||
with the [ExtractTextPlugin](https://github.com/webpack/extract-text-webpack-plugin)) | ||
then these will be included with `<link>` tags in the HTML head. | ||
Configuration | ||
@@ -64,2 +68,4 @@ ------------- | ||
You can specify a subdirectory here too (eg: `assets/admin.html`). | ||
- `hash`: if `true` then append a unique webpack compilation hash to all | ||
included scripts and css files. This is useful for cache busting. | ||
@@ -72,3 +78,4 @@ Here's an example webpack config illustrating how to use these options: | ||
path: 'dist', | ||
filename: 'index_bundle.js' | ||
filename: 'index_bundle.js', | ||
hash: true | ||
}, | ||
@@ -120,6 +127,6 @@ plugins: [ | ||
<title>My App</title> | ||
<script src="{%=o.htmlWebpackPlugin.assets.head%}"></script> | ||
<script src="{%=o.htmlWebpackPlugin.files.chunks.head.entry%}"></script> | ||
</head> | ||
<body> | ||
<script src="{%=o.htmlWebpackPlugin.assets.main%}"></script> | ||
<script src="{%=o.htmlWebpackPlugin.files.chunks.main.entry%}"></script> | ||
</body> | ||
@@ -155,2 +162,13 @@ </html> | ||
The `templateContent` option can also be a function: | ||
```javascript | ||
plugins: [ | ||
new HtmlWebpackPlugin({ | ||
templateContent: function(templateParams, webpackCompiler) { | ||
// Return your template content synchronously here | ||
} | ||
}) | ||
] | ||
``` | ||
Note the plugin will throw an error if you specify both `template` _and_ | ||
@@ -162,3 +180,3 @@ `templateContent`. | ||
- `htmlWebpackPlugin`: data specific to this plugin | ||
- `htmlWebpackPlugin.assets`: a massaged representation of the | ||
- `htmlWebpackPlugin.files`: a massaged representation of the | ||
`assetsByChunkName` attribute of webpack's [stats](https://github.com/webpack/docs/wiki/node.js-api#stats) | ||
@@ -168,5 +186,15 @@ object. It contains a mapping from entry point name to the bundle filename, eg: | ||
"htmlWebpackPlugin": { | ||
"assets": { | ||
"head": "assets/head_bundle.js", | ||
"main": "assets/main_bundle.js" | ||
"files": { | ||
"css": [ "main.css" ], | ||
"js": [ "assets/head_bundle.js", "assets/main_bundle.js"], | ||
"chunks": { | ||
"head": { | ||
"entry": "assets/head_bundle.js", | ||
"css": [ "main.css" ] | ||
}, | ||
"main": { | ||
"entry": "assets/main_bundle.js", | ||
"css": [] | ||
}, | ||
} | ||
} | ||
@@ -186,1 +214,4 @@ } | ||
after the wepback run is complete. | ||
- `webpackConfig`: the webpack configuration that was used for this compilation. This | ||
can be used, for example, to get the `publicPath` (`webpackConfig.output.publicPath`). |
@@ -0,1 +1,2 @@ | ||
require('./common'); | ||
document.body.innerHTML = document.body.innerHTML + "<p>index.js</p>"; |
@@ -0,1 +1,2 @@ | ||
require('./common'); | ||
document.body.innerHTML = document.body.innerHTML + "<p>util.js</p>"; |
@@ -0,1 +1,2 @@ | ||
'use strict'; | ||
var path = require('path'); | ||
@@ -5,2 +6,3 @@ var fs = require('fs'); | ||
var rm_rf = require('rimraf'); | ||
var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin"); | ||
var HtmlWebpackPlugin = require('../index.js'); | ||
@@ -21,3 +23,3 @@ | ||
} else { | ||
expect(htmlContent).toContain(expectedResult); | ||
expect(htmlContent).toContain(expectedResult.replace('%hash%', stats.hash)); | ||
} | ||
@@ -71,3 +73,3 @@ } | ||
}, | ||
['<script src="app_bundle.js"', 'Some unique text'], null, done); | ||
['<script src="app_bundle.js', 'Some unique text'], null, done); | ||
}); | ||
@@ -86,2 +88,46 @@ | ||
}, | ||
['<script src="app_bundle.js'], null, done); | ||
}); | ||
it('allows you to use the deprecated assets object', function (done) { | ||
testHtmlPlugin({ | ||
entry: { | ||
app: path.join(__dirname, 'fixtures/index.js') | ||
}, | ||
output: { | ||
path: OUTPUT_DIR, | ||
filename: '[name]_bundle.js' | ||
}, | ||
plugins: [new HtmlWebpackPlugin({template: path.join(__dirname, 'fixtures/legacy.html')})] | ||
}, | ||
['<script src="app_bundle.js', 'Some unique text'], null, done); | ||
}); | ||
it('allows you to use the deprecated default_index file', function (done) { | ||
testHtmlPlugin({ | ||
entry: { | ||
app: path.join(__dirname, 'fixtures/index.js') | ||
}, | ||
output: { | ||
path: OUTPUT_DIR, | ||
filename: '[name]_bundle.js' | ||
}, | ||
plugins: [new HtmlWebpackPlugin({template: path.join(__dirname, 'fixtures/legacy_default_index.html')})] | ||
}, | ||
['<script src="app_bundle.js'], null, done); | ||
}); | ||
it('allows you to specify your own HTML template function', function(done) { | ||
testHtmlPlugin({ | ||
entry: {app: path.join(__dirname, 'fixtures/index.js')}, | ||
output: { | ||
path: OUTPUT_DIR, | ||
filename: 'app_bundle.js' | ||
}, | ||
plugins: [new HtmlWebpackPlugin({ | ||
templateContent: function() { | ||
return fs.readFileSync(path.join(__dirname, 'fixtures/test.html'), 'utf8'); | ||
} | ||
})] | ||
}, | ||
['<script src="app_bundle.js"'], null, done); | ||
@@ -128,5 +174,16 @@ }); | ||
plugins: [new HtmlWebpackPlugin()] | ||
}, [/<script src="index_bundle_[0-9a-f]+\.js"/], null, done); | ||
}, [/<script src="index_bundle_[0-9a-f]+\.js/], null, done); | ||
}); | ||
it('allows to append hashes to the assets', function(done) { | ||
testHtmlPlugin({ | ||
entry: path.join(__dirname, 'fixtures/index.js'), | ||
output: { | ||
path: OUTPUT_DIR, | ||
filename: 'index_bundle.js' | ||
}, | ||
plugins: [new HtmlWebpackPlugin({hash: true})] | ||
}, ['<script src="index_bundle.js?%hash%"'], null, done); | ||
}); | ||
it('prepends the webpack public path to script src', function(done) { | ||
@@ -202,3 +259,5 @@ testHtmlPlugin({ | ||
testHtmlPlugin({ | ||
entry: path.join(__dirname, 'fixtures/index.js'), | ||
entry: { | ||
app: path.join(__dirname, 'fixtures/index.js') | ||
}, | ||
output: { | ||
@@ -235,2 +294,41 @@ path: OUTPUT_DIR, | ||
it('exposes the webpack configuration to templates', function(done) { | ||
testHtmlPlugin({ | ||
entry: { | ||
app: path.join(__dirname, 'fixtures/index.js') | ||
}, | ||
output: { | ||
path: OUTPUT_DIR, | ||
publicPath: 'https://cdn.com', | ||
filename: '[name]_bundle.js' | ||
}, | ||
plugins: [new HtmlWebpackPlugin({template: path.join(__dirname, 'fixtures/webpackconfig.html')})] | ||
}, | ||
['Public path is https://cdn.com'], null, done); | ||
}); | ||
it('works with commons chunk plugin', function(done) { | ||
testHtmlPlugin({ | ||
debug: true, | ||
verbose: true, | ||
entry: { | ||
util: path.join(__dirname, 'fixtures/util.js'), | ||
index: path.join(__dirname, 'fixtures/index.js') | ||
}, | ||
output: { | ||
path: OUTPUT_DIR, | ||
filename: '[name]_bundle.js' | ||
}, | ||
plugins: [ | ||
new CommonsChunkPlugin({ | ||
name: 'common', | ||
filename: "common_bundle.js", | ||
}), | ||
new HtmlWebpackPlugin() | ||
] | ||
}, [ | ||
/<script src="common_bundle.js">[\s\S]*<script src="util_bundle.js">/, | ||
/<script src="common_bundle.js"[\s\S]*<script src="index_bundle.js">/], null, done); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
32685
16
426
209
2
+ Addedlodash@~3.6.0
+ Addedlodash@3.6.0(transitive)