From 6c4492ad1d535214c6c12f633830581b39e669cb Mon Sep 17 00:00:00 2001 From: Stefan Frede Date: Tue, 8 Sep 2020 17:19:00 +0200 Subject: [PATCH 1/5] feat: implement html minifier --- plugins/plugin-webpack/package.json | 1 + plugins/plugin-webpack/plugin.js | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/plugins/plugin-webpack/package.json b/plugins/plugin-webpack/package.json index 56804d6c4a..3bd00e8d78 100644 --- a/plugins/plugin-webpack/package.json +++ b/plugins/plugin-webpack/package.json @@ -13,6 +13,7 @@ "css-loader": "^3.5.3", "file-loader": "^6.0.0", "glob": "^7.1.6", + "html-minifier": "^4.0.0", "jsdom": "^16.2.2", "mini-css-extract-plugin": "^0.9.0", "optimize-css-assets-webpack-plugin": "^5.0.3", diff --git a/plugins/plugin-webpack/plugin.js b/plugins/plugin-webpack/plugin.js index e15b32f4cf..612a70fb02 100644 --- a/plugins/plugin-webpack/plugin.js +++ b/plugins/plugin-webpack/plugin.js @@ -11,6 +11,7 @@ const ManifestPlugin = require('webpack-manifest-plugin'); const jsdom = require("jsdom"); const { JSDOM } = jsdom; const cwd = process.cwd(); +const minify = require('html-minifier').minify; function insertBefore(newNode, existingNode) { existingNode.parentNode.insertBefore(newNode, existingNode); @@ -87,7 +88,19 @@ function emitHTMLFiles({ doms, jsEntries, stats, baseUrl, buildDirectory }) { //And write our modified html files out to the destination for (const [htmlFile, dom] of Object.entries(doms)) { - fs.writeFileSync(path.join(buildDirectory, htmlFile), dom.serialize()); + const html = dom.serialize(); + // HTMLMinifier + // https://github.com/kangax/html-minifier#options-quick-reference + const htmlMinified = minify(html, { + collapseWhitespace: true, + removeComments: true, + removeEmptyAttributes: true, + removeRedundantAttributes: true, + removeScriptTypeAttributes: true, + removeStyleLinkTypeAttributes: true, + }); + + fs.writeFileSync(path.join(buildDirectory, htmlFile), htmlMinified); } } From 6687dbb0bcf04468c6eb33b3f0e4d9bde587193e Mon Sep 17 00:00:00 2001 From: Stefan Frede Date: Wed, 9 Sep 2020 05:51:04 +0200 Subject: [PATCH 2/5] refactor: make the html minification configurable --- plugins/plugin-webpack/README.md | 32 ++++++++++++++++++++ plugins/plugin-webpack/plugin.js | 50 ++++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 15 deletions(-) diff --git a/plugins/plugin-webpack/README.md b/plugins/plugin-webpack/README.md index 502ee297b6..5e3bb87e59 100644 --- a/plugins/plugin-webpack/README.md +++ b/plugins/plugin-webpack/README.md @@ -27,6 +27,7 @@ npm install --save-dev @snowpack/plugin-webpack - `outputPattern: {css: string, js: string, assets: string}` - Set the URL for your final bundled files. This is where they will be written to disk in the `build/` directory. See Webpack's [`output.filename`](https://webpack.js.org/configuration/output/#outputfilename) documentation for examples of valid values. - `extendConfig: (config: WebpackConfig) => WebpackConfig` - extend your webpack config, see below. - `manifest: boolean | string` - Enable generating a manifest file. The default value is `false`, the default file name is `./asset-manifest.json` if setting manifest to `true`. The relative path is resolved from the output directory. +- `htmlMinifierOptions: boolean | object` - See below. #### Extending The Default Webpack Config @@ -50,3 +51,34 @@ module.exports = { ], }; ``` + +#### Minify HTML + +With `htmlMinifierOptions` you can either disable the minification entirely or provide your own [options](https://github.com/kangax/html-minifier#options-quick-reference). + +```js +// snowpack.config.js +module.exports = { + plugins: [ + [ + "@snowpack/plugin-webpack", + { + htmlMinifierOptions: false // disabled entirely, + }, + ], + ], +}; +``` + +The default options are: + +```js +{ + collapseWhitespace: true, + removeComments: true, + removeEmptyAttributes: true, + removeRedundantAttributes: true, + removeScriptTypeAttributes: true, + removeStyleLinkTypeAttributes: true, +} +``` diff --git a/plugins/plugin-webpack/plugin.js b/plugins/plugin-webpack/plugin.js index 612a70fb02..668176a261 100644 --- a/plugins/plugin-webpack/plugin.js +++ b/plugins/plugin-webpack/plugin.js @@ -52,7 +52,13 @@ function parseHTMLFiles({ buildDirectory }) { return { doms, jsEntries }; } -function emitHTMLFiles({ doms, jsEntries, stats, baseUrl, buildDirectory }) { +function emitHTMLFiles({ + doms, + jsEntries, + stats, baseUrl, + buildDirectory, + htmlMinifierOptions, +}) { const entrypoints = stats.toJson({ assets: false, hash: true }).entrypoints; //Now that webpack is done, modify the html files to point to the newly compiled resources @@ -88,19 +94,11 @@ function emitHTMLFiles({ doms, jsEntries, stats, baseUrl, buildDirectory }) { //And write our modified html files out to the destination for (const [htmlFile, dom] of Object.entries(doms)) { - const html = dom.serialize(); - // HTMLMinifier - // https://github.com/kangax/html-minifier#options-quick-reference - const htmlMinified = minify(html, { - collapseWhitespace: true, - removeComments: true, - removeEmptyAttributes: true, - removeRedundantAttributes: true, - removeScriptTypeAttributes: true, - removeStyleLinkTypeAttributes: true, - }); + const html = htmlMinifierOptions + ? minify(dom.serialize(), htmlMinifierOptions) + : dom.serialize(); - fs.writeFileSync(path.join(buildDirectory, htmlFile), htmlMinified); + fs.writeFileSync(path.join(buildDirectory, htmlFile), html); } } @@ -174,7 +172,22 @@ module.exports = function plugin(config, args) { if (!cssOutputPattern.endsWith(".css")) { throw new Error("Output Pattern for CSS must end in .css"); } - + + // Default options for HTMLMinifier + // https://github.com/kangax/html-minifier#options-quick-reference + let htmlMinifierOptions = { + collapseWhitespace: true, + removeComments: true, + removeEmptyAttributes: true, + removeRedundantAttributes: true, + removeScriptTypeAttributes: true, + removeStyleLinkTypeAttributes: true, + }; + + if (typeof args.htmlMinifierOptions !== 'undefined') { + htmlMinifierOptions = args.htmlMinifierOptions; + } + const manifest = typeof args.manifest === 'string' ? args.manifest @@ -368,7 +381,14 @@ module.exports = function plugin(config, args) { ); } - emitHTMLFiles({ doms, jsEntries, stats, baseUrl, buildDirectory }); + emitHTMLFiles({ + doms, + jsEntries, + stats, + baseUrl, + buildDirectory, + htmlMinifierOptions, + }); }, }; }; From 807d249bf4c469beb705d80ea9355e9ef0160565 Mon Sep 17 00:00:00 2001 From: Stefan Frede Date: Wed, 9 Sep 2020 21:42:25 +0200 Subject: [PATCH 3/5] Update plugins/plugin-webpack/README.md Co-authored-by: Gregor Martynus --- plugins/plugin-webpack/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugin-webpack/README.md b/plugins/plugin-webpack/README.md index 5e3bb87e59..015847ef61 100644 --- a/plugins/plugin-webpack/README.md +++ b/plugins/plugin-webpack/README.md @@ -27,7 +27,7 @@ npm install --save-dev @snowpack/plugin-webpack - `outputPattern: {css: string, js: string, assets: string}` - Set the URL for your final bundled files. This is where they will be written to disk in the `build/` directory. See Webpack's [`output.filename`](https://webpack.js.org/configuration/output/#outputfilename) documentation for examples of valid values. - `extendConfig: (config: WebpackConfig) => WebpackConfig` - extend your webpack config, see below. - `manifest: boolean | string` - Enable generating a manifest file. The default value is `false`, the default file name is `./asset-manifest.json` if setting manifest to `true`. The relative path is resolved from the output directory. -- `htmlMinifierOptions: boolean | object` - See below. +- `htmlMinifierOptions: boolean | object` - [See below](#minify-html). #### Extending The Default Webpack Config From 4604d7e63e07cad4f8c4fa7556cd46382668d4f4 Mon Sep 17 00:00:00 2001 From: Stefan Frede Date: Wed, 9 Sep 2020 23:13:32 +0200 Subject: [PATCH 4/5] Update plugins/plugin-webpack/plugin.js Co-authored-by: Gregor Martynus --- plugins/plugin-webpack/plugin.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/plugin-webpack/plugin.js b/plugins/plugin-webpack/plugin.js index 668176a261..adb9462010 100644 --- a/plugins/plugin-webpack/plugin.js +++ b/plugins/plugin-webpack/plugin.js @@ -175,7 +175,7 @@ module.exports = function plugin(config, args) { // Default options for HTMLMinifier // https://github.com/kangax/html-minifier#options-quick-reference - let htmlMinifierOptions = { + const defaultHtmlMinifierOptions = { collapseWhitespace: true, removeComments: true, removeEmptyAttributes: true, @@ -184,9 +184,7 @@ module.exports = function plugin(config, args) { removeStyleLinkTypeAttributes: true, }; - if (typeof args.htmlMinifierOptions !== 'undefined') { - htmlMinifierOptions = args.htmlMinifierOptions; - } + const htmlMinifierOptions = args.htmlMinifierOptions === false ? defaultHtmlMinifierOptions : Object.assign({}, defaultHtmlMinifierOptions, args.htmlMinifierOptions) const manifest = typeof args.manifest === 'string' From 9ab15629c7250a3e33b2843163cde89d832c97f2 Mon Sep 17 00:00:00 2001 From: Stefan Frede Date: Thu, 10 Sep 2020 04:03:27 +0200 Subject: [PATCH 5/5] Update plugins/plugin-webpack/plugin.js Co-authored-by: Gregor Martynus --- plugins/plugin-webpack/plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/plugin-webpack/plugin.js b/plugins/plugin-webpack/plugin.js index adb9462010..5f1af6be11 100644 --- a/plugins/plugin-webpack/plugin.js +++ b/plugins/plugin-webpack/plugin.js @@ -184,7 +184,7 @@ module.exports = function plugin(config, args) { removeStyleLinkTypeAttributes: true, }; - const htmlMinifierOptions = args.htmlMinifierOptions === false ? defaultHtmlMinifierOptions : Object.assign({}, defaultHtmlMinifierOptions, args.htmlMinifierOptions) + const htmlMinifierOptions = args.htmlMinifierOptions === false ? false : Object.assign({}, defaultHtmlMinifierOptions, args.htmlMinifierOptions) const manifest = typeof args.manifest === 'string'