Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Entry Points with Multiple Vendor Bundles in Webpack

I've got several 'single-page apps' that need to run side-by-side in a single overarching application. To that end, I'm using webpack to trigger transpilation for jsx and scss, bundle the resulting css and js, and split application code written by us and application code that's coming in from third-party sources.

Unfortunately, it seems like webpack is very opinionated on how it bundles the vendor files - it wants to create a single large vendor bundle for all my entry points instead of a more reasonable split like this:

- app1
    - app1.bundle.js
    - app1.vendor.bundle.js
    - app1.bundle.css
- app2
    - app2.bundle.js
    - app2.vendor.bundle.js
    - app2.bundle.css

I specifically don't want to run into the situation where I import some large (eg, JQuery) library into app 2 and have it included along in the vendor bundles for other apps that don't need it. Many of our pages use totally different front-end stacks, and if I used a single vendor.js file for the entire web app I could see this ballooning out of control very quickly.

I'd also prefer to have this done automatically - webpack should be able to scan through my entry point, detect which third-party libraries (probably by referencing node-modules?) are being imported, and only include those in the vendor file for that app. I don't want to have to add third-party dependencies into an array in my webpack config and require() them in my entry point. That seems very redundant.

I'm okay with app1.vendor.bundle.js and app2.vendor.bundle.js having overlap (ie, if they both import React, they can both include that code in their separate bundles). I consider this a lot easier to manage than having to deal with common files that are shared between some subset of the apps running on my site.

Is there any way to actually do this in webpack on its own, or am I going to have to write some kind of custom solution that wraps around it to do this? All the examples I've seen have people compiling a single overarching vendor bundle for their entire application.

like image 668
Chris D. Avatar asked Dec 07 '17 15:12

Chris D.


People also ask

Can webpack have multiple entry points?

webpack.config.js We can also pass an array of file paths to the entry property which creates what is known as a "multi-main entry". This is useful when you would like to inject multiple dependent files together and graph their dependencies into one "chunk".

What is chunking in webpack?

Chunk: This webpack-specific term is used internally to manage the bundling process. Bundles are composed out of chunks, of which there are several types (e.g. entry and child).

How does webpack code splitting work?

In React, code splitting involves applying the dynamic import() syntax to your components so that webpack automatically split the imported component as a separate bundle.

What are 4 core concept of webpack?

There are four basic concepts in webpack: entry , output , modules and plug-ins . These configurations are added in webpack.


2 Answers

It's good to note that webpack supports an array of configurations. In that case, you would write something like this:

webpack.config.js

module.exports = [
  {...}, // Your first config
  {...}, // Your second config
]

Using this approach, you could write a configuration per page.

To generate entry HTML, you could use something like html-webpack-plugin or mini-html-webpack-plugin.

If you inject the bundles to your HTML otherwise, then it's useful to extract a manifest (webpack-manifest-plugin, webpack-assets-manifest). That gives you a JSON you can then use to inject the HTML you need at your host environment.

like image 91
Juho Vepsäläinen Avatar answered Oct 16 '22 14:10

Juho Vepsäläinen


Maybe you can use one webpack.config.js for each app, with entrypoint set to that app. (even if they share the same node_modules)

Like this:

config/
  base.webpack.config.js
  app1.webpack.config.js
  app2.webpack.config.js
  ...
build.sh

base.webpack.config.js

// your main webpack config with `splitChunks` config etc.
module.exports = {
  ...
  optimization: {
    splitChunks: {
      minChunks: ...,
      cacheGroups: {
        vendors: { ... }
      }
    }
  }
};

app1.webpack.config.js

// config for app1
const baseConfig = require('./base.webpack.config');

module.exports = {
  ...baseConfig,
  entry: {
    app: '../src/app1.js'
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, '..', 'dist/app1')
  }
};

build.sh

#!/bin/sh
# build app1
webpack --config config/app1.webpack.config.js

# build app2
webpack --config config/app2.webpack.config.js
like image 1
Aravindan Ve Avatar answered Oct 16 '22 15:10

Aravindan Ve