0

I have a project that makes use of a large bundle (dexie.js not that it's important to this question), that I'd like to 'split out' into it's own bundle that I can include manually, because it's only needed in a few of my entry point scripts.

Just so that you know: my webpack config uses multiple modules, with multiple (6) entry points, so this is a cut-down sample of my webpack.config.js:

{
context: path.join(__dirname, 'src'),
entry: {
    'js/contentscript.js' : './js/contentscript.js',
    'js/background.js'    : './js/background.js',
    'js/popup.js'         : './js/popup.js',
    'js/options.js'       : './js/options.js',
},
output: {
    path: path.join(__dirname, 'dist'), 
    filename: "[name]"
},
plugins: [
    new webpack.optimize.CommonsChunkPlugin({
        name: "dexie",
        filename: "js/dexie.js",
        minChunks: function (module) {
            // this assumes your vendor imports exist in the node_modules directory
            return module.context && module.context.includes("node_modules/dexie");
        }
    }),
    ... // other non relevant plugins here
]
}

The problem is that I have no typical 'vendor' nor 'common' requirement, like many other projects to. It's only in a few cases that I want to include the js/dexie.js bundle.

eg. in options.html, I have this:

<script src="js/dexie.js"></script>
<script src="js/options.js"></script>

...but I do not want it to be used for popup.html, which I want to keep as this:

<script src="js/popup.js"></script>

And since this is also a WebExtensions project, I definitely don't want my content scripts to need it!

The problem is, that when I open popup.js, I get the error: Uncaught ReferenceError: webpackJsonp is not defined.

Is there any way -- without splitting this into more webpack modules -- so that the CommonsChunkPlugin will play nice with the entry points so that only the ones I want are affected by it?

The only solution I can think of, is to make another CommonsChunkPlugin that acts in the way that 'vendor' and 'common' is typically used. That is:

    new webpack.optimize.CommonsChunkPlugin({
        name: "dexie",
        filename: "js/dexie.js",
        minChunks: function (module) {
            // this assumes your vendor imports exist in the node_modules directory
            return module.context && module.context.includes("node_modules/dexie");
        }
    }),
    new webpack.optimize.CommonsChunkPlugin({
        name: "manifest",
        filename: "js/manifest.js",
        minChunks: Infinity
    }),

Unfortunately, this means I need to include js/manifest.js in all my scripts, and since this is a WebExtension, then that means I have to inject it into each content page...IMHO this is a terrible solution.

Any ideas on how to improve this? Am I using CommonsChunkPlugin incorrectly? Is there a better module I should be using? (I'm actually still coming to grips with webpack!)

cmroanirgo
  • 7,297
  • 4
  • 32
  • 38

2 Answers2

0

First of all, using 'js/xxx.js' as an entry name is not a good way. If your options.js need dexie.js and popup.js do not need it. You can try to change files like below.

webpack.config.js

entry: {
    'vendor' : ['dexie'],
    'contentscript' : './js/contentscript.js',
    'background'    : './js/background.js',
    'popup'         : './js/popup.js',
    'options'       : './js/options.js',
},
resolve: {
    alias: {
        'dexie':'...'
    }
},
new webpack.optimize.CommonsChunkPlugin({
    name: "vendor",
    minChunks: Infinity
}),

Like I said before, CommonChunksPlugin will automatically help u extract common dependencies, in this case you dont need write a function of minChunks to indicate dependencies.

options.html

<script src="js/vendor.js"></script>
<script src="js/options.js"></script>

popup.html

<script src="js/popup.js"></script>
胡亚雄
  • 2,161
  • 1
  • 19
  • 21
0

I stumbled across this excellent answer by @prograhammer: https://stackoverflow.com/a/40416826/125525

In it he made reference to the Externals plugin, which I'd not heard of before, and it neatly solves my problems. This is the description from the webpack site:

For example, to include jQuery from a CDN instead of bundling it:

index.html

<script
  src="https://code.jquery.com/jquery-3.1.0.js"
  integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
  crossorigin="anonymous">
</script>

webpack.config.js

externals: {
  jquery: 'jQuery'
}

This leaves any dependent modules unchanged, i.e. the code shown below will still work:

import $ from 'jquery';

$('.my-element').animate(...);
cmroanirgo
  • 7,297
  • 4
  • 32
  • 38