cockpit-project / cockpit

Cockpit is a web-based graphical interface for servers.
http://www.cockpit-project.org/
GNU Lesser General Public License v2.1
10.64k stars 1.07k forks source link

Analyze Cockpit bundle sizes #18267

Closed jelly closed 1 week ago

jelly commented 1 year ago

Add the webpack bundle analyzer to package.json and the webpack config and run ./tools/webpack-make $page.

diff --git a/package.json b/package.json
index 7bbf709ac..5d3aaf0d2 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
     "xterm-addon-canvas": "0.3.0"
   },
   "devDependencies": {
+    "webpack-bundle-analyzer": "4.7.0",
     "@babel/core": "^7.9.0",
     "@babel/eslint-parser": "^7.13.14",
     "@babel/preset-env": "^7.9.0",
diff --git a/webpack.config.js b/webpack.config.js
index c839975df..e8cd9434e 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -250,6 +250,7 @@ const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
 const ESLintPlugin = require('eslint-webpack-plugin');
 const StylelintPlugin = require('stylelint-webpack-plugin');
 const CockpitPoPlugin = require("./pkg/lib/cockpit-po-plugin");
+const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

 /* These can be overridden, typically from the Makefile.am */
 const srcdir = process.env.SRCDIR || __dirname;
@@ -342,6 +343,7 @@ const plugins = [
         // login page does not have cockpit.js, but reads window.cockpit_po
         wrapper: (section === 'static/') ? 'window.cockpit_po = PO_DATA;' : undefined,
     }),
+    new BundleAnalyzerPlugin()
 ];

 if (production) {

Biggest modules:

systemd/services.js (3.6 MB)

kdump (1.69 MB)

users 3.3MB

storaged 3.8 MB

Note: the bundle does include test-util.js. for storaged/kdump

jelly commented 1 year ago

We could, only import the locales which are required.

KKoukiou commented 1 year ago

By doing the following changes in the build.js one can generate a meta.json file

[kkoukiou@sequioa cockpit]$ git diff
diff --git build.js build.js
index d20324070..60059d8ed 100755
--- build.js
+++ build.js
@@ -225,6 +225,7 @@ async function build() {
     } else {
         // with native esbuild, build everything in one go, that's fastest
         const pkgContext = await esbuild.context({
+            metafile: true,
             ...pkgOptions,
             entryPoints,
             plugins: [...pkgFirstPlugins, ...pkgPlugins, ...pkgLastPlugins],
@@ -241,7 +242,8 @@ async function build() {
         });

         try {
-            await Promise.all([pkgContext.rebuild(), qunitContext.rebuild()]);
+            const result = await Promise.all([pkgContext.rebuild(), qunitContext.rebuild()]);
+            fs.writeFileSync('meta.json', JSON.stringify(result[0].metafile));
         } catch (e) {
             if (!args.watch)
                 process.exit(1);

Which can be then fed to https://esbuild.github.io/analyze/

esbuild-an-2 esbuild-anal-1

martinpitt commented 1 year ago

@KKoukiou: Nice! Do you want to add that as a CLI option to ./build.js? Or is this cheap enough that we could just always do that?

KKoukiou commented 1 year ago

@martinpitt I definitely want to introduce it as a CLI option and I want to introduce some check for bundle size changes, so if bundle size increases by >5% there should be an error in CI.

jelly commented 2 weeks ago

In our cockpit plugins we now generate an esbuild metadata file which can be used to analyze the bundle size https://github.com/cockpit-project/starter-kit/commit/49c368809e7667f066f13605286178b4ab75b78f