Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack: reference bundled components from outside bundle

I have a class inside my bundled app that I want to allow users of the app to extend.

Here's what the definition of the bundled class looks like:

import * as d3 from 'd3';

class VizPlugin {

    constructor(options) {
        this.options = options;
    }

    build() {
    }

...

}

export default VizPlugin;

The application is a full client/server nodejs app, installed on a customers server. After the app is bundled/deployed/installed on the server, I want the customer to be able to extend the app and add their own custom modules as extensions/plugins, like this:

import VizPlugin from './js/viz-plugin'; //there is no viz-plugin.js because it's bundled

class ScatterPlot extends VizPlugin {

    constructor(options) {
        super(options);
    }

    build() {

        //I'd like to also use the reference to d3 from VizPlugin here

    }
...
}

export default ScatterPlot;

They would put their javascript code in a directory along side the other bundled client javascript and import from that. Basically, there needs to be a named file called "viz-plugin.js" that can be imported from "scatter-plot.js".

like image 514
Andrew Avatar asked Oct 27 '22 02:10

Andrew


2 Answers

Add d3 to your class, and give the extender some way of using it:

import * as d3 from 'd3';

class VizPlugin {

    constructor(options) {
        this.options = options;
        this.d3 = d3;
    }
    useD3 (callback) {
      callback(this, this.d3);
    }
    build() {
    }

...

}

module.exports = VizPlugin as VizPlugin;
like image 88
Sydney Y Avatar answered Nov 12 '22 18:11

Sydney Y


You can use the webpack SplitChunksPlugin and give names to individual modules by using splitChunks.name.

The following code will look for the viz-plugin.js module and tell it to keep it's name:

optimization: {
    splitChunks: {
        name(module, chunks, cacheGroupKey) {
            const moduleId = module.identifier();
            if( moduleId && moduleId.indexOf('viz-plugin.js') >= 0 ) {
                return 'viz-plugin'
            }
            return null;
        }
    }
},

Now, in the dist/build output, there will be a file called "viz-plugin.js" that you can extend, as such:

import VizPlugin from './dist/js/viz-plugin';

class ScatterPlot extends VizPlugin {

    constructor(options) {
        super(options);
    }

    build() {

        //I'd like to also use the reference to d3 from VizPlugin here

    }
...
}

export default ScatterPlot;
like image 36
Andrew Avatar answered Nov 12 '22 19:11

Andrew