Multiple targets

This is mostly to open discussion on how to solve a specific problem at this point, I only have a crude idea in my head of how this could be made to work.

I currently have an isomorphic website (www.toons.tv) that’s built using React and Webpack on both the server and the client. The current build setup is quite clunky and accounts for a big portion of code in the whole project – the main reason for this is that in order to have an efficient development setup, I of course want to be watching all the assets and rebuild them when changed. However, every time the assets are rebuilt, the JS (both client and server) needs to know the new asset URLs. This means a very complex setup where webpack is only building the JS, and the rest (icon fonts, web fonts, images and other assets) is handled by gulp, and then all these update a build-manifest.json file that is required by the JS, so that the webpack builds are triggered as well.

I’d like to move the asset pipeline completely to webpack instead, but this is problematic because currently you can only have one target (and set of options) per compiler, so the assets would be rebuilt twice and given that some of the assets are not generated deterministically (e.g. the icon fonts), the client could end up with different asset URLs than the server, which could easily lead to resources being loaded twice on the client.

At some point, I would also like to take service workers into use, and the worker would also need the same asset URLs.

One proposal that comes to mind is that you could define per-entry options:

webpack({
  entry: {
    client: {
      entry: "/path/to/client/entry.js",
      target: "browser",
    },
    server: {
      entry: "/path/to/server/entry.js",
      target: "node",
    },
  },
});

I do realize that this would probably be a pain to implement, especially if the different entries are supposed to share parts of the pipeline while diverging at some points (e.g. if there’s different plugins and/or loaders used by different entries), and also possibly require breaking changes to the plugin API, but I do hope to see this use case solved by webpack at some point.

Cheers! ❤️

Author: Fantashit

6 thoughts on “Multiple targets

  1. You can pass an array of configurations to webpack (with different targets). This works fine.

    that some of the assets are not generated deterministically (e.g. the icon fonts)

    Make sure they are determinisitic. It’s a guideline for loaders.

    webpack([
        {
          name: "client",
          entry: "/path/to/client/entry.js",
          target: "browser",
        },
        {
          name: "server",
          entry: "/path/to/server/entry.js",
          target: "node",
        },
    ]);
  2. +1
    array of configuration is not optimal because “browser” and “webworker” could share bundles, but with multiply configuration they do not share anything.
    i think webpack should unify “browser” and “webworker” target or the second best solution is that target should be configured by entry points.
    This should be essential because usualy webworker share a lot of common library with the main thread, and browser could use the cache.

  3. If your config file is big, and all you need is to change the target for a specific entry, its lengthy and has duplicate configuration for no reason.

    I too would love to see:

    webpack({
      entry: {
        client: {
          entry: "/path/to/client/entry.js",
          target: "browser",
        },
        server: {
          entry: "/path/to/server/entry.js",
          target: "node",
        },
      },
    });
  4. @omeid It is not a problem, rather, it is a suggestion I believe.
    @sokra I would like to ask you: does webpack shares common chunks between separate configurations when two and more configuration objects are used?
    I think if the compilers don’t share them then it incurs an additional overhead and performance losses.

Comments are closed.