Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚧 WIP: bundle analysis #61

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion lib/bundle/bundler.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
let rollupAnalyzer = require("rollup-plugin-analyzer").plugin;
let rollup = require("rollup");

module.exports = function generateBundle(entryPoint, target, config, cache) {
let { readConfig, writeConfig } = config;
let { readConfig, writeConfig, reporting } = config;
let options = Object.assign({}, readConfig, {
input: entryPoint,
cache
});

if(reporting) {
options.plugins.push(rollupAnalyzer({
root: reporting.referenceDir,
// TODO: support for options: `limit`, `filter`, `showExports`, `hideDeps`
onAnalysis: res => void reporting.report({
size: res.bundleSize,
originalSize: res.bundleOrigSize,
reduction: res.bundleReduction
})
}));
}

return rollup.rollup(options).
then(bundle => {
let modules = bundle.modules.reduce(collectModulePaths, new Set());
Expand Down
33 changes: 30 additions & 3 deletions lib/bundle/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,49 @@ let generateBundle = require("./bundler");
let generateConfig = require("./config");
let { generateError } = require("../util");
let SerializedRunner = require("faucet-pipeline/lib/util/runner");
let { repr } = require("faucet-pipeline/lib/util");
let path = require("path");

let DEFAULTS = {
format: "iife"
config: {
format: "iife"
},
reporting: {
threshold: 100000 * 1024 // ~100 kB
}
};

module.exports = class Bundle {
constructor(entryPoint, target, config, { browsers, resolvePath }) {
constructor(entryPoint, target, config, { browsers, referenceDir, resolvePath }) {
this.entryPoint = entryPoint;
this.target = target;

config = Object.assign({}, DEFAULTS, config);
config = Object.assign({}, DEFAULTS.config, config);
if(config.fingerprint !== undefined) {
this.fingerprint = config.fingerprint;
delete config.fingerprint;
}
this._config = generateConfig(config, { browsers, resolvePath });

let { reporting } = config;
if(reporting !== false) {
let { threshold } = Object.assign({}, DEFAULTS.reporting, reporting);
let bundle = repr(path.relative(referenceDir, target), false);
this._config.reporting = {
referenceDir,
report: ({ size, originalSize, reduction }) => {
let b2kb = i => `${Math.round(i / 1024)} kB`;
console.error(`${bundle}: ${b2kb(originalSize)} β†’ ` +
`${b2kb(size)} (Ξ” ${Math.round(reduction)} %)`);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd consider this a placeholder for now, until we've figured out detailed reporting (see above). It sort of duplicates AssetManager#writeFile's reporting.

if(size > threshold) {
console.error("⚠️ this bundle looks to be fairly big - " +
"you might want to double-check whether " +
"that's intended and consider performance " +
"implications for your users: " + bundle);
}
}
};
}
}

// recompiles the bundle if its dependency graph includes any of the given files
Expand Down
15 changes: 4 additions & 11 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

let Bundle = require("./bundle");
let { abort, repr } = require("faucet-pipeline/lib/util");
let path = require("path");

module.exports = (config, assetManager, { watcher, browsers, compact } = {}) => {
let bundles = config.map(bundleConfig => {
// NB: bundle-specific configuration can override global options
bundleConfig = Object.assign({ compact }, bundleConfig);
return makeBundle(bundleConfig, assetManager.resolvePath, { browsers });
return makeBundle(bundleConfig, assetManager, { browsers });
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not happy with the increasing amount of context we have to pass through in situations like this - not sure that can be avoided though. (In this case, we need assertManager.referenceDir so we can pass it to rollup-plugin-analyzer, eventually, via Bundle β†’ generateBundle; it all seems a little too convoluted.)

});

let res = bundles.map(bundle => {
Expand Down Expand Up @@ -38,13 +37,6 @@ module.exports = (config, assetManager, { watcher, browsers, compact } = {}) =>

function makeWriter(bundle, assetManager, { fingerprint } = {}) {
return ({ code, error }) => {
if(code.length > 100000) { // ~100 kB -- XXX: arbitrary -- TODO: configurable
console.error("⚠️ this bundle looks to be fairly big, you might " +
"want to double-check whether that's intended and " +
"consider performance implications for your users:\n " +
path.relative(assetManager.referenceDir, bundle.target));
}

let options = { error };
if(fingerprint !== undefined) {
options.fingerprint = fingerprint;
Expand All @@ -53,7 +45,7 @@ function makeWriter(bundle, assetManager, { fingerprint } = {}) {
};
}

function makeBundle(config, resolvePath, { browsers }) {
function makeBundle(config, { referenceDir, resolvePath }, { browsers }) {
// dissect configuration for constructor
config = Object.assign({}, config);
let [entryPoint, target] = extract(config, "source", "target");
Expand All @@ -64,7 +56,8 @@ function makeBundle(config, resolvePath, { browsers }) {

entryPoint = resolvePath(entryPoint);
target = resolvePath(target, { enforceRelative: true });
return new Bundle(entryPoint, target, config, { browsers, resolvePath });
return new Bundle(entryPoint, target, config,
{ browsers, referenceDir, resolvePath });
}

// removes properties from object, returning their respective values
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@
"dependencies": {
"faucet-pipeline": "~1.0.0-rc.7",
"rollup": "~0.62.0",
"rollup-plugin-analyzer": "^2.1.0",
"rollup-plugin-cleanup": "~3.0.0",
"rollup-plugin-commonjs": "~9.1.3",
"rollup-plugin-node-resolve": "~3.3.0"
},
"devDependencies": {
"eslint-config-fnd-jsx": "^1.4.0",
"eslint-config-fnd-jsx": "^1.6.0",
"faucet-pipeline-esnext": "file:pkg/faucet-pipeline-esnext",
"faucet-pipeline-jsx": "file:pkg/faucet-pipeline-jsx",
"faucet-pipeline-typescript": "file:pkg/faucet-pipeline-typescript",
Expand Down
5 changes: 4 additions & 1 deletion test/cli/test_custom_config/assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ let path = require("path");
module.exports = {
js: [{
source: "./index.js",
target: "./dist/bundle.js"
target: "./dist/bundle.js",
reporting: {
threshold: 100
}
}],
plugins: {
js: path.resolve(__dirname, "../../..")
Expand Down
18 changes: 17 additions & 1 deletion test/cli/test_custom_config/expected.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@ if(typeof global === "undefined" && typeof window !== "undefined") {
window.global = window;
}

// N/A
// lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
// tempor incididunt ut labore et dolore magna aliqua
// ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
// aliquip ex ea commodo consequat
// duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
// eu fugiat nulla pariatur
// excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
// deserunt mollit anim id est laborum
//
// lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
// tempor incididunt ut labore et dolore magna aliqua
// ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
// aliquip ex ea commodo consequat
// duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
// eu fugiat nulla pariatur
// excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
// deserunt mollit anim id est laborum

}());
18 changes: 17 additions & 1 deletion test/cli/test_custom_config/index.js
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
// N/A
// lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
// tempor incididunt ut labore et dolore magna aliqua
// ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
// aliquip ex ea commodo consequat
// duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
// eu fugiat nulla pariatur
// excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
// deserunt mollit anim id est laborum
//
// lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
// tempor incididunt ut labore et dolore magna aliqua
// ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
// aliquip ex ea commodo consequat
// duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
// eu fugiat nulla pariatur
// excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia
// deserunt mollit anim id est laborum