diff --git a/.gitignore b/.gitignore index ad06a247..9b9dd599 100644 --- a/.gitignore +++ b/.gitignore @@ -5,9 +5,10 @@ _vendor/ hugo_stats.json .hugo_build.lock -# webpack artifacts -data/manifest.json +# webpack output static/assets/ +data/manifest.json +webpack_stats.json # node/npm/yarn node_modules/ diff --git a/.node-version b/.node-version new file mode 100644 index 00000000..07c142ff --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +16.13.1 diff --git a/.prettierignore b/.prettierignore index d9fd8654..67a151e7 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,8 +1,9 @@ -# Hugo stuff that doesn't play well with Prettier +# Hugo/Webpack stuff that doesn't play well with Prettier assets/**/vendor/ layouts/ static/ hugo_stats.json +webpack_stats.json data/manifest.json # output from Hugo @@ -15,4 +16,4 @@ _vendor/ .vercel/ .lighthouseci/ .vscode/ -content/notes/dark-mode/example/ +/content/notes/dark-mode/example/ diff --git a/gulpfile.js b/gulpfile.js index 50618201..b398d52a 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,4 +1,6 @@ import "dotenv/config"; +import path from "path"; +import { fileURLToPath } from "url"; import gulp from "gulp"; import { task as execa } from "gulp-execa"; import cache from "gulp-cache"; @@ -12,6 +14,9 @@ import imageminPngquant from "imagemin-pngquant"; import imageminGifsicle from "imagemin-gifsicle"; import imageminSvgo from "imagemin-svgo"; +// https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c#what-do-i-use-instead-of-__dirname-and-__filename +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + gulp.task( "default", gulp.series( @@ -33,10 +38,27 @@ gulp.task( ) ); +gulp.task( + "analyze", + gulp.series( + clean, + npx("webpack", ["--mode", "production"]), + npx("webpack-bundle-analyzer", [ + // https://github.com/webpack-contrib/webpack-bundle-analyzer#usage-as-a-cli-utility + path.resolve(__dirname, "webpack_stats.json"), // path to webpack-generated JSON stats file + path.resolve(__dirname, "static/assets/"), // path to finalized bundles + "--mode", + "server", + "--default-sizes", + "gzip", + ]) + ) +); + gulp.task("clean", clean); function clean() { - return del(["public/", "builds/", "_vendor/", "static/assets/"]); + return del(["public/", "builds/", "_vendor/", "static/assets/", "webpack_stats.json"]); } function optimizeHtml() { diff --git a/package.json b/package.json index 106eec9a..7db06574 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "build": "gulp", "clean": "gulp clean", "start": "gulp serve", + "analyze-bundle": "gulp analyze", "lint": "run-s lint:**", "lint:js": "eslint .", "lint:css": "stylelint '**/*.{css,scss}'", @@ -105,6 +106,7 @@ "web-vitals": "^2.1.2", "webpack": "^5.64.4", "webpack-assets-manifest": "^5.0.6", + "webpack-bundle-analyzer": "^4.5.0", "webpack-cli": "^4.9.1", "webpack-dev-server": "^4.6.0" }, @@ -126,6 +128,7 @@ ] }, "volta": { - "node": "16.13.0" + "node": "16.13.1", + "yarn": "1.22.17" } } diff --git a/webpack.config.js b/webpack.config.js index 345ade49..04b51d7f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,6 +7,7 @@ import { LicenseWebpackPlugin as LicensePlugin } from "license-webpack-plugin"; import MiniCssExtractPlugin from "mini-css-extract-plugin"; import CssMinimizerPlugin from "css-minimizer-webpack-plugin"; import TerserPlugin from "terser-webpack-plugin"; +import { BundleAnalyzerPlugin } from "webpack-bundle-analyzer"; // PostCSS stuff: import autoprefixer from "autoprefixer"; @@ -100,6 +101,11 @@ export default (env, argv) => { if (entry.key.startsWith("emoji/") || entry.key.endsWith(".map")) return false; }, }), + new BundleAnalyzerPlugin({ + analyzerMode: "disabled", // this is done in gulp via `yarn analyze-bundle` instead + generateStatsFile: true, + statsFilename: path.resolve(__dirname, "webpack_stats.json"), + }), ], module: { rules: [ diff --git a/yarn.lock b/yarn.lock index 13fb2014..64029671 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1085,6 +1085,11 @@ dependencies: "@octokit/openapi-types" "^11.2.0" +"@polka/url@^1.0.0-next.20": + version "1.0.0-next.21" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" + integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== + "@primer/octicons-react@^16.1.1": version "16.1.1" resolved "https://registry.yarnpkg.com/@primer/octicons-react/-/octicons-react-16.1.1.tgz#6a9eaffbbf46cb44d344a37a5ff2384973b82d3f" @@ -1516,7 +1521,12 @@ acorn-jsx@^5.3.1: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.4.1, acorn@^8.6.0: +acorn-walk@^8.0.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.0.4, acorn@^8.4.1, acorn@^8.6.0: version "8.6.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895" integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw== @@ -3412,6 +3422,11 @@ duplexer3@^0.1.4: resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= +duplexer@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" @@ -4883,6 +4898,13 @@ gulplog@^1.0.0: dependencies: glogg "^1.0.0" +gzip-size@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" + integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== + dependencies: + duplexer "^0.1.2" + handle-thing@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" @@ -6244,7 +6266,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.14, lodash@^4.17.15: +lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -6670,6 +6692,11 @@ mozjpeg@^7.0.0: bin-build "^3.0.0" bin-wrapper "^4.0.0" +mrmime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.0.tgz#14d387f0585a5233d291baba339b063752a2398b" + integrity sha512-a70zx7zFfVO7XpnQ2IX1Myh9yY4UYvfld/dikWRnsXxbyvMcfz+u6UfgNAtH+k2QqtJuzVpv6eLTx1G2+WKZbQ== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -7079,6 +7106,11 @@ open@^8.0.9: is-docker "^2.1.1" is-wsl "^2.2.0" +opener@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" + integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== + optionator@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" @@ -8751,6 +8783,15 @@ simple-git-hooks@^2.7.0: resolved "https://registry.yarnpkg.com/simple-git-hooks/-/simple-git-hooks-2.7.0.tgz#121a5c3023663b8abcc5648c8bfe8619dc263705" integrity sha512-nQe6ASMO9zn5/htIrU37xEIHGr9E6wikXelLbOeTcfsX2O++DHaVug7RSQoq+kO7DvZTH37WA5gW49hN9HTDmQ== +sirv@^1.0.7: + version "1.0.19" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" + integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== + dependencies: + "@polka/url" "^1.0.0-next.20" + mrmime "^1.0.0" + totalist "^1.0.0" + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -9638,6 +9679,11 @@ token-types@^4.1.1: "@tokenizer/token" "^0.3.0" ieee754 "^1.2.1" +totalist@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" + integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -10118,6 +10164,21 @@ webpack-assets-manifest@^5.0.6: schema-utils "^3.0" tapable "^2.0" +webpack-bundle-analyzer@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz#1b0eea2947e73528754a6f9af3e91b2b6e0f79d5" + integrity sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ== + dependencies: + acorn "^8.0.4" + acorn-walk "^8.0.0" + chalk "^4.1.0" + commander "^7.2.0" + gzip-size "^6.0.0" + lodash "^4.17.20" + opener "^1.5.2" + sirv "^1.0.7" + ws "^7.3.1" + webpack-cli@^4.9.1: version "4.9.1" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.9.1.tgz#b64be825e2d1b130f285c314caa3b1ba9a4632b3" @@ -10331,6 +10392,11 @@ write-file-atomic@^3.0.3: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +ws@^7.3.1: + version "7.5.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" + integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== + ws@^8.1.0: version "8.3.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.3.0.tgz#7185e252c8973a60d57170175ff55fdbd116070d"