Leveraging webpack2 for code splitting with the CommonsChunkPlugin

I encountered an issue while using code splitting and the CommonsChunkPlugin. My previous experience with require.js involved files being automatically cached. Additionally, I have configured my webpack with libraryTarget: 'amd'.

When looking at these two simple files, here is the resulting output:

// 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

Both files, fileA and fileB, contain jquery. I am able to include these files in my html like this:

require(['./dist/fileA.js', './dist/fileB.js'], function () {
})

The documentation suggests using the CommonsChunkPlugin to extract jquery into its own file. So, my configuration now looks like this:

new webpack.optimize.CommonsChunkPlugin({
  name: 'common'
}),

This results in the following 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

However, now I am unable to use the above require block because the common.js also includes the webpack runtime. This leads to an error saying

Uncaught ReferenceError: webpackJsonp is not defined
.

To resolve this, I require the following setup:

  1. fileA.js (contains "fileA" code, requiring jquery)
  2. fileB.js (contains "fileB" code, requiring jquery)
  3. jquery.js (contains all jquery functionality)
  4. common.js (only contains webpack runtime)

I attempted something similar for fileA and fileB, but it resulted in 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 required in requirejs).

Is there a way to achieve this? I've checked the webpack2 docs multiple times but couldn't find anything helpful...

Edit: With guidance from various GitHub issues, I was able to correct the 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 updated the source files to include:

// fileA.js
import $ from 'jquery'
import Vue from 'vue'
// fileB.js
import $ from 'jquery'
// fileC.js
import Vue from 'vue'

Here is the updated 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

Despite this, attempting to use it in an .html file leads to 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>

This error occurs both for fileA and 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 have created a repository on GitHub showcasing the issue I encountered. Following Rafael De Leon's suggestion, I now utilize System.import('<module>') to asynchronously import other files. The error seems to occur when output.js (the compiled main.ts file) requires fileA.ts using this syntax. I have also raised a concern in a GitHub issue as I suspect it may be a bug.

Answer №1

It is important to only load a (Vendor) library if a script, such as fileA, has it as a dependency (as seen with requirejs).

If you are seeking this outcome, CommonsChunkPlugin may not be the solution you need. This plugin is designed to combine files used by different entries or other CommonChunkPlugins into one file.

To achieve what you want, consider using import() or require.ensure for loading "vendor" files on demand.

Alternatively, you can refer to How to bundle vendor scripts separately and require them as needed with Webpack? for a solution.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Capturing errors during function declaration in JavaScript

A problem has arisen in the below function definition due to a script error function foo () { try { var bar = function() { ERROR } } catch (exception) { console.debug("exception"); } } foo(); However, th ...

How can I retrieve the height of a dynamically generated div in Angular and pass it to a sibling component?

My setup consists of a single parent component and 2 child components structured as follows: Parent-component.html <child-component-1 [id]="id"></child-component-1> <child-component-2></child-component-2> The child-compo ...

Issue with a hidden div, problem with scrolling, a div overlapping other divs

I'm feeling a bit lost here, trying to figure out what went wrong. It seems like a simple mistake, but I can't pinpoint it. Currently, I'm just testing everything out for a mobile website template. Hopefully, that information helps. For any ...

What is the best way to convert a date to ISO 8601 format using JavaScript? Are there any built-in functions or methods in

Currently, I am using this function to set the duration: const setDuration = () => { const currentDate = new Date(); const newDate = new Date(currentDate.getTime()); const year = newDate.getUTCFullYear(); const m ...

Issue: Access to sdcard/hello.mp3 file denied due to permission error (EACCES)

While testing the "react-native-audio-recorder-player": "^3.5.3" on Android 11 & 12 with targetSDKversion 31, I encountered the error message Error: sdcard/sound.mp3: open failed: EACCES (Permission denied). Numerous suggested solut ...

Remove the initial section of the text and provide the rest of the string

I am a beginner in the world of Javascript and unfortunately I have not been able to find an answer to my current problem. Here is the situation. On a webpage, I am receiving a URL that is sometimes presented in this format: http://url1.come/http://url2.c ...

Modifying the input placeholder color with ng-style

I am working on setting the color of my input placeholder using a dynamic color defined in a $scope variable in my controller for my HTML code. The $scope variable is structured as follows: $scope.primaryColor={"color":colorVar}; //colorVar represents th ...

Angular-powered SPAs with cookie authentication

My current web framework utilizes cookie (or token) based authentication. Upon user registration, a postback occurs and the server embeds an authentication token into a cookie which is then linked to the user's browser. Subsequent requests utilize thi ...

Looking to minify a JavaScript file? Consider changing the overly long variable name "veryLoooooooongVariable" to something shorter,

When working on improving readability, I tend to use very long variable names which can increase the size of my JS files. I'm wondering if there are any tools or libraries available that can automatically change these long names to shorter ones? I am ...

I am attempting to gather outcomes from two separate arrays

I have a challenge of filtering the first array based on the text in the second array. I am trying to figure out how to update the count filter in the first array using values from the second array. First Array: var firstArray =[{text:"India",co ...

What is the significance of the "@" in JXON conversion in JavaScript?

Looking at an XML structure like the one below: <calendar> <month year="2013" num="5"> <day num="1"> </month> </calendar> I decided to convert it to JSON using MDN's JXON Snippet 3. https://developer.moz ...

How to Dynamically Set AngularJS Filter (like date or currency) Using Variables

When working with Angular, it's possible to easily apply filters to format variables, like so: {{ myDate | date }} {{ myMoney | currency }} But, is there a way to dynamically set the filter type in a more flexible manner as shown below? // controll ...

Using shortcode to enhance wordpress post content

I am trying to implement a feature similar to the one found at http://jsfiddle.net/theimaginative/gA63t/ within a wordpress post. I have attempted to create a shortcode for inserting this into a post, but I am encountering difficulties. While I have been s ...

Is it possible to prefetch library calls in Next.js in advance?

Recently, I started working with GeoChart using react-google-charts (https://github.com/RakanNimer/react-google-charts). However, I noticed that several scripts load after the entire process is completed. In my scenario, is loading towards the end. Is t ...

Is it possible to utilize AngularJS's $q functionality outside of an Angular component?

I am currently working on a browser application, where I have a specific file responsible for creating and initializing an object. This file is written in plain Javascript rather than being part of the Angular ecosystem like the rest of the app, which is b ...

Error encountered when attempting to upload image on Twitter: missing media parameter

According to the latest Twitter media upload API documentation, it is recommended to first utilize either POST multipart/form-data or base64 encoded files when interacting with . However, encountering an error with code 38 stating "media parameter is mi ...

Prevent additional clicks on the image

Currently, I am dealing with a situation where I have a list containing a jQuery handler for mouse clicks. The dilemma is that I need to insert an image into the list, but I want clicking on the image to trigger a different function than clicking elsewhere ...

What criteria does Angular use to determine when the aot compiler should be utilized?

This page discusses the concept of modules in Angular and explains the two approaches to bootstrapping - dynamic and static. The configuration for these approaches is typically found in main.ts: // Using the browser platform with a compiler import { platf ...

Modifying all occurrences of a specified string in an object (or array) - JavaScript

Is there a more efficient way to search through and replace all instances of a given string in a JavaScript object with unknown depth and properties? Check out this method, but is it the most optimal solution? var obj = { 'a' : 'The foo ...

How can I conceal child <div> elements when the parent div is resized?

Struggling to implement a zoom in/out feature on my web app using the jqueryUI slider. Having trouble handling cases where the parent div shrinks too much, causing issues with the child containers. <div class="puck originator inline-block" style="w ...