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

Instantiate MemoryFileSystem only once #120

Merged
merged 4 commits into from
Sep 13, 2016
Merged

Conversation

moljac024
Copy link
Contributor

I wasn't sure if I should open an issue or a pull request, but since I already made some changes, here goes.

I have perhaps a peculiar use case: I want to use the middleware for multiple express apps that would share a single compiler but otherwise be independent and listen on different ports and serve different index files that would include different bundles (webpack is configured with multiple entry points).

The problem arises because the middleware mutates the compiler.outputFileSystem property. When setting up multiple middlewares only the last one will be valid and the ones before will hold a reference to a memory fs that the compiler is not using to write files to.

My solution was to detect if the outputFileSystem already was a MemoryFileSystem and if it was, just not overwrite it but use the existing one for the middleware. An alternative approach would be to take an optional file system as an option and use that, and then every middleware instance could be passed in the same fs reference. But this requires installing memory-fs as a peer so for my quick-fix I didn't do it that way.

There must be a better way to achieve this, and I also may be misunderstanding something and doing everything horribly wrong. I need some feedback on this and if changes in this direction are wanted, will fix up the commits and the code.

@moljac024
Copy link
Contributor Author

moljac024 commented Sep 8, 2016

This is an example of multiple express apps that would use the same compiler:

var path = require('path');
var express = require('express');

var webpack = require('webpack');
var webpackConfig = require('./webpack.config');
var devMiddleware = require('webpack-dev-middleware');

var compiler = webpack(webpackConfig);


function configureApp (app, indexFile) {
  app.use(devMiddleware(compiler, {
    noInfo: true,
    quiet: true,
    publicPath: webpackConfig.output.publicPath
  }));

  // For any route that isn't static file, serve the index.html, so we can have
  // client-side routing
  app.get('*', function(req, res) {
    res.sendFile(indexFile);
  });

  return app;
}

var ServerStartedCallback = function (port) {
  return function(err) {
    if (err) {
      console.log(err);
      return;
    }

    console.log('Listening at http://0.0.0.0:' + port);
  }
}

function listen (app, port) {
  app.listen(port, ServerStartedCallback(port));
}

function startServer (app, port, indexFile) {
  listen(configureApp(app, indexFile), port)
}

var apps = [
  { // App 1
    port: 3000,
    index: path.join(__dirname, 'src/public', 'index1.html')
  },
  { // App 2
    port: 3001,
    index: path.join(__dirname, 'src/public', 'index2.html')
  }
];

// Start dev servers
apps.forEach(function (app) {
  startServer(express(), app.port, app.index)
})

@@ -53,7 +53,19 @@ module.exports = function(compiler, options) {
if(typeof options.reporter !== "function") options.reporter = defaultReporter;

// store our files in memory
var fs = compiler.outputFileSystem = new MemoryFileSystem();
var fs;
if(options.fileSystem) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does your usecase still work when you remove the options.fileSystem? It looks now as if you've implemented two ways of reusing the outputFileSystem; by allowing options.fileSystem AND by checking if compiler.outputFileSystem already exists.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, my usecase will work with the removal of options.fileSystem. I'm not even using it currently but I added it here because it might be a better solution than checking the outputFileSystem.

Or maybe we want both for flexibility. Like I said, I'm willing to make any changes necessary, so long as there is an option for not mutating the outputFileSystem.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, could you remove options.fileSystem then? After that I'll do some tests and merge this in.

Copy link
Contributor Author

@moljac024 moljac024 Sep 10, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

EDIT: I have also changed the pull request title, removing the part that referenced the deleted code.

@moljac024 moljac024 changed the title Allow configurable outputFileSystem; Instantiate MemoryFileSystem only once Instantiate MemoryFileSystem only once Sep 10, 2016
@SpaceK33z
Copy link
Member

Cool, I'll try to test it in the upcoming days.

I've started writing some tests for this package since yesterday. If you have the time, it would be awesome if you could write a test for this. It would ensure this does not break in the future, so it's also in your own best interest :).

@SpaceK33z SpaceK33z merged commit 92403e9 into webpack:master Sep 13, 2016
SpaceK33z added a commit that referenced this pull request Sep 13, 2016
@SpaceK33z
Copy link
Member

Thanks. I added a test for this.

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

Successfully merging this pull request may close these issues.

2 participants