html-webpack-plugin
Advanced tools
Comparing version 1.2.0 to 1.3.0
95
index.js
@@ -19,3 +19,3 @@ 'use strict'; | ||
templateParams.htmlWebpackPlugin.assets = self.htmlWebpackPluginLegacyAssets(compilation, webpackStatsJson); | ||
templateParams.htmlWebpackPlugin.files = self.htmlWebpackPluginAssets(compilation, webpackStatsJson, self.options.hash); | ||
templateParams.htmlWebpackPlugin.files = self.htmlWebpackPluginAssets(compilation, webpackStatsJson, self.options.chunks, self.options.excludeChunks); | ||
templateParams.htmlWebpackPlugin.options = self.options; | ||
@@ -36,3 +36,4 @@ templateParams.webpackConfig = compilation.options; | ||
if (!templateFile) { | ||
templateFile = path.join(__dirname, 'default_index.html'); | ||
// Use a special index file to prevent double script / style injection if the `inject` option is truthy | ||
templateFile = path.join(__dirname, self.options.inject ? 'default_inject_index.html' : 'default_index.html'); | ||
} | ||
@@ -60,2 +61,6 @@ compilation.fileDependencies.push(templateFile); | ||
} | ||
// Inject link and script elements into an existing html file | ||
if (this.options.inject) { | ||
html = this.injectAssetsIntoHtml(html, templateParams); | ||
} | ||
compilation.assets[outputFilename] = { | ||
@@ -72,5 +77,5 @@ source: function() { | ||
HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webpackStatsJson, appendHash) { | ||
HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webpackStatsJson, includedChunks, excludedChunks) { | ||
var self = this; | ||
var publicPath = compilation.options.output.publicPath || ''; | ||
var queryString = appendHash ? '?' + webpackStatsJson.hash : ''; | ||
@@ -87,7 +92,10 @@ var assets = { | ||
return path.extname(assetFile) === '.appcache'; | ||
}).map(function(assetFile) { | ||
return assetFile + queryString; | ||
})[0] | ||
}; | ||
// Append a hash for cache busting | ||
if (this.options.hash) { | ||
assets.manifest = self.appendHash(assets.manifest, webpackStatsJson.hash); | ||
} | ||
var chunks = webpackStatsJson.chunks.sort(function orderEntryLast(a, b) { | ||
@@ -104,2 +112,12 @@ if (a.entry !== b.entry) { | ||
var chunkName = chunk.names[0]; | ||
// Skip if the chunks should be filtered and the given chunk was not added explicity | ||
if (Array.isArray(includedChunks) && includedChunks.indexOf(chunkName) === -1) { | ||
continue; | ||
} | ||
// Skip if the chunks should be filtered and the given chunk was excluded explicity | ||
if (Array.isArray(excludedChunks) && excludedChunks.indexOf(chunkName) !== -1) { | ||
continue; | ||
} | ||
assets.chunks[chunkName] = {}; | ||
@@ -109,5 +127,12 @@ | ||
var chunkFiles = [].concat(chunk.files).map(function(chunkFile) { | ||
return publicPath + chunkFile + queryString; | ||
return publicPath + chunkFile; | ||
}); | ||
// Append a hash for cache busting | ||
if (this.options.hash) { | ||
chunkFiles = chunkFiles.map(function(chunkFile) { | ||
return self.appendHash(chunkFile, webpackStatsJson.hash); | ||
}); | ||
} | ||
// Webpack outputs an array for each chunk when using sourcemaps | ||
@@ -121,3 +146,5 @@ // But we need only the entry file | ||
var css = chunkFiles.filter(function(chunkFile){ | ||
return path.extname(chunkFile) === '.css'; | ||
// Some chunks may contain content hash in their names, for ex. 'main.css?1e7cac4e4d8b52fd5ccd2541146ef03f'. | ||
// We must proper handle such cases, so we use regexp testing here | ||
return /^.css($|\?)/.test(path.extname(chunkFile)); | ||
}); | ||
@@ -136,2 +163,45 @@ assets.chunks[chunkName].css = css; | ||
/** | ||
* Injects the assets into the given html string | ||
*/ | ||
HtmlWebpackPlugin.prototype.injectAssetsIntoHtml = function(html, templateParams) { | ||
var assets = templateParams.htmlWebpackPlugin.files; | ||
var chunks = Object.keys(assets.chunks); | ||
// Gather all css and script files | ||
var styles = []; | ||
var scripts = []; | ||
chunks.forEach(function(chunkName) { | ||
styles = styles.concat(assets.chunks[chunkName].css); | ||
scripts.push(assets.chunks[chunkName].entry); | ||
}); | ||
// Turn script files into script tags | ||
scripts = scripts.map(function(scriptPath) { | ||
return '<script src="' + scriptPath + '"></script>'; | ||
}); | ||
// Turn css files into link tags | ||
styles = styles.map(function(stylePath) { | ||
return '<link href="' + stylePath + '" rel="stylesheet">'; | ||
}); | ||
// Append scripts to body element | ||
html = html.replace(/(<\/body>)/i, function (match) { | ||
return scripts.join('') + match; | ||
}); | ||
// Append styles to head element | ||
html = html.replace(/(<\/head>)/i, function (match) { | ||
return styles.join('') + match; | ||
}); | ||
// Inject manifest into the opening html tag | ||
if (assets.manifest) { | ||
html = html.replace(/(<html.*)(>)/i, function (match, start, end) { | ||
// Append the manifest only if no manifest was specified | ||
if (match.test(/\smanifest\s*=/)) { | ||
return match; | ||
} | ||
return start + ' manifest="' + assets.manifest + '"' + end; | ||
}); | ||
} | ||
return html; | ||
}; | ||
/** | ||
* A helper to support the templates written for html-webpack-plugin <= 1.1.0 | ||
@@ -148,4 +218,13 @@ */ | ||
/** | ||
* Appends a cache busting hash | ||
*/ | ||
HtmlWebpackPlugin.prototype.appendHash = function (url, hash) { | ||
if (!url) { | ||
return url; | ||
} | ||
return url + (url.indexOf('?') === -1 ? '?' : '&') + hash; | ||
}; | ||
module.exports = HtmlWebpackPlugin; |
{ | ||
"name": "html-webpack-plugin", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "Simplifies creation of HTML files to serve your webpack bundles", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -1,2 +0,2 @@ | ||
HTML Webpack Plugin | ||
HTML Webpack Plugin [![bitHound Score](https://www.bithound.io/github/ampedandwired/html-webpack-plugin/badges/score.svg)](https://www.bithound.io/github/ampedandwired/html-webpack-plugin) [![Dependency Status](https://david-dm.org/ampedandwired/html-webpack-plugin.svg)](https://david-dm.org/ampedandwired/html-webpack-plugin) | ||
=================== | ||
@@ -81,3 +81,3 @@ | ||
title: 'My App', | ||
filename 'assets/admin.html' | ||
filename: 'assets/admin.html' | ||
}) | ||
@@ -158,3 +158,3 @@ ] | ||
The `templateContent` option can also be a function: | ||
The `templateContent` option can also be a function to use another template language like jade: | ||
```javascript | ||
@@ -211,1 +211,26 @@ plugins: [ | ||
can be used, for example, to get the `publicPath` (`webpackConfig.output.publicPath`). | ||
Filtering chunks | ||
---------------- | ||
To include only certain chunks you can limit the chunks being used: | ||
```javascript | ||
plugins: [ | ||
new HtmlWebpackPlugin({ | ||
chunks: ['app'] | ||
}) | ||
] | ||
``` | ||
It is also possible to exclude certain chunks by setting the `excludeChunks` option: | ||
```javascript | ||
plugins: [ | ||
new HtmlWebpackPlugin({ | ||
excludeChunks: ['dev-helper'] | ||
}) | ||
] | ||
``` | ||
@@ -88,2 +88,73 @@ 'use strict'; | ||
it('allows you to inject the assets into a given html file', function (done) { | ||
testHtmlPlugin({ | ||
entry: { | ||
util: path.join(__dirname, 'fixtures/util.js'), | ||
app: path.join(__dirname, 'fixtures/index.js') | ||
}, | ||
output: { | ||
path: OUTPUT_DIR, | ||
filename: '[name]_bundle.js' | ||
}, | ||
plugins: [new HtmlWebpackPlugin({ | ||
inject: true, | ||
template: path.join(__dirname, 'fixtures/plain.html') | ||
})] | ||
}, ['<script src="util_bundle.js"', '<script src="app_bundle.js"'], null, done); | ||
}); | ||
it('allows you to inject the assets into a html string', function (done) { | ||
testHtmlPlugin({ | ||
entry: { | ||
util: path.join(__dirname, 'fixtures/util.js'), | ||
app: path.join(__dirname, 'fixtures/index.js') | ||
}, | ||
output: { | ||
path: OUTPUT_DIR, | ||
filename: '[name]_bundle.js' | ||
}, | ||
plugins: [new HtmlWebpackPlugin({ | ||
inject: true, | ||
chunks: ['util', 'app'], | ||
templateContent: fs.readFileSync(path.join(__dirname, 'fixtures/plain.html'), 'utf8') | ||
})] | ||
}, ['<script src="util_bundle.js"', '<script src="app_bundle.js"'], null, done); | ||
}); | ||
it('allows you to inject a specified asset into a given html file', function (done) { | ||
testHtmlPlugin({ | ||
entry: { | ||
util: path.join(__dirname, 'fixtures/util.js'), | ||
app: path.join(__dirname, 'fixtures/index.js') | ||
}, | ||
output: { | ||
path: OUTPUT_DIR, | ||
filename: '[name]_bundle.js' | ||
}, | ||
plugins: [new HtmlWebpackPlugin({ | ||
inject: true, | ||
chunks: ['app'], | ||
template: path.join(__dirname, 'fixtures/plain.html') | ||
})] | ||
}, ['<script src="app_bundle.js"'], null, done); | ||
}); | ||
it('allows you to inject a specified asset into a given html file', function (done) { | ||
testHtmlPlugin({ | ||
entry: { | ||
util: path.join(__dirname, 'fixtures/util.js'), | ||
app: path.join(__dirname, 'fixtures/index.js') | ||
}, | ||
output: { | ||
path: OUTPUT_DIR, | ||
filename: '[name]_bundle.js' | ||
}, | ||
plugins: [new HtmlWebpackPlugin({ | ||
inject: true, | ||
excludeChunks: ['util'], | ||
template: path.join(__dirname, 'fixtures/plain.html') | ||
})] | ||
}, ['<script src="app_bundle.js"'], null, done); | ||
}); | ||
it('allows you to use the deprecated assets object', function (done) { | ||
@@ -185,2 +256,13 @@ testHtmlPlugin({ | ||
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, inject: true})] | ||
}, ['<script src="index_bundle.js?%hash%"'], null, done); | ||
}); | ||
it('prepends the webpack public path to script src', function(done) { | ||
@@ -187,0 +269,0 @@ testHtmlPlugin({ |
39214
18
576
234