Search code examples
javascriptwebpackhandlebars.jsloaderumd

Avoid bundling lib dependencies with webpack + handlebars loader


I'm writing a library using handlebars templates and I want to use Webpack to bundle it. I'm using handlebars-loader so that I can require and precompile the templates.

However I don't want handlebars (nor handlebars/runtime) to be included in my compiled library and thus, I would like to set them as externals.

Here is my config file:

module.exports = {
    context: __dirname + '/src',
    entry: './index.js',
    output: {
        path: __dirname + '/dist',
        filename: 'stuff.js',
        libraryTarget: 'umd',
        library: 'Stuff'
    },
    externals: [{
        'handlebars/runtime': {
            root: 'Handlebars',
            amd: 'handlebars.runtime',
            commonjs2: 'handlebars/runtime',
            commonjs: 'handlebars/runtime'
        }
    }],
    module: {
        loaders: [
            { test: /\.handlebars$/, loader: 'handlebars-loader' }
        ]
    }
};

Unfortunately it doesn't work and handlebars-loader still makes handlebars/runtime to be bundled...

I believe it is because I do not require handlebars/runtime directly, rather it is required in the code added by the loader.

Is there a way to mark it as external?

Edit: I know I need handlebars/runtime to compile my template. But as I am building a library, I want it to be provided by the user of the library instead of being included. This way, if my user is also using Handlebars, the library is not loaded twice. I believe it is good practice for libraries to avoid bundling any dependency (it is something we see much too often in my humble opinion).


Solution

  • The handlebars-loader's team helped me solve this issue.

    The problem is that handlebars-loader, by default, loads handlebars' runtime using an absolute path. However, it is possible to use the runtime argument of the handlebar loader to specify a different path for handlebars' runtime. It is then possible to set this path as external.

    This is working:

    module.exports = {
        context: __dirname + '/src',
        entry: './index.js',
        output: {
            path: __dirname + '/dist',
            filename: 'stuff.js',
            libraryTarget: 'umd',
            library: 'Stuff'
        },
        externals: [{
            'handlebars/runtime': {
                root: 'Handlebars',
                amd: 'handlebars/runtime',
                commonjs2: 'handlebars/runtime',
                commonjs: 'handlebars/runtime'
            }
        }],
        module: {
            loaders: [
                { test: /\.handlebars$/, loader: 'handlebars-loader?runtime=handlebars/runtime' }
            ]
        }
    };