hawkins / prettier-webpack-plugin

Process your Webpack dependencies with Prettier
https://travis-ci.org/hawkins/prettier-webpack-plugin
50 stars 14 forks source link

Rewrite files before Webpack bundles #2

Open hawkins opened 7 years ago

hawkins commented 7 years ago

Currently, the plugin rewrites files just a bit too late, so the bundler runs twice in watch mode. Once on the file changes by user, a second time when the plugin reformats the file.

It would be great if we could manage to rewrite the file before the bundler finalizes the assets, that way code is only bundled once in watch mode.

hawkins commented 7 years ago

I've tried modifying each module's filepath for each one of its fileDependencies as soon as I can tell is possible, but it is still too late to prevent Webpack bundling code twice.

Here's the earliest I could figure out to modify code:

apply(compiler) {
  compiler.plugin('compilation', (compilation, params) => {
    compilation.plugin('optimize-modules', modules => {
      modules.forEach(module => {
          if (!module.fileDependencies) return;

          // Explore each source file path that was included into the module
          module.fileDependencies.forEach(filepath => {
            // ... our plugin's work ...
          });
        });
    });
  });
}

However, this attempt causes these results to be produced:

image

As you can see, when the user changes the source file, Webpack appropriately invalidates the bundle and rebuilds.

However, if Prettier reformats the source file, then Webpack will rebundle after our plugin rewrites the source file again. This is highlighted in the pink color, and this is the behavior I want to prevent.

TheLarkInn commented 7 years ago

Is this something that could be ran as a preloader instead of a plugin? Loaders are the last step to webpacks resolution process so once a file changes its deps resolve (if needed) and then loaders are applied.

hawkins commented 7 years ago

Looks like you're right, @TheLarkInn . I originally thought this would fit best as a plugin, but a preloader definitely makes the most sense.

I believe I've worked out the loader's logic, but I'm unable to load it in my webpack config. I've tried specifying a relative path, using resolveLoader, and using the package name and npm linking the module, but I can't seem to make my loader actually be invoked.

Even a simple plugin (module.exports = source => { console.log(source); return source; };) does not work with the config:

module.exports = {
  entry: "./entry.js",
  output: {
    filename: "bundle.js",
    path: __dirname
  },
  preLoaders: [
    {
      test: /\.js$/,
      loader: '../loader/index.js' // Or 'prettier-webpack-loader' with npm link,
    }
  ]
};

Webpack resolves all modules correctly, but does not apply the loader.

How can loaders be used locally in configuration without pushing to npm?

Edit: The solution here is to use path.resolve: https://webpack.github.io/docs/configuration.html#module-loaders

torgeir commented 6 years ago

Any updates on this?