diff --git a/client/configuration/webpack/cspHashPlugin.js b/client/configuration/webpack/cspHashPlugin.js index d219dc82..fa532ef6 100644 --- a/client/configuration/webpack/cspHashPlugin.js +++ b/client/configuration/webpack/cspHashPlugin.js @@ -14,13 +14,14 @@ class CspHashPlugin { (data, cb) => { const { filename } = this.opts; + const $ = cheerio.load(data.html, { decodeEntities: false }); + if (filename) { - const $ = cheerio.load(data.html, { decodeEntities: false }); const results = {}; - results["script-hashes"] = $("script:not([src])") + results["script-hashes"] = $("script:not([src]):not([no-csp-hash])") .map((i, elmt) => this.digest($(elmt).html())) .get(); - results["style-hashes"] = $("style:not([href])") + results["style-hashes"] = $("style:not([href]):not([no-csp-hash])") .map((i, elmt) => this.digest($(elmt).html())) .get(); @@ -31,6 +32,18 @@ class CspHashPlugin { }; } + // remove no-csp-hash attributes + let foundOne = false; + $("script[no-csp-hash]").each((i, elmt) => { + $(elmt).removeAttr("no-csp-hash"); + foundOne = true; + }); + $("style[no-csp-hash]").each((i, elmt) => { + $(elmt).removeAttr("no-csp-hash"); + foundOne = true; + }); + if (foundOne) data.html = $.html(); + // Tell webpack to move on cb(null, data); } diff --git a/client/configuration/webpack/webpack.config.prod.js b/client/configuration/webpack/webpack.config.prod.js index 06e7b08c..8ac2da94 100644 --- a/client/configuration/webpack/webpack.config.prod.js +++ b/client/configuration/webpack/webpack.config.prod.js @@ -5,6 +5,10 @@ const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const HtmlWebpackInlineSourcePlugin = require("html-webpack-inline-source-plugin"); const FaviconsWebpackPlugin = require("favicons-webpack-plugin"); const { CleanWebpackPlugin } = require("clean-webpack-plugin"); +const TerserJSPlugin = require("terser-webpack-plugin"); +const CleanCss = require("clean-css"); +const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); + const CspHashPlugin = require("./cspHashPlugin"); const src = path.resolve("src"); @@ -21,9 +25,19 @@ module.exports = { cache: false, entry: ["./src/index.js"], output: { + filename: "static/[name]-[contenthash].js", path: path.resolve("build"), publicPath, }, + optimization: { + minimize: true, + minimizer: [ + new TerserJSPlugin({}), + new OptimizeCSSAssetsPlugin({ + cssProcessor: CleanCss, + }), + ], + }, module: { rules: [ { @@ -52,15 +66,7 @@ module.exports = { { test: /index\.css$/, include: [path.resolve(src, "index.css")], - use: [ - MiniCssExtractPlugin.loader, - { - loader: "css-loader", - options: { - importLoaders: 1, - }, - }, - ], + use: [MiniCssExtractPlugin.loader, "css-loader"], }, { test: /\.json$/, @@ -78,10 +84,9 @@ module.exports = { }, plugins: [ new HtmlWebpackPlugin({ - inject: "body", filename: "index.html", template: path.resolve("index_template.html"), - inlineSource: ".(js|css)$", + decodeEntities: false, minify: { removeComments: true, collapseWhitespace: true, @@ -115,8 +120,9 @@ module.exports = { }, }, }), - new HtmlWebpackInlineSourcePlugin(HtmlWebpackPlugin), - new MiniCssExtractPlugin(), + new MiniCssExtractPlugin({ + filename: "static/[name]-[contenthash].css", + }), new CspHashPlugin({ filename: "csp-hashes.json", }), diff --git a/client/index_template.html b/client/index_template.html index 83082374..f6162afb 100644 --- a/client/index_template.html +++ b/client/index_template.html @@ -52,10 +52,11 @@
{% for script in SCRIPTS %} - {% endfor %} {% for ils in INLINE_SCRIPTS %} - + {% endfor %} + + {% for ils in INLINE_SCRIPTS %} + + {% endfor %}