pahen / madge

Create graphs from your CommonJS, AMD or ES6 module dependencies
MIT License
9.07k stars 317 forks source link

How to use with Next.js webpack config? #204

Open CaitlinWeb opened 5 years ago

CaitlinWeb commented 5 years ago

I would like to list/graph dependencies for a Next.js project. Next.js comes with Webpack and Babel. You can also extend their configurations.

Webpack is extended with a next.config.js file and Babel with a .babelrc file.

Here is my next.config.js with irrelevant bits removed:

const withCSS = require('@zeit/next-css');
const webpack = require('webpack');

module.exports = withCSS({
    webpack: function(config) {
        // Load static files
        config.module.rules.push({
            test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
            use: {
                loader: 'url-loader',
                options: {
                    limit: 100000,
                    name: '[name].[ext]',
                },
            },
        });

        return config;
    },
});

Here's the relevant parts of my .babelrc:

{
    "presets": ["next/babel"],
    "plugins": [
        [
            "module-resolver",
            {
                "root": ["./"],
                "alias": {
                    "api": "./api",
                    "components": "./components",
                    "elements": "./components/elements",
                    "layout": "./components/layout",
                }
            }
        ]
    ]
}

Problem

There is no central "app.js" but rather pages (located in pages/). Running madge on a page results in lots of warnings for ignored files or directories. Here's a debug for one of my pages that has dependencies in components/ (with filepaths removed):

- Finding files  madge using src paths [ 'filepath\\pages\\login.js' ] +7ms
  madge using config { baseDir: null, excludeRegExp: false, fileExtensions: [ 'js' ], includeNpm: false, requireConfig: null, webpackConfig: null, tsConfig: null, rankdir: 'LR', layout: 'dot', fontName: 'Arial', fontSize: '14px', backgroundColor: '#111111', nodeColor: '#c6c5fe', nodeShape: 'box', nodeStyle: 'rounded', noDependencyColor: '#cfffac', cyclicNodeColor: '#ff6c60', edgeColor: '#757575', graphVizOptions: false, graphVizPath: false, dependencyFilter: [Function], debug: true, version: [Function], color: true, spinner: true } +2ms
  madge using base directory filepath/pages +2ms
  tree given filename: filepath\pages\login.js +0ms
  tree resolved filename: filepath\pages\login.js +0ms
  tree visited:  {} +1ms
  tree traversing filepath\pages\login.js +0ms
  precinct paperwork: invoking precinct +0ms
  precinct options given:  { includeCore: false } +0ms
  precinct we assume this is JS +0ms
  precinct parsed the file content into an ast +27ms
  precinct module type:  es6 +2ms
  tree extracted 8 dependencies:  [ 'react',
  'classnames',
  'next/head',
  'formik',
  'style/main.css',
  'api/auth',
  'components',
  'api/validations' ] +34ms
  cabinet Given filename: filepath\pages\login.js +0ms
  cabinet which has the extension: .js +1ms
  cabinet found a resolver for .js +0ms
  cabinet reusing the given ast +1ms
  cabinet using commonjs resolver for es6 +0ms
  cabinet adding filepath\pages\node_modules to the require resolution paths +6ms
  cabinet resolved path: filepath\node_modules\react\index.js +4ms
  cabinet resolved path for react: filepath\node_modules\react\index.js +1ms
  cabinet Given filename: filepath\pages\login.js +0ms
  cabinet which has the extension: .js +0ms
  cabinet found a resolver for .js +0ms
  cabinet reusing the given ast +1ms
  cabinet using commonjs resolver for es6 +0ms
  cabinet adding filepath\pages\node_modules to the require resolution paths +0ms
  cabinet resolved path: filepath\node_modules\classnames\index.js +9ms
  cabinet resolved path for classnames: filepath\node_modules\classnames\index.js +0ms
  cabinet Given filename: filepath\pages\login.js +1ms
  cabinet which has the extension: .js +0ms
  cabinet found a resolver for .js +0ms
  cabinet reusing the given ast +0ms
  cabinet using commonjs resolver for es6 +0ms
  cabinet adding filepath\pages\node_modules to the require resolution paths +1ms
  cabinet resolved path: filepath\node_modules\next\head.js +2ms
  cabinet resolved path for next/head: filepath\node_modules\next\head.js +0ms
  cabinet Given filename: filepath\pages\login.js +0ms
  cabinet which has the extension: .js +1ms
  cabinet found a resolver for .js +0ms
  cabinet reusing the given ast +0ms
  cabinet using commonjs resolver for es6 +0ms
  cabinet adding filepath\pages\node_modules to the require resolution paths +0ms
  cabinet resolved path: filepath\node_modules\formik\dist\index.js +5ms
  cabinet resolved path for formik: filepath\node_modules\formik\dist\index.js +2ms
  cabinet Given filename: filepath\pages\login.js +0ms
  cabinet which has the extension: .js +0ms
  cabinet found a resolver for .js +1ms
  cabinet reusing the given ast +0ms
  cabinet using commonjs resolver for es6 +0ms
  cabinet adding filepath\pages\node_modules to the require resolution paths +1ms
  cabinet could not resolve style/main.css +5ms
  cabinet resolved path for style/main.css:  +0ms
  tree skipping an empty filepath resolution for partial: style/main.css +43ms
  cabinet Given filename: filepath\pages\login.js +1ms
  cabinet which has the extension: .js +0ms
  cabinet found a resolver for .js +1ms
  cabinet reusing the given ast +0ms
  cabinet using commonjs resolver for es6 +0ms
  cabinet adding filepath\pages\node_modules to the require resolution paths +0ms
  cabinet could not resolve api/auth +5ms
  cabinet resolved path for api/auth:  +2ms
  tree skipping an empty filepath resolution for partial: api/auth +8ms
  cabinet Given filename: filepath\pages\login.js +0ms
  cabinet which has the extension: .js +0ms
  cabinet found a resolver for .js +1ms
  cabinet reusing the given ast +0ms
  cabinet using commonjs resolver for es6 +0ms
  cabinet adding filepath\pages\node_modules to the require resolution paths +0ms
  cabinet could not resolve components +5ms
  cabinet resolved path for components:  +0ms
  tree skipping an empty filepath resolution for partial: components +6ms
  cabinet Given filename: filepath\pages\login.js +0ms
  cabinet which has the extension: .js +0ms
  cabinet found a resolver for .js +1ms
  cabinet reusing the given ast +0ms
  cabinet using commonjs resolver for es6 +0ms
  cabinet adding filepath\pages\node_modules to the require resolution paths +1ms
  cabinet could not resolve api/validations +6ms
  cabinet resolved path for api/validations:  +1ms
  tree skipping an empty filepath resolution for partial: api/validations +10ms
  tree cabinet-resolved all dependencies:  [ 'filepath\\node_modules\\react\\index.js',
  'filepath\\node_modules\\classnames\\index.js',
  'filepath\\node_modules\\next\\head.js',
  'filepath\\node_modules\\formik\\dist\\index.js' ] +0ms
  tree using filter function to filter out dependencies +0ms
  tree unfiltered number of dependencies: 4 +1ms
