Search code examples
javascriptangulartypescriptwebpackwebpack-2

Build standalone module alongside main module with Webpack


I have an Angular 2 app that's built by Webpack 2, based on the AngularClass starter project. As you'll probably tell from this question, I am still a Webpack n00b.

As part of a a new feature I'm implementing, I want to develop a standalone widget that gets downloaded to the client. It is logically part of my main application, but doesn't use Angular so shouldn't directly depend on the main Angular application being loaded in the browser. However, it does share some code and settings - things like SASS, endpoint URLs, lint rules and some TypeScript classes.

To keep things DRY, I'm hoping to build both the App and the Widget using the same Webpack configuration. To get things started, I told Webpack to build my widget as a separate module:

entry: {    
    'polyfills': './src/polyfills.browser.ts',
    'main': AOT ? './src/main.browser.aot.ts' :
        './src/main.browser.ts',
    'widget': './src/app/widget/index.ts'      // <-- added this
}

I now have three problems.

Make widget.bundle.js standalone

Because Webpack has bundled shared dependencies together, I still have to load all of my Angular app modules to get my widget to work:

<script src="http://localhost:8080/polyfills.dll.js"></script>
<script src="http://localhost:8080/vendor.dll.js"></script>
<script src="http://localhost:8080/polyfills.bundle.js"></script>
<script src="http://localhost:8080/vendor.bundle.js"></script>
<script src="http://localhost:8080/main.bundle.js"></script>
<script src="http://localhost:8080/widget.bundle.js"></script>

I want my widget to be completely self contained, so I can just load:

<script src="http://localhost:8080/widget.bundle.js"></script>

Prevent widget.bundle.js being loaded in the main app

Now when I run my main app, it also tries to load widget.bundle.js. I want to prevent this.

Webpack appends the chunk ID to the bundle name

For production builds, Webpack creates my widget bundle with a name like widget.234e2174f24f78d1072c.bundle.js. This is no good, because this will change on each build, so all my clients will have to be updated with the new name. How do I make this name static?


Solution

  • The more I thought about it, the more obvious it became that I needed a completely separate webpack.config.js for this widget. Based off one of my existing configs, this wasn't that hard to do. I ended up with a simple config with a single entry and output, removing all unneeded plugins, especially CommonChunkPlugin which splits modules based on shared dependencies.

        entry: {
            'selector-widget': './src/app/widget/index.ts'
        },
    
        output: {
            path: helpers.root('dist'),
            filename: 'widget.bundle.js'
        }
    

    I then created a new script in package.json to build the widget, then called this from the main production build script.