django-webpack / webpack-bundle-tracker

Spits out some stats about webpack compilation process to a file
MIT License
268 stars 107 forks source link

BundleTracker raises errors as it tries to re-create existing folders #73

Closed harpunius closed 3 years ago

harpunius commented 4 years ago

Hello,

I followed the rather simple tutorial here https://owais.lone.pw/blog/webpack-plus-reactjs-and-django/ (as referred to in https://github.com/owais/django-webpack-loader). I'm using version 1.0.0-alpha.1

However, my stats file always ended up corrupt (stuck on status: "compile") when building using webpack --watch without error. When building without the --watch argument, I got the error below.

Error: EEXIST: file already exists, mkdir '/home/tso/Projects/bike/client/build'
    at Object.fs.mkdirSync (fs.js:885:18)
    at BundleTrackerPlugin._writeOutput (/home/tso/Projects/bike/client/node_modules/webpack-bundle-tracker/lib/index.js:79:8)
    at BundleTrackerPlugin._handleDone (/home/tso/Projects/bike/client/node_modules/webpack-bundle-tracker/lib/index.js:154:10)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/home/tso/Projects/bike/client/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:9:1)
    at AsyncSeriesHook.lazyCompileHook (/home/tso/Projects/bike/client/node_modules/tapable/lib/Hook.js:154:20)
    at emitRecords.err (/home/tso/Projects/bike/client/node_modules/webpack/lib/Compiler.js:304:22)
    at Compiler.emitRecords (/home/tso/Projects/bike/client/node_modules/webpack/lib/Compiler.js:499:39)
    at emitAssets.err (/home/tso/Projects/bike/client/node_modules/webpack/lib/Compiler.js:298:10)
    at hooks.afterEmit.callAsync.err (/home/tso/Projects/bike/client/node_modules/webpack/lib/Compiler.js:485:14)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/home/tso/Projects/bike/client/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (/home/tso/Projects/bike/client/node_modules/tapable/lib/Hook.js:154:20)
    at asyncLib.forEachLimit.err (/home/tso/Projects/bike/client/node_modules/webpack/lib/Compiler.js:482:27)
    at /home/tso/Projects/bike/client/node_modules/neo-async/async.js:2818:7
    at done (/home/tso/Projects/bike/client/node_modules/neo-async/async.js:3522:9)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/home/tso/Projects/bike/client/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook (/home/tso/Projects/bike/client/node_modules/tapable/lib/Hook.js:154:20)
    at outputFileSystem.writeFile.err (/home/tso/Projects/bike/client/node_modules/webpack/lib/Compiler.js:464:33)
    at /home/tso/Projects/bike/client/node_modules/graceful-fs/graceful-fs.js:61:14

My config:

const BundleTracker = require('webpack-bundle-tracker');
const path = require('path');

module.exports = {
    context: __dirname,
    entry: {
        app: ['./src/app.js']
    },
    output: {
        path: path.resolve('./build/'),
        filename: '[name]-[hash].js'
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader'
            },
            {
                test: /\.jsx$/,
                exclude: /node_modules/,
                loader: 'babel-loader'
            },
        ]
    },
    plugins: [
        new BundleTracker({
            // filename: './build/webpack-stats.json',
            // path: __dirname,

            filename: './webpack-stats.json',
            })
    ]
};

and my project structure

image

I googled and found two other cases and my setup is identical (no answer on either): https://www.reddit.com/r/webpack/comments/hs94is/webpack_bundle_tracker_not_working/ https://stackoverflow.com/questions/62935574/webpack-bundle-tracker-not-working-error-eexist-file-already-exists-mkdir

I managed to monkey patch it by skipping the recreation of the folder if it already exists in lib/index:79. Now the code runs and the stats file is populated as expected.

if (!fs.existsSync(this.outputTrackerDir)) {
  fs.mkdirSync(this.outputTrackerDir, {recursive: true, mode: 0o755});
}

Any ideas as to why? - Best regards

quinox commented 3 years ago

I'm a happy webpack-bundle-tracker user, I was upgrading some old projects and I ran into the same problem.

I tracked it down to a difference in NodeJS versions:

fjsj commented 3 years ago

@quinox thanks for the input.

@harpunius could you please try using the latest webpack-bundle-tracker version (1.1.0) and let us know if the error persists?

quinox commented 3 years ago

Just adding the info I've gathered:

For me webpack-bundle-tracker version 0.4.2-beta worked fine on the old NodeJS whereas version 1.1.0 crashed. Version 0.4.2-beta of the tracker used mkdirp.sync instead of fs.mkdirSync, which got changed in d1f8e39c:

Old node:

$ nodejs
> console.log(process.version)
v8.10.0

# what 0.4.2-beta does:
> mkdirp = require('mkdirp')
> mkdirp.sync('/tmp/already-exists')
null
> mkdirp.sync('/tmp/already-exists')
null

# what 1.1.0 does:
> fs.mkdirSync('/tmp/already-exists', { recursive: true })
Error: EEXIST: file already exists, mkdir '/tmp/already-exists'
    at Object.fs.mkdirSync (fs.js:885:18)

New node:

> console.log(process.version)
v14.17.1

# what 0.4.2-beta does:
> mkdirp.sync('/tmp/already-exists')
null
> mkdirp.sync('/tmp/already-exists')
null

# what 1.1.0 does:
> fs.mkdirSync('/tmp/already-exists', { recursive: true })
undefined
> fs.mkdirSync('/tmp/already-exists', { recursive: true })
undefined

I don't know the reason behind switching from mkdirp.sync to fs.mkdirSync. A possible solution would be keep using fs.mkdirsync and simply try/catch the call.

fjsj commented 3 years ago

Thanks for pinpointing the issue @quinox, that's super-helpful!

I think the reason for not using mkdirp.sync is avoiding an additional dependency. Not sure if we should bring it back. Node 10 is now unsupported (out of LTS): https://nodejs.org/en/about/releases/

We should, however, have a CI here to know better which Node versions we support.

quinox commented 3 years ago

I think the reason for not using mkdirp.sync is avoiding an additional dependency. Not sure if we should bring it back. Node 10 is now unsupported (out of LTS): https://nodejs.org/en/about/releases/

That sounds entirely reasonable.

We should, however, have a CI here to know better which Node versions we support.

Excellent idea. I see there's already a small Travis configuration but it's not actively used by this project, see #95. I tried it out on my own fork, the build runs but doesn't run the matrix correctly and it also fails. I can polish it up a bit.

fjsj commented 3 years ago

@quinox if you can make it work via GitHub Actions or CircleCI, please feel free to open a PR.

fjsj commented 3 years ago

Closing as Node 10 is now out of LTS.