\ ./login.js  tree filtered number of dependencies: 0 +3ms
  tree traversal complete {} +0ms
  tree deduped list of nonExistent partials:  [ 'style/main.css', 'api/auth', 'components', 'api/validations' ] +0ms
  tree object form of results requested +0ms
  tree final tree { 'filepath\\pages\\login.js': {} } +1ms
Processed 1 file (519ms) (4 warnings)

login.js

✖ Skipped 4 files

style/main.css
api/auth
components
api/validations

I think the relevant part is "cabinet could not resolve components". Why does this happen and how can I use Madge for Next.js pages/apps?

thoo1 commented 3 years ago

Were you able to solve this? I haven't tried what I'm about to suggest but.. There seems to be a config option in madge called webpackConfig. This should point to a webpack config. I would try extracting the webpack config that is in the next.config.js into its own file. And then import that config in next.config.js and also point to that config in madge so you can use madge to detect circular references

CaitlinWeb commented 3 years ago

Were you able to solve this?

I'm no longer working on a Next.js project and, no, I never solved this. I suspect you're right about using webpackConfig with the next.config.js, though.

xveganxxxedgex commented 7 months ago

I know this is an old thread, but in case anyone else comes across this, doing the suggestions from the previous comments seems to work as expected for me:

next.config.js:

const nextConfig = {
  webpack: config => {
      madge("src", {
          tsConfig: "./tsconfig.json",
          webpackConfig: config,
          fileExtensions: ["js", "tsx", "ts"],
    }).then(res => console.log(res.circular()));

    return config;
  }
}