Compare commits
18 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
74909e4c94 | |
|
|
571407f960 | |
|
|
4f1ab08827 | |
|
|
8e89ea23de | |
|
|
7f63ba8988 | |
|
|
9e313ef6d1 | |
|
|
a5b10196be | |
|
|
58a3414a36 | |
|
|
2fb24b29be | |
|
|
a1442f2a54 | |
|
|
d91c306c81 | |
|
|
3066de978e | |
|
|
94fc6c98af | |
|
|
e56b2fb600 | |
|
|
c5033f9d95 | |
|
|
d793886a5e | |
|
|
998ef87cf7 | |
|
|
79b0e692f0 |
|
|
@ -1,2 +1,3 @@
|
||||||
/node_modules/
|
/node_modules/
|
||||||
/dist/
|
/dist/
|
||||||
|
examples/*/dist
|
||||||
15
README.md
15
README.md
|
|
@ -1,11 +1,11 @@
|
||||||
HTML Webpack Plugin
|
HTML Webpack Plugin
|
||||||
===================
|
===================
|
||||||
[](http://badge.fury.io/js/html-webpack-plugin) [](https://david-dm.org/ampedandwired/html-webpack-plugin) [](https://www.bithound.io/github/ampedandwired/html-webpack-plugin) [](https://travis-ci.org/ampedandwired/html-webpack-plugin)
|
[](http://badge.fury.io/js/html-webpack-plugin) [](https://david-dm.org/ampedandwired/html-webpack-plugin) [](https://www.bithound.io/github/ampedandwired/html-webpack-plugin) [](https://travis-ci.org/ampedandwired/html-webpack-plugin)
|
||||||
|
|
||||||
This is a [webpack](http://webpack.github.io/) plugin that simplifies creation of HTML files to serve your
|
This is a [webpack](http://webpack.github.io/) plugin that simplifies creation of HTML files to serve your
|
||||||
webpack bundles. This is especially useful for webpack bundles that include
|
webpack bundles. This is especially useful for webpack bundles that include
|
||||||
a hash in the filename which changes every compilation. You can either let the plugin generate an HTML file for you or supply
|
a hash in the filename which changes every compilation. You can either let the plugin generate an HTML file for you or supply
|
||||||
your own template (using [blueimp templates](https://github.com/blueimp/JavaScript-Templates)).
|
your own template (using lodash/ejs templates.
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
|
@ -63,15 +63,14 @@ Allowed values are as follows:
|
||||||
- `title`: The title to use for the generated HTML document.
|
- `title`: The title to use for the generated HTML document.
|
||||||
- `filename`: The file to write the HTML to. Defaults to `index.html`.
|
- `filename`: The file to write the HTML to. Defaults to `index.html`.
|
||||||
You can specify a subdirectory here too (eg: `assets/admin.html`).
|
You can specify a subdirectory here too (eg: `assets/admin.html`).
|
||||||
- `template`: A html template (supports [blueimp templates](https://github.com/blueimp/JavaScript-Templates)).
|
- `template`: Path to the template. Supports loaders e.g. `html!./index.html`.
|
||||||
- `templateContent`: A html string or a function returning the html (supports [blueimp templates](https://github.com/blueimp/JavaScript-Templates)).
|
|
||||||
- `inject`: `true | 'head' | 'body' | false` Inject all assets into the given `template` or `templateContent` - When passing `true` or `'body'` all javascript resources will be placed at the bottom of the body element. `'head'` will place the scripts in the head element.
|
- `inject`: `true | 'head' | 'body' | false` Inject all assets into the given `template` or `templateContent` - When passing `true` or `'body'` all javascript resources will be placed at the bottom of the body element. `'head'` will place the scripts in the head element.
|
||||||
- `favicon`: Adds the given favicon path to the output html.
|
- `favicon`: Adds the given favicon path to the output html.
|
||||||
- `minify`: `true | {...} | false` Set to true or pass a [html-minifier](https://github.com/kangax/html-minifier#options-quick-reference) options object to minify the output.
|
- `minify`: `true | {...} | false` Set to true or pass a [html-minifier](https://github.com/kangax/html-minifier#options-quick-reference) options object to minify the output.
|
||||||
- `hash`: `true | false` if `true` then append a unique webpack compilation hash to all
|
- `hash`: `true | false` if `true` then append a unique webpack compilation hash to all
|
||||||
included scripts and css files. This is useful for cache busting.
|
included scripts and css files. This is useful for cache busting.
|
||||||
- `chunks`: Allows you to add only some chunks (e.g. only the unit-test chunk)
|
- `chunks`: Allows you to add only some chunks (e.g. only the unit-test chunk)
|
||||||
- `excludeChunks`: Allows you to skip some chunks (e.g. don't add the unit-test chunk)
|
- `excludeChunks`: Allows you to skip some chunks (e.g. don't add the unit-test chunk)
|
||||||
|
|
||||||
Here's an example webpack config illustrating how to use these options:
|
Here's an example webpack config illustrating how to use these options:
|
||||||
```javascript
|
```javascript
|
||||||
|
|
@ -122,7 +121,7 @@ and favicon files into the markup.
|
||||||
```javascript
|
```javascript
|
||||||
plugins: [
|
plugins: [
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
title: 'Custom template',
|
title: 'Custom template',
|
||||||
template: 'my-index.html', // Load a custom template
|
template: 'my-index.html', // Load a custom template
|
||||||
inject: 'body' // Inject all scripts into the body
|
inject: 'body' // Inject all scripts into the body
|
||||||
})
|
})
|
||||||
|
|
@ -136,7 +135,7 @@ plugins: [
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
||||||
<title>{%=o.htmlWebpackPlugin.options.title}</title>
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
</body>
|
</body>
|
||||||
|
|
@ -154,7 +153,7 @@ plugins: [
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
You can use the [blueimp template](https://github.com/blueimp/JavaScript-Templates) syntax out of the box.
|
You can use the lodash/ejs syntax out of the box.
|
||||||
If the `inject` feature doesn't fit your needs and you want full control over the asset placement use the [default template](https://github.com/ampedandwired/html-webpack-plugin/blob/master/default_index.html)
|
If the `inject` feature doesn't fit your needs and you want full control over the asset placement use the [default template](https://github.com/ampedandwired/html-webpack-plugin/blob/master/default_index.html)
|
||||||
as a starting point for writing your own.
|
as a starting point for writing your own.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,9 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html{% if(o.htmlWebpackPlugin.files.manifest) { %} manifest="{%= o.htmlWebpackPlugin.files.manifest %}"{% } %}>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>{%=o.htmlWebpackPlugin.options.title || 'Webpack App'%}</title>
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
{% if (o.htmlWebpackPlugin.files.favicon) { %}
|
|
||||||
<link rel="shortcut icon" href="{%=o.htmlWebpackPlugin.files.favicon%}">
|
|
||||||
{% } %}
|
|
||||||
{% for (var css in o.htmlWebpackPlugin.files.css) { %}
|
|
||||||
<link href="{%=o.htmlWebpackPlugin.files.css[css] %}" rel="stylesheet">
|
|
||||||
{% } %}
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{% for (var chunk in o.htmlWebpackPlugin.files.chunks) { %}
|
|
||||||
<script src="{%=o.htmlWebpackPlugin.files.chunks[chunk].entry %}"></script>
|
|
||||||
{% } %}
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>{%=o.htmlWebpackPlugin.options.title || 'Webpack App'%}</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
require('./main.css');
|
||||||
|
var h1 = document.createElement('h1');
|
||||||
|
h1.innerHTML = 'Hello world!';
|
||||||
|
document.body.appendChild(h1);
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
|
|
@ -0,0 +1,3 @@
|
||||||
|
body {
|
||||||
|
background: snow;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Example template</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src="logo.png">
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
var HtmlWebpackPlugin = require('..');
|
||||||
|
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
|
module.exports = {
|
||||||
|
entry: './example.js',
|
||||||
|
output: {
|
||||||
|
path: __dirname + '/dist',
|
||||||
|
publicPath: '',
|
||||||
|
filename: 'bundle.js'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
loaders: [
|
||||||
|
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
|
||||||
|
{ test: /\.png$/, loader: 'file-loader' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
template: 'template.html'
|
||||||
|
}),
|
||||||
|
new ExtractTextPlugin('styles.css')
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
require('./main.css');
|
||||||
|
var h1 = document.createElement('h1');
|
||||||
|
h1.innerHTML = 'Hello world!';
|
||||||
|
document.body.appendChild(h1);
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
body {
|
||||||
|
background: snow;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
var HtmlWebpackPlugin = require('..');
|
||||||
|
module.exports = {
|
||||||
|
entry: './example.js',
|
||||||
|
output: {
|
||||||
|
path: __dirname + '/dist',
|
||||||
|
publicPath: '',
|
||||||
|
filename: 'bundle.js'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
loaders: [
|
||||||
|
{ test: /\.css$/, loader: 'style-loader!css-loader' },
|
||||||
|
{ test: /\.png$/, loader: 'file-loader' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new HtmlWebpackPlugin()
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
require('./main.css');
|
||||||
|
var h1 = document.createElement('h1');
|
||||||
|
h1.innerHTML = 'Hello world!';
|
||||||
|
document.body.appendChild(h1);
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 766 B |
|
|
@ -0,0 +1,3 @@
|
||||||
|
body {
|
||||||
|
background: snow;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Example template</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src="logo.png">
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
var HtmlWebpackPlugin = require('..');
|
||||||
|
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
|
module.exports = {
|
||||||
|
entry: './example.js',
|
||||||
|
output: {
|
||||||
|
path: __dirname + '/dist',
|
||||||
|
publicPath: '',
|
||||||
|
filename: 'bundle.js'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
loaders: [
|
||||||
|
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
|
||||||
|
{ test: /\.png$/, loader: 'file-loader' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
title: 'HtmlWebpackPlugin example',
|
||||||
|
favicon: 'favicon.ico',
|
||||||
|
filename: 'favicon.html'
|
||||||
|
}),
|
||||||
|
new ExtractTextPlugin('styles.css')
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
require('./main.css');
|
||||||
|
var h1 = document.createElement('h1');
|
||||||
|
h1.innerHTML = 'Hello world!';
|
||||||
|
document.body.appendChild(h1);
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 766 B |
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
|
|
@ -0,0 +1,3 @@
|
||||||
|
body {
|
||||||
|
background: snow;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Example template</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src="logo.png">
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
var HtmlWebpackPlugin = require('..');
|
||||||
|
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
|
module.exports = {
|
||||||
|
entry: './example.js',
|
||||||
|
output: {
|
||||||
|
path: __dirname + '/dist',
|
||||||
|
publicPath: '',
|
||||||
|
filename: 'bundle.js'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
loaders: [
|
||||||
|
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
|
||||||
|
{ test: /\.png$/, loader: 'file-loader' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
filename: 'html-loader.html',
|
||||||
|
favicon: 'favicon.ico',
|
||||||
|
template: 'html!./template.html'
|
||||||
|
}),
|
||||||
|
new ExtractTextPlugin('styles.css')
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
require('./main.css');
|
||||||
|
var h1 = document.createElement('h1');
|
||||||
|
h1.innerHTML = 'Hello world!';
|
||||||
|
document.body.appendChild(h1);
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
|
|
@ -0,0 +1,3 @@
|
||||||
|
body {
|
||||||
|
background: snow;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
<h2>Partial</h2>
|
||||||
|
<img src="logo.png">
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Example template</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%- include(require('html!./partial.html'), {}); %>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
var HtmlWebpackPlugin = require('../..');
|
||||||
|
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
|
module.exports = {
|
||||||
|
entry: './example.js',
|
||||||
|
output: {
|
||||||
|
path: __dirname + '/dist',
|
||||||
|
publicPath: '',
|
||||||
|
filename: 'bundle.js'
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
loaders: [
|
||||||
|
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
|
||||||
|
{ test: /\.png$/, loader: 'file-loader' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
template: 'template.html'
|
||||||
|
}),
|
||||||
|
new ExtractTextPlugin('styles.css')
|
||||||
|
]
|
||||||
|
};
|
||||||
399
index.js
399
index.js
|
|
@ -1,154 +1,249 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
var vm = require('vm');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var path = require('path');
|
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
var tmpl = require('blueimp-tmpl').tmpl;
|
|
||||||
var Promise = require('bluebird');
|
var Promise = require('bluebird');
|
||||||
|
var path = require('path');
|
||||||
Promise.promisifyAll(fs);
|
Promise.promisifyAll(fs);
|
||||||
|
|
||||||
|
var NodeTemplatePlugin = require('webpack/lib/node/NodeTemplatePlugin');
|
||||||
|
var NodeTargetPlugin = require('webpack/lib/node/NodeTargetPlugin');
|
||||||
|
var LibraryTemplatePlugin = require('webpack/lib/LibraryTemplatePlugin');
|
||||||
|
var SingleEntryPlugin = require('webpack/lib/SingleEntryPlugin');
|
||||||
|
|
||||||
function HtmlWebpackPlugin(options) {
|
function HtmlWebpackPlugin(options) {
|
||||||
this.options = options || {};
|
// Default options
|
||||||
|
this.options = _.extend({
|
||||||
|
template: __dirname + '/default_index.html',
|
||||||
|
filename: 'index.html',
|
||||||
|
hash: false,
|
||||||
|
inject: true,
|
||||||
|
compile: true,
|
||||||
|
favicon: false,
|
||||||
|
minify: false,
|
||||||
|
chunks: 'all',
|
||||||
|
excludeChunks: [],
|
||||||
|
title: 'Webpack App'
|
||||||
|
}, options);
|
||||||
|
// If the template doesn't use a loader use the blueimp template loader
|
||||||
|
if(this.options.template.indexOf('!') === -1) {
|
||||||
|
this.options.template = require.resolve('./loader.js') + '!' + path.resolve(this.options.template);
|
||||||
|
}
|
||||||
|
// Resolve template path
|
||||||
|
this.options.template = this.options.template.replace(
|
||||||
|
/(\!)([^\/\\][^\!\?]+|[^\/\\!?])($|\?.+$)/,
|
||||||
|
function(match, prefix, filepath, postfix) {
|
||||||
|
return prefix + path.resolve(filepath) + postfix;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
HtmlWebpackPlugin.prototype.apply = function(compiler) {
|
HtmlWebpackPlugin.prototype.apply = function(compiler) {
|
||||||
var self = this;
|
var self = this;
|
||||||
compiler.plugin('emit', function(compilation, compileCallback) {
|
var compilationPromise;
|
||||||
var webpackStatsJson = compilation.getStats().toJson();
|
self.context = compiler.context;
|
||||||
var outputFilename = self.options.filename || 'index.html';
|
|
||||||
|
compiler.plugin('make', function(compilation, callback) {
|
||||||
|
// Compile the template
|
||||||
|
compilationPromise = self.compileTemplate(self.options.template, self.options.filename, compilation);
|
||||||
|
compilationPromise.finally(callback);
|
||||||
|
});
|
||||||
|
|
||||||
|
compiler.plugin('emit', function(compilation, callback) {
|
||||||
|
// Get all chunks
|
||||||
|
var chunks = self.filterChunks(compilation.getStats().toJson(), self.options.chunks, self.options.excludeChunks);
|
||||||
|
// Get assets
|
||||||
|
var assets = self.htmlWebpackPluginAssets(compilation, chunks);
|
||||||
Promise.resolve()
|
Promise.resolve()
|
||||||
// Add the favicon
|
// Favicon
|
||||||
.then(function(callback) {
|
.then(function() {
|
||||||
if (self.options.favicon) {
|
if (self.options.favicon) {
|
||||||
return self.addFileToAssets(compilation, self.options.favicon, callback);
|
return self.addFileToAssets(self.options.favicon, compilation)
|
||||||
|
.then(function(faviconBasename){
|
||||||
|
assets.favicon = faviconBasename;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// Generate the html
|
// Wait for the compilation to finish
|
||||||
.then(function() {
|
.then(function() {
|
||||||
var templateParams = {
|
return compilationPromise;
|
||||||
webpack: webpackStatsJson,
|
})
|
||||||
webpackConfig: compilation.options,
|
.then(function(resultAsset) {
|
||||||
htmlWebpackPlugin: {
|
// Once everything is compiled evaluate the html factory
|
||||||
files: self.htmlWebpackPluginAssets(compilation, webpackStatsJson, self.options.chunks, self.options.excludeChunks),
|
// and replace it with its content
|
||||||
options: self.options,
|
return self.evaluateCompilationResult(compilation, resultAsset);
|
||||||
}
|
})
|
||||||
};
|
// Execute the template
|
||||||
// Deprecate templateParams.htmlWebpackPlugin.assets
|
.then(function(compilationResult) {
|
||||||
var assets = self.htmlWebpackPluginLegacyAssets(compilation, webpackStatsJson);
|
// If the loader result is a function execute it to retreive the html
|
||||||
Object.defineProperty(templateParams.htmlWebpackPlugin, 'assets', {
|
// otherwise use the returned html
|
||||||
get: function() {
|
return typeof compilationResult !== 'function' ? compilationResult :
|
||||||
compilation.warnings.push(new Error('HtmlWebPackPlugin: htmlWebpackPlugin.assets is deprecated - please use inject or htmlWebpackPlugin.files instead' +
|
self.executeTemplate(compilationResult, chunks, assets, compilation);
|
||||||
'\nsee: https://github.com/ampedandwired/html-webpack-plugin/issues/52'));
|
})
|
||||||
return assets;
|
.then(function(html) {
|
||||||
}
|
// Add the stylesheets, scripts and so on to the resulting html
|
||||||
});
|
return self.postProcessHtml(html, assets);
|
||||||
|
|
||||||
// Get/generate html
|
|
||||||
return self.getTemplateContent(compilation, templateParams)
|
|
||||||
.then(function(htmlTemplateContent) {
|
|
||||||
// Compile and add html to compilation
|
|
||||||
return self.emitHtml(compilation, htmlTemplateContent, templateParams, outputFilename);
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
// In case anything went wrong let the user know
|
|
||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
compilation.errors.push(err);
|
// In case anything went wrong the promise is resolved
|
||||||
compilation.assets[outputFilename] = {
|
// with the error message and an error is logged
|
||||||
|
var errorMessage = "HtmlWebpackPlugin Error: " + err;
|
||||||
|
compilation.errors.push(new Error(errorMessage));
|
||||||
|
return errorMessage;
|
||||||
|
})
|
||||||
|
.then(function(html) {
|
||||||
|
// Replace the compilation result with the evaluated html code
|
||||||
|
compilation.assets[self.options.filename] = {
|
||||||
source: function() {
|
source: function() {
|
||||||
return err.toString();
|
return html;
|
||||||
},
|
},
|
||||||
size: function() {
|
size: function() {
|
||||||
return err.toString().length;
|
return html.length;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})
|
callback();
|
||||||
// Tell the compiler to proceed
|
});
|
||||||
.finally(compileCallback);
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the child compiler name
|
||||||
|
*/
|
||||||
|
HtmlWebpackPlugin.prototype.getCompilerName = function() {
|
||||||
|
var absolutePath = path.resolve(this.context, this.options.filename);
|
||||||
|
var relativePath = path.relative(this.context, absolutePath);
|
||||||
|
return 'html-webpack-plugin for "' + (absolutePath.length < relativePath.length ? absolutePath : relativePath) + '"';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compiles the template into a nodejs factory, adds its to the compilation.assets
|
||||||
|
* and returns a promise of the result asset object.
|
||||||
|
*/
|
||||||
|
HtmlWebpackPlugin.prototype.compileTemplate = function(template, outputFilename, compilation) {
|
||||||
|
// The entry file is just an empty helper as the dynamic template
|
||||||
|
// require is added in "loader.js"
|
||||||
|
var outputOptions = {
|
||||||
|
filename: outputFilename,
|
||||||
|
publicPath: compilation.outputOptions.publicPath
|
||||||
|
};
|
||||||
|
// Create an additional child compiler which takes the template
|
||||||
|
// and turns it into an Node.JS html factory.
|
||||||
|
// This allows us to use loaders during the compilation
|
||||||
|
var compilerName = this.getCompilerName();
|
||||||
|
var childCompiler = compilation.createChildCompiler(compilerName, outputOptions);
|
||||||
|
childCompiler.apply(new NodeTemplatePlugin(outputOptions));
|
||||||
|
childCompiler.apply(new LibraryTemplatePlugin('result', 'var'));
|
||||||
|
childCompiler.apply(new NodeTargetPlugin());
|
||||||
|
childCompiler.apply(new SingleEntryPlugin(this.context, template));
|
||||||
|
// Create a subCache (copied from https://github.com/SanderSpies/extract-text-webpack-plugin/blob/master/loader.js)
|
||||||
|
childCompiler.plugin('compilation', function(compilation) {
|
||||||
|
if(compilation.cache) {
|
||||||
|
if(!compilation.cache[compilerName]) {
|
||||||
|
compilation.cache[compilerName] = {};
|
||||||
|
}
|
||||||
|
compilation.cache = compilation.cache[compilerName];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Compile and return a promise
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
childCompiler.runAsChild(function(err) {
|
||||||
|
// Resolve / reject the promise
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve(compilation.assets[outputFilename]);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the html source depending on `this.options`.
|
* Evaluates the child compilation result
|
||||||
* Supports:
|
* Returns a promise
|
||||||
* + options.fileContent as string
|
|
||||||
* + options.fileContent as sync function
|
|
||||||
* + options.fileContent as async function
|
|
||||||
* + options.template as template path
|
|
||||||
* Returns a Promise
|
|
||||||
*/
|
*/
|
||||||
HtmlWebpackPlugin.prototype.getTemplateContent = function(compilation, templateParams) {
|
HtmlWebpackPlugin.prototype.evaluateCompilationResult = function(compilation, compilationResult) {
|
||||||
|
if(!compilationResult) {
|
||||||
|
return Promise.reject('The child compilation didn\'t provide a result');
|
||||||
|
}
|
||||||
|
// Strip the leading 'var '
|
||||||
|
var source = compilationResult.source().substr(3);
|
||||||
|
// Evaluate code and cast to string
|
||||||
|
var newSource;
|
||||||
|
try {
|
||||||
|
newSource = vm.runInThisContext(source);
|
||||||
|
} catch (e) {
|
||||||
|
compilation.errors.push(new Error('Template compilation failed: ' + 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.');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Html post processing
|
||||||
|
*
|
||||||
|
* Returns a promise
|
||||||
|
*/
|
||||||
|
HtmlWebpackPlugin.prototype.executeTemplate = function(templateFunction, chunks, assets, compilation) {
|
||||||
var self = this;
|
var self = this;
|
||||||
// If config is invalid
|
return Promise.resolve()
|
||||||
if (self.options.templateContent && self.options.template) {
|
// Template processing
|
||||||
return Promise.reject(new Error('HtmlWebpackPlugin: cannot specify both template and templateContent options'));
|
.then(function() {
|
||||||
}
|
var templateParams = {
|
||||||
// If a function is passed
|
webpack: compilation.getStats().toJson(),
|
||||||
if (typeof self.options.templateContent === 'function') {
|
webpackConfig: compilation.options,
|
||||||
return Promise.fromNode(function(callback) {
|
htmlWebpackPlugin: {
|
||||||
// allow to specify a sync or an async function to generate the template content
|
files: assets,
|
||||||
var result = self.options.templateContent(templateParams, compilation, callback);
|
options: self.options,
|
||||||
// if it returns a result expect it to be sync
|
}
|
||||||
if (result !== undefined) {
|
};
|
||||||
callback(null, result);
|
var html = '';
|
||||||
|
try {
|
||||||
|
html = templateFunction(templateParams);
|
||||||
|
} catch (e) {
|
||||||
|
compilation.errors.push(new Error('Template execution failed: ' + e));
|
||||||
|
return Promise.reject(e);
|
||||||
}
|
}
|
||||||
});
|
return html;
|
||||||
}
|
|
||||||
// If a string is passed
|
|
||||||
if (self.options.templateContent) {
|
|
||||||
return Promise.resolve(self.options.templateContent);
|
|
||||||
}
|
|
||||||
// If templateContent is empty use the template option
|
|
||||||
var templateFile = self.options.template;
|
|
||||||
if (!templateFile) {
|
|
||||||
// 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');
|
|
||||||
}
|
|
||||||
compilation.fileDependencies.push(templateFile);
|
|
||||||
return fs.readFileAsync(templateFile, 'utf8')
|
|
||||||
// If the file could not be read log a error
|
|
||||||
.catch(function() {
|
|
||||||
return Promise.reject(new Error('HtmlWebpackPlugin: Unable to read HTML template "' + templateFile + '"'));
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Compile the html template and push the result to the compilation assets
|
* Html post processing
|
||||||
|
*
|
||||||
|
* Returns a promise
|
||||||
*/
|
*/
|
||||||
HtmlWebpackPlugin.prototype.emitHtml = function(compilation, htmlTemplateContent, templateParams, outputFilename) {
|
HtmlWebpackPlugin.prototype.postProcessHtml = function(html, assets) {
|
||||||
var html;
|
var self = this;
|
||||||
// blueimp-tmpl processing
|
return Promise.resolve()
|
||||||
try {
|
// Inject
|
||||||
html = tmpl(htmlTemplateContent, templateParams);
|
.then(function() {
|
||||||
} catch(e) {
|
if (self.options.inject) {
|
||||||
return Promise.reject(new Error('HtmlWebpackPlugin: template error ' + e));
|
return self.injectAssetsIntoHtml(html, assets);
|
||||||
}
|
} else {
|
||||||
|
return html;
|
||||||
// Inject link and script elements into an existing html file
|
}
|
||||||
if (this.options.inject) {
|
})
|
||||||
html = this.injectAssetsIntoHtml(html, templateParams);
|
// Minify
|
||||||
}
|
.then(function(html) {
|
||||||
|
if (self.options.minify) {
|
||||||
// Minify the html output
|
var minify = require('html-minifier').minify;
|
||||||
if (this.options.minify) {
|
// If `options.minify` is set to true use the default minify options
|
||||||
var minify = require('html-minifier').minify;
|
var minifyOptions = _.isObject(self.options.minify) ? self.options.minify : {};
|
||||||
// If `options.minify` is set to true use the default minify options
|
try {
|
||||||
var minifyOptions = _.isObject(this.options.minify) ? this.options.minify : {};
|
minify(html, minifyOptions);
|
||||||
html = minify(html, minifyOptions);
|
} catch(e) {
|
||||||
}
|
Promise.reject(e);
|
||||||
|
}
|
||||||
compilation.assets[outputFilename] = {
|
}
|
||||||
source: function() {
|
|
||||||
return html;
|
return html;
|
||||||
},
|
});
|
||||||
size: function() {
|
|
||||||
return html.length;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pushes the content of the given filename to the compilation assets
|
* Pushes the content of the given filename to the compilation assets
|
||||||
*/
|
*/
|
||||||
HtmlWebpackPlugin.prototype.addFileToAssets = function(compilation, filename) {
|
HtmlWebpackPlugin.prototype.addFileToAssets = function(filename, compilation) {
|
||||||
return Promise.props({
|
return Promise.props({
|
||||||
size: fs.statAsync(filename),
|
size: fs.statAsync(filename),
|
||||||
source: fs.readFileAsync(filename)
|
source: fs.readFileAsync(filename)
|
||||||
|
|
@ -157,24 +252,57 @@ HtmlWebpackPlugin.prototype.addFileToAssets = function(compilation, filename) {
|
||||||
return Promise.reject(new Error('HtmlWebpackPlugin: could not load file ' + filename));
|
return Promise.reject(new Error('HtmlWebpackPlugin: could not load file ' + filename));
|
||||||
})
|
})
|
||||||
.then(function(results) {
|
.then(function(results) {
|
||||||
|
var basename = path.basename(filename);
|
||||||
compilation.fileDependencies.push(filename);
|
compilation.fileDependencies.push(filename);
|
||||||
compilation.assets[path.basename(filename)] = {
|
compilation.assets[basename] = {
|
||||||
source: function() {
|
source: function() {
|
||||||
return results.source;
|
return results.source;
|
||||||
},
|
},
|
||||||
size: function() {
|
size: function() {
|
||||||
return results.size;
|
return results.size.size;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
return basename;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webpackStatsJson, includedChunks, excludedChunks) {
|
/**
|
||||||
|
* Return all chunks from the compilation result which match the exclude and include filters
|
||||||
|
*/
|
||||||
|
HtmlWebpackPlugin.prototype.filterChunks = function (webpackStatsJson, includedChunks, excludedChunks) {
|
||||||
|
var chunks = webpackStatsJson.chunks.filter(function(chunk){
|
||||||
|
var chunkName = chunk.names[0];
|
||||||
|
// This chunk doesn't have a name. This script can't handled it.
|
||||||
|
if (chunkName === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Skip if the chunks should be filtered and the given chunk was not added explicity
|
||||||
|
if (Array.isArray(includedChunks) && includedChunks.indexOf(chunkName) === -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Skip if the chunks should be filtered and the given chunk was excluded explicity
|
||||||
|
if (Array.isArray(excludedChunks) && excludedChunks.indexOf(chunkName) !== -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Add otherwise
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
return chunks.sort(function orderEntryLast(a, b) {
|
||||||
|
if (a.entry !== b.entry) {
|
||||||
|
return b.entry ? 1 : -1;
|
||||||
|
} else {
|
||||||
|
return b.id - a.id;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, chunks) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var webpackStatsJson = compilation.getStats().toJson();
|
||||||
|
|
||||||
// Use the configured public path or build a relative path
|
// Use the configured public path or build a relative path
|
||||||
var publicPath = typeof compilation.options.output.publicPath !== 'undefined' ?
|
var publicPath = typeof compilation.options.output.publicPath !== 'undefined' ?
|
||||||
compilation.options.output.publicPath :
|
compilation.options.output.publicPath :
|
||||||
path.relative(path.dirname(self.options.filename), '.');
|
path.relative(path.dirname(self.options.filename), '.');
|
||||||
|
|
||||||
if (publicPath.length && publicPath.substr(-1, 1) !== '/') {
|
if (publicPath.length && publicPath.substr(-1, 1) !== '/') {
|
||||||
|
|
@ -188,8 +316,6 @@ HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webp
|
||||||
js: [],
|
js: [],
|
||||||
// Will contain all css files
|
// Will contain all css files
|
||||||
css: [],
|
css: [],
|
||||||
// Will contain the path to the favicon if it exists
|
|
||||||
favicon: self.options.favicon ? publicPath + path.basename(self.options.favicon): undefined,
|
|
||||||
// Will contain the html5 appcache manifest files if it exists
|
// Will contain the html5 appcache manifest files if it exists
|
||||||
manifest: Object.keys(compilation.assets).filter(function(assetFile){
|
manifest: Object.keys(compilation.assets).filter(function(assetFile){
|
||||||
return path.extname(assetFile) === '.appcache';
|
return path.extname(assetFile) === '.appcache';
|
||||||
|
|
@ -202,32 +328,10 @@ HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webp
|
||||||
assets.favicon = self.appendHash(assets.favicon, webpackStatsJson.hash);
|
assets.favicon = self.appendHash(assets.favicon, webpackStatsJson.hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
for (var i = 0; i < chunks.length; i++) {
|
for (var i = 0; i < chunks.length; i++) {
|
||||||
var chunk = chunks[i];
|
var chunk = chunks[i];
|
||||||
var chunkName = chunk.names[0];
|
var chunkName = chunk.names[0];
|
||||||
|
|
||||||
// This chunk doesn't have a name. This script can't handled it.
|
|
||||||
if(chunkName === undefined) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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] = {};
|
assets.chunks[chunkName] = {};
|
||||||
|
|
||||||
// Prepend the public path to all chunk files
|
// Prepend the public path to all chunk files
|
||||||
|
|
@ -268,8 +372,7 @@ HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webp
|
||||||
/**
|
/**
|
||||||
* Injects the assets into the given html string
|
* Injects the assets into the given html string
|
||||||
*/
|
*/
|
||||||
HtmlWebpackPlugin.prototype.injectAssetsIntoHtml = function(html, templateParams) {
|
HtmlWebpackPlugin.prototype.injectAssetsIntoHtml = function(html, assets) {
|
||||||
var assets = templateParams.htmlWebpackPlugin.files;
|
|
||||||
var chunks = Object.keys(assets.chunks);
|
var chunks = Object.keys(assets.chunks);
|
||||||
|
|
||||||
// Gather all css and script files
|
// Gather all css and script files
|
||||||
|
|
@ -324,18 +427,6 @@ HtmlWebpackPlugin.prototype.injectAssetsIntoHtml = function(html, templateParams
|
||||||
return html;
|
return html;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends a cache busting hash
|
* Appends a cache busting hash
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
var _ = require('lodash');
|
||||||
|
var loaderUtils = require('loader-utils');
|
||||||
|
|
||||||
|
module.exports = function (source) {
|
||||||
|
'use strict';
|
||||||
|
if (this.cacheable) {
|
||||||
|
this.cacheable();
|
||||||
|
}
|
||||||
|
var allLoadersButThisOne = this.loaders.filter(function(loader) {
|
||||||
|
return loader.module !== module.exports;
|
||||||
|
});
|
||||||
|
// This loader shouldn't kick in if there is any other loader
|
||||||
|
if (allLoadersButThisOne.length > 0) {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
// Use underscore for a minimalistic loader
|
||||||
|
var options = loaderUtils.parseQuery(this.query);
|
||||||
|
var template = _.template(source, options);
|
||||||
|
return 'module.exports = ' + template;
|
||||||
|
};
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "html-webpack-plugin",
|
"name": "html-webpack-plugin",
|
||||||
"version": "1.5.2",
|
"version": "2.0.0",
|
||||||
"description": "Simplifies creation of HTML files to serve your webpack bundles",
|
"description": "Simplifies creation of HTML files to serve your webpack bundles",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"files": [
|
"files": [
|
||||||
"index.js",
|
"index.js",
|
||||||
|
"loader.js",
|
||||||
"default_index.html",
|
"default_index.html",
|
||||||
"default_inject_index.html"
|
"default_inject_index.html"
|
||||||
],
|
],
|
||||||
|
|
@ -32,6 +33,7 @@
|
||||||
"css-loader": "^0.12.0",
|
"css-loader": "^0.12.0",
|
||||||
"extract-text-webpack-plugin": "^0.7.1",
|
"extract-text-webpack-plugin": "^0.7.1",
|
||||||
"file-loader": "^0.8.1",
|
"file-loader": "^0.8.1",
|
||||||
|
"html-loader": "^0.3.0",
|
||||||
"jasmine-node": "^1.14.5",
|
"jasmine-node": "^1.14.5",
|
||||||
"jshint": "^2.7.0",
|
"jshint": "^2.7.0",
|
||||||
"rimraf": "^2.3.3",
|
"rimraf": "^2.3.3",
|
||||||
|
|
@ -41,8 +43,8 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bluebird": "^2.9.25",
|
"bluebird": "^2.9.25",
|
||||||
"blueimp-tmpl": "~2.5.4",
|
|
||||||
"html-minifier": "^0.7.2",
|
"html-minifier": "^0.7.2",
|
||||||
|
"loader-utils": "^0.2.10",
|
||||||
"lodash": "~3.9.3"
|
"lodash": "~3.9.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,11 @@ function testHtmlPlugin(webpackConfig, expectedResults, outputFile, done, expect
|
||||||
} else {
|
} else {
|
||||||
expect(compilationWarnings).toBe('');
|
expect(compilationWarnings).toBe('');
|
||||||
}
|
}
|
||||||
|
var outputFileExists = fs.existsSync(path.join(OUTPUT_DIR, outputFile));
|
||||||
|
expect(outputFileExists).toBe(true);
|
||||||
|
if(!outputFileExists) {
|
||||||
|
return done();
|
||||||
|
}
|
||||||
var htmlContent = fs.readFileSync(path.join(OUTPUT_DIR, outputFile)).toString();
|
var htmlContent = fs.readFileSync(path.join(OUTPUT_DIR, outputFile)).toString();
|
||||||
|
|
||||||
for (var i = 0; i < expectedResults.length; i++) {
|
for (var i = 0; i < expectedResults.length; i++) {
|
||||||
|
|
@ -83,20 +88,6 @@ describe('HtmlWebpackPlugin', function() {
|
||||||
['<script src="app_bundle.js', 'Some unique text'], null, done);
|
['<script src="app_bundle.js', 'Some unique text'], null, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows you to specify your own HTML template string', function(done) {
|
|
||||||
testHtmlPlugin({
|
|
||||||
entry: {app: path.join(__dirname, 'fixtures/index.js')},
|
|
||||||
output: {
|
|
||||||
path: OUTPUT_DIR,
|
|
||||||
filename: 'app_bundle.js'
|
|
||||||
},
|
|
||||||
plugins: [new HtmlWebpackPlugin({
|
|
||||||
templateContent: fs.readFileSync(path.join(__dirname, 'fixtures/test.html'), 'utf8')
|
|
||||||
})]
|
|
||||||
},
|
|
||||||
['<script src="app_bundle.js'], null, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('allows you to inject the assets into a given html file', function (done) {
|
it('allows you to inject the assets into a given html file', function (done) {
|
||||||
testHtmlPlugin({
|
testHtmlPlugin({
|
||||||
entry: {
|
entry: {
|
||||||
|
|
@ -148,24 +139,6 @@ describe('HtmlWebpackPlugin', function() {
|
||||||
}, ['<script src="util_bundle.js"', '<script src="app_bundle.js"'], null, done);
|
}, ['<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) {
|
it('allows you to inject a specified asset into a given html file', function (done) {
|
||||||
testHtmlPlugin({
|
testHtmlPlugin({
|
||||||
entry: {
|
entry: {
|
||||||
|
|
@ -202,34 +175,6 @@ describe('HtmlWebpackPlugin', function() {
|
||||||
}, ['<script src="app_bundle.js"'], null, done);
|
}, ['<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, false, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('allows you to use a deprecated legacy_index template', 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, false, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('allows you to specify your own HTML template function', function(done) {
|
it('allows you to specify your own HTML template function', function(done) {
|
||||||
testHtmlPlugin({
|
testHtmlPlugin({
|
||||||
entry: {app: path.join(__dirname, 'fixtures/index.js')},
|
entry: {app: path.join(__dirname, 'fixtures/index.js')},
|
||||||
|
|
@ -246,24 +191,6 @@ describe('HtmlWebpackPlugin', function() {
|
||||||
['<script src="app_bundle.js"'], null, done);
|
['<script src="app_bundle.js"'], null, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('registers a webpack error both template and template content are specified', function(done) {
|
|
||||||
webpack({
|
|
||||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
|
||||||
output: {
|
|
||||||
path: OUTPUT_DIR,
|
|
||||||
filename: 'index_bundle.js'
|
|
||||||
},
|
|
||||||
plugins: [new HtmlWebpackPlugin({
|
|
||||||
template: path.join(__dirname, 'fixtures/test.html'),
|
|
||||||
templateContent: 'whatever'
|
|
||||||
})]
|
|
||||||
}, function(err, stats) {
|
|
||||||
expect(stats.hasErrors()).toBe(true);
|
|
||||||
expect(stats.toJson().errors[0]).toContain('HtmlWebpackPlugin');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('works with source maps', function(done) {
|
it('works with source maps', function(done) {
|
||||||
testHtmlPlugin({
|
testHtmlPlugin({
|
||||||
devtool: 'sourcemap',
|
devtool: 'sourcemap',
|
||||||
|
|
@ -489,21 +416,6 @@ describe('HtmlWebpackPlugin', function() {
|
||||||
expect(fs.existsSync(path.join(__dirname, 'fixtures/test.html'))).toBe(true);
|
expect(fs.existsSync(path.join(__dirname, 'fixtures/test.html'))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('registers a webpack error if the template cannot be opened', function(done) {
|
|
||||||
webpack({
|
|
||||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
|
||||||
output: {
|
|
||||||
path: OUTPUT_DIR,
|
|
||||||
filename: 'index_bundle.js'
|
|
||||||
},
|
|
||||||
plugins: [new HtmlWebpackPlugin({template: 'fixtures/does_not_exist.html'})]
|
|
||||||
}, function(err, stats) {
|
|
||||||
expect(stats.hasErrors()).toBe(true);
|
|
||||||
expect(stats.toJson().errors[0]).toContain('HtmlWebpackPlugin');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('exposes the webpack configuration to templates', function(done) {
|
it('exposes the webpack configuration to templates', function(done) {
|
||||||
testHtmlPlugin({
|
testHtmlPlugin({
|
||||||
entry: {
|
entry: {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>{%=o.htmlWebpackPlugin.options.title || 'Webpack App'%}</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{% for (var chunk in o.htmlWebpackPlugin.assets) { %}
|
|
||||||
<script src="{%=o.htmlWebpackPlugin.assets[chunk]%}"></script>
|
|
||||||
{% } %}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<title>Test</title>
|
<title>Test</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<p>Public path is {%=o.webpackConfig.output.publicPath%}</p>
|
<p>Public path is <%= webpackConfig.output.publicPath %></p>
|
||||||
<script src="{%=o.htmlWebpackPlugin.files.chunks.app.entry%}"></script>
|
<script src="<%= htmlWebpackPlugin.files.chunks.app.entry %>"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue