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

MemoryFS does not support file timestamps #37

Open
oliverwoodings opened this issue Apr 21, 2017 · 1 comment
Open

MemoryFS does not support file timestamps #37

oliverwoodings opened this issue Apr 21, 2017 · 1 comment

Comments

@oliverwoodings
Copy link

Continuing discussions from here - https://twitter.com/TheLarkInn/status/855369900914855937

At my recent talk at React London I mentioned that we use MemoryFS as the input filesystem for webpack in our bundling service - https://www.youtube.com/watch?v=mkUK2SZ8moY . One issue we came across when making this system scale was that as soon as we swapped out the input filesystem, rebuild times went through the roof. After digging into the webpack core I discovered that the compiler was trying to use the last modified timestamp (mtime) in order to work out whether it needed to rebuild each file. Since MemoryFS does not support mtime, webpack is unable to use its module cache and ends up rebuilding every file on every compilation.

We ended up monkey-patching support for timestamps into the methods we needed. It's not pretty, but here is the code extracted from our project:

const _ = require('lodash')
const MemoryFS = require('memory-fs')

const mfs = new MemoryFS()
mfs.lastModified = {}

// memory-fs doens't support stats by default, so we wrap all relevant methods
// to make it work.
wrap('writeFileSync', writeFile)
wrap('unlinkSync', unlink)
wrap('rmdirSync', rmdir)
wrap('statSync', stat)
wrap('mkdir', mkdir)

function mkdir (fn, args) {
  // mfs doesn't support supplying the mode!
  if (typeof args[2] === 'function') {
    return fn.apply(mfs, [args[0], args[2]])
  } else {
    return fn.apply(mfs, args)
  }
}

function writeFile (fn, args) {
  const filePath = args[0]
  const result = fn.apply(mfs, args)
  mfs.lastModified[filePath] = new Date()
  return result
}

function unlink (fn, args) {
  const filePath = args[0]
  const result = fn.apply(mfs, args)
  delete mfs.lastModified[filePath]
  return result
}

function rmdir (fn, args) {
  const dir = args[0]
  const result = fn.apply(mfs, args)
  mfs.lastModified = _.reduce(mfs.lastModified, (memo, mtime, filePath) => {
    if (filePath.indexOf(dir) !== 0) {
      memo[filePath] = mtime
    }
    return memo
  }, {})
  return result
}

function stat (fn, args) {
  const filePath = args[0]
  const stats = fn.apply(mfs, args)
  stats.mtime = mfs.lastModified[filePath]
  return stats
}

function wrap (method, fn) {
  const oldFn = mfs[method]
  mfs[method] = () => fn(oldFn, arguments)
}

@sokra @TheLarkInn

@hinell
Copy link

hinell commented Feb 13, 2019

It looks like it doesn't support stats object either. At least, as of v11.x.x version of Node.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants