I ran into a problem using code splitting and the CommonsChunkPlugin. I'm used to require.js
where the files are cached automatically. I'm also using the libraryTarget: 'amd'
for my webpack configuration.
Considering these two simple files, this is the output I get:
// fileA.js
import $ from 'jquery'
// fileB.js
import $ from 'jquery'
Asset Size Chunks Chunk Names
fileB.js 271 kB 0 [emitted] [big] fileB
fileA.js 271 kB 1 [emitted] [big] fileA
So both files, fileA
and fileB
have jquery
included. Also, I'm able to use these files like this in my html
file.
require(['./dist/fileA.js', './dist/fileB.js'], function () {
})
As per the docs I can use the CommonsChunkPlugin
to basically extract jquery into its own file, so my config looks like this:
new webpack.optimize.CommonsChunkPlugin({
name: 'common'
}),
resulting in this output:
Asset Size Chunks Chunk Names
fileB.js 635 bytes 0 [emitted] fileB
fileA.js 617 bytes 1 [emitted] fileA
common.js 274 kB 2 [emitted] [big] common
BUT now I'm unable to use the above require
block, because the common.js
also includes the webpack runtime. All I now get is an Uncaught ReferenceError: webpackJsonp is not defined
error.
So what I would need is:
- fileA.js (only contains "fileA" code, requiring jquery)
- fileB.js (only contains "fileB" code, requiring jquery)
- jquery.js (all of the jquery stuff)
- common.js (only contains the runtime for webpack)
I already tried something like this for fileA
and fileB
, but it's basically the same output:
define(['jquery'], function ($) {
})
A (Vendor) library should only be loaded, if a script (like fileA
) is loaded and has it as a dependency (as it is with requirejs).
Can this be accomplished? I skimmed through the webpack2 docs numerous times, but couldn't find anything that could help me...
edit: Ok, with the help of some github issues, I managed to get the correct asset generation with the following configuration:
module.exports = {
entry: {
jquery: ['jquery'],
vue: ['vue'],
fileA: ['./src/fileA.js'],
fileB: ['./src/fileB.js'],
fileC: ['./src/fileC.js']
},
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist',
filename: '[name].js',
libraryTarget: 'amd'
}
}
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.optimize.CommonsChunkPlugin({
name: ['vue', 'jquery']
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
chunks: ['vue', 'jquery'],
minChunks: Infinity
}),
new webpack.optimize.OccurrenceOrderPlugin()
])
I changed the source files to:
// fileA.js
import $ from 'jquery'
import Vue from 'vue'
// fileB.js
import $ from 'jquery'
// fileC.js
import Vue from 'vue'
And this is the output:
vue.js 193 kB 0 [emitted] vue
fileC.js 447 bytes 1 [emitted] fileC
fileB.js 579 bytes 2 [emitted] fileB
fileA.js 666 bytes 3 [emitted] fileA
jquery.js 269 kB 4 [emitted] [big] jquery
common.js 5.78 kB 5 [emitted] common
However, using it in an .html
file like so results in the following error:
<body>
<script src="./dist/common.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.3/require.js"></script>
<script>
require(['./dist/fileA.js', './dist/fileB.js', './dist/fileC.js'], function (a, b, c) {
})
</script>
</body>
The following error occurs both for fileA
and for fileC
...
common.js:55 Uncaught TypeError: Cannot read property 'call' of undefined
at __webpack_require__ (common.js:55)
at Object.7 (fileA.js:16)
at __webpack_require__ (common.js:55)
at Object.6 (fileA.js:6)
at __webpack_require__ (common.js:55)
at webpackJsonpCallback (common.js:26)
at fileA.js:1
at Object.execCb (require.js:1696)
at Module.check (require.js:883)
at Module.enable (require.js:1176)
edit:
I've create a repo on github showing the problem I ran into. As per the answer of Rafael De Leon, I'm now using System.import('<module>')
to asynchronously import other files. main.ts
imports fileA.ts
via this syntax, resulting in an error when output.js
(the compiled main.ts
file) is required. The error seems to happen when fileA
is being loaded from withing output.js
... I've also created a github issue, because I think it's a bug.