Skip to main content

Build Pipeline Integration

As explained in the "Dynamic Analysis" chapter: for Dbux to work, it first needs to record JavaScript application behavior. To that end, your program must be instrumented with @dbux/babel-plugin (i.e.: you need to "babel your program" with @dbux/babel-plugin enabled).

Once running, the injected @dbux/runtime will send collected data to the runtime server.

Setup

First npm install or yarn add the necessary @dbux packages to the project you want to trace:

  • @dbux/babel-plugin
  • @dbux/runtime

Alternatively, simply install @dbux/cli. That will also install the other necessary dependencies.

Important: Make sure, that they match the version of Dbux VSCode Extension that you installed.

Config

You can find configuration options for the different tools in the "Tools and Configuration" chapter.

In addition to configuring the individual tools, you want to make sure you configure the module filter to trace the right files.

Node Applications

For Node applications that do not need bundling or building, refer to the Dbux CLI documentation.

Webpack

Example:

const makeInclude = require('@dbux/common-node/dist/filters/makeInclude').default;

const moduleFilterOptions = {
packageWhitelist: 'interestingPackage1,@interesting/package2',
// packageBlacklist: '',
fileBlacklist: '.*bad_file1\.js,.*/unwanted_dir1/.*'
};

// ...

module.exports = {
// ...
module: {
rules: [
// ...
{
test: /\.jsx?$/,
include: [
makeInclude(moduleFilterOptions)
],
use: {
loader: 'babel-loader',
options: {
/**
* Make sure, things work correctly, even if babeling (maybe previously unbabled) `node_modules`.
* @see https://github.com/webpack/webpack/issues/4039#issuecomment-419284940
*/
sourceType: 'unambiguous',
plugins: [
// other plugins, running **after** Dbux...
'@dbux/babel-plugin'
// other plugins, running **before** Dbux...
]
}
}
}
]
}
};

NOTE: For Dbux Practice projects, we use the (configurable/flexible/complicated) dbux.webpack.config.base.js.

Debugging Webpack w/ Dbux

Sometimes, you want to debug your webpack.config.js, or webpack, in general, using Dbux.

This is the command to do that:

npx dbux run ../node_modules/webpack-cli/bin/cli.js -- webpack args here
# or, if you want to debug webpack itself:
npx dbux run --pw=webpack.*,tapable,graceful-fs,enhanced-resolve ../node_modules/webpack-cli/bin/cli.js -- webpack args here

Keep an eye out for the following pitfalls:

  1. webpack adds a layer of @babel/register.
    • Because of that: webpack will run itself with the default babel config of the project. That usually does not affect anything, but there are buggy edge cases, and that's worth noting.
    • Also, if you run that webpack project with Dbux enabled, Dbux adds a second layer of @babel/register. So it will double up. That is generally not a problem, but attentions is warranted.
      • You want to make sure that webpack itself does not read a babel config which in turn adds @dbux/babel-plugin (which the project default babel config is likely to do).
      • NOTE: If you don't run webpack with Dbux enabled, it is all fine.
  2. webpack uses few libraries that themselves are very heavy on instrumentation. Since Dbux also instruments things, you end up having one instrumenter trying to instrument another. That can lead to problems.
    • If you want to understand the inner workings of webpack, we found the following whitelist to work quite well: --pw=webpack.*,tapable,graceful-fs,enhanced-resolve

Rollup

TODO: We have not tested this in a while. Need to verify and set it in stone. Test with the previously working Chart.js practice exercises (which uses Rollup).

Rollup requires use of @rollup/plugin-babel.

Example - something like this:

const makeInclude = require('@dbux/common-node/dist/filters/makeInclude').default;

const moduleFilterOptions = {
packageWhitelist: 'interestingPackage1,@interesting/package2',
// packageBlacklist: '',
fileBlacklist: '.*bad_file1\.js,.*/unwanted_dir1/.*'
};

const config = {
...
plugins: [
babel({
babelHelpers: 'inline',
filter: makeInclude(moduleFilterOptions),
/**
* WARNING: if not skipped, we saw some serious memory leaks (in 2020), but might already be fixed in 2022.
* TODO: we need to test this again.
*/
skipPreflightCheck: true
})
]
};

Storybook

TODO

Create-React-App

TODO: Clean this up

  1. install CRACO

    $ yarn add --dev @craco/craco
  2. Fix package.json to use craco instead of react-scripts:

    /* package.json */

    "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test"
    }
  3. Customize webpack config with CRACO: Example - something like this:

    // craco.config.js

    const { getLoaders, loaderByName } = require('@craco/craco');

    const dbuxOptions = {
    moduleFilter: {
    packageWhitelist: '.*',
    /**
    * NOTE: these libraries might run before dbux is initialized, so they must be blacklisted.
    * 1. Some hook themsleves into webpack.
    * 2. The later ones are polyfills (probably brought in by CRA) and their libraries; loaded when first requiring things, and before `@dbux/runtime`.
    */
    packageBlacklist: 'react-dev-utils,react-refresh,react-error-overlay,process,buffer,isarray,ieee754,base64-js',
    fileWhitelist: '.*',
    // we generally do not want to mess with production or webpack code
    fileBlacklist: '.*production.*,.*[wW]ebpack.*'
    }
    };

    module.exports = {
    webpack: {
    configure: (webpackConfig, { env, paths }) => {
    const { hasFoundAny, matches } = getLoaders(webpackConfig, loaderByName("babel-loader"));


    // // TODO: write output files (this won't work, `devServer` does not exit)
    // webpackConfig.devServer.devMiddleware.writeToDisk = true;

    // // exclude dbux from all rules
    // const reported = new Set();
    // webpackConfig.module.rules.forEach(rule => {
    // if (rule.exclude && !Array.isArray(rule.exclude)) {
    // rule.exclude = [rule.exclude];
    // }
    // if (!rule.exclude) {
    // rule.exclude = [];
    // }
    // rule.exclude.push((modulePath) => {
    // const exclude = modulePath.includes('@dbux');
    // if (!reported.has(modulePath)) {
    // reported.add(modulePath);
    // console.debug(`[WEBPACK]`, modulePath, !exclude);
    // }
    // return exclude;
    // });
    // });

    // add dbux to loader
    if (hasFoundAny) {
    matches.forEach(match => {
    const babelOptions = match.loader.options;
    if (!babelOptions.plugins) {
    babelOptions.plugins = [];
    }
    // NOTE: weird bug with a class having public fields (in @dbux/runtime) that Babel complains about
    babelOptions.plugins.push(['@babel/plugin-proposal-class-properties', { loose: true }]);
    babelOptions.plugins.push(['@dbux/babel-plugin', dbuxOptions]);
    });
    console.debug(`Added @dbux/babel-plugin to babel-loaders.`);
    }
    else {
    throw new Error(`Could not inject Dbux: 'babel-loader' found`);
    }

    return webpackConfig;
    }
    },
    };

Next.js

TODO

ng

TODO

Other Bundlers or Bundler Wrappers

TODO