Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I get the dependency tree before webpack starts to build?

Does webpack expose the dependency tree before the build is sealed? I have searched all through the compiler instance, but have found nothing about a dependency tree. It seems that there should be one hidden in that object somewhere, because webpack has to know what this tree is in order to later output the stats.json.

I've tried using the dependency-tree npm package, but it doesn't support some things I have in my webpack config, so the tree is incomplete.

like image 994
KevBot Avatar asked Nov 28 '17 20:11

KevBot


People also ask

How long should webpack build take?

We use babel and TailwindCSS. Using simple methods, I discovered that CSS and JS take about the same time to build. Benchmark: Webpack build took 64 seconds, whole build took 91 seconds.

Does webpack include dependencies in bundle?

Webpack builds a dependency graph used internally Now all modules that are used in your app are included in the dependency graph. Your project have many installed dependencies in the node_modules folder that should not be included in your client-side JavaScript production bundle.

Why is webpack build so slow?

Over the past eight years, webpack has become increasingly powerful. However, due to the additional packaging process, the building speed is getting slower as the project grows. As a result, each startup takes dozens of seconds (or minutes), followed by a round of build optimization.

How do I reduce webpack build time?

Use the uglifyjs-webpack-plugin v1 It is one of the main methods used to reduce the build time. But this modification process itself can take a considerable amount of time as the project size increases. So if your project is scaling, you can use uglifyjs-webpack-plugin v1 to optimize the modification time.


1 Answers

TL;DR: Yes, you can access the dependency tree just before it's being sealed.

To do this, add the following code to your webpack.config.js:

class AccessDependenciesPlugin {
  apply (compiler) {
    compiler.hooks.compilation.tap('AccessDependenciesPlugin', compilation => {
      compilation.hooks.finishModules.tap('AccessDependenciesPlugin', modules => {
        /*
        |---------------------------------------------------
        | Here we go, `modules` is what we're looking for!
        |---------------------------------------------------
        */
      })
    })
  }
}


module.exports = {
  // ...
  plugins: [
    new AccessDependenciesPlugin()
  ]
}

For more details, see the explanation below.


The hook we're looking for

We can access the pre-sealed dependency tree with the finishModules compilation hook.


How do we know?

Since the webpack hook docs are very minimal (to say the least), we had to read webpack source code to be sure it's what we're looking for:

The last thing the compiler does before sealing the dependency tree is "finishing" it.

  • This happens in Compiler.js, line 492

Finishing the dependency tree offers a hook on the compilation.

  • finishModules hook in the webpack docs
  • The hook is being called in Compilation.js, line 828

Code example

We create a plugin called AccessDependenciesPlugin:

// Basic webpack plugin structure
class AccessDependenciesPlugin {
  apply (compiler) {

  }
}

To use a compilation hook, we need to get access to the compilation object first. We do that with the compilation hook:

class AccessDependenciesPlugin {
  apply (compiler) {
    compiler.hooks.compilation.tap('AccessDependenciesPlugin', compilation => {
      // We have access to the compilation now!
    })
  }
}

Now we tap the finishModules hook of the compilation:

class AccessDependenciesPlugin {
  apply (compiler) {
    compiler.hooks.compilation.tap('AccessDependenciesPlugin', compilation => {
      compilation.hooks.finishModules.tap('AccessDependenciesPlugin', modules => {
        // Here we go, `modules` is what we're looking for!
      })
    })
  }
}

The modules parameter of that hook is an array of webpack modules with their dependencies and basically all other data available about them.

Last but not least, we need to add the plugin to our webpack configuration:

module.exports = {
  plugins: [
    new AccessDependenciesPlugin()
  ]
}

And we're done. 🎉


Hope this helps.


Bonus Content: webpack 3

Per request in the comments: Here's the version of the AccessDependenciesPlugin for the legacy plugin system of webpack 3.

class AccessDependenciesPlugin {
  apply (compiler) {
    compiler.plugin('compilation', compilation => {
      compilation.plugin('finish-modules', modules => {
        /*
        |---------------------------------------------------
        | Here we go, `modules` is what we're looking for!
        |---------------------------------------------------
        */
      })
    })
  }
}
like image 194
Loilo Avatar answered Oct 05 '22 06:10

Loilo