jqueryangularwebpackangular-cliwebpack-externals

Angular `build` throw error for externals decaled with `webpack`


In my angular, I am loading jquery from extranal and it works. But, after the build, I am getting an error Uncaught ReferenceError: jQuery is not defined . My build downloads the jquery, mind you.

Question: How can I map the jquery with my build?

index.html:

<script type="systemjs-importmap">
      {
        "imports": {
          "single-spa": "https://cdn.jsdelivr.net/npm/single-spa@5.8.2/lib/system/single-spa.min.js",
          "jquery": "https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"
        }
      }
    </script>

 <script>
      System.import("single-spa");
      System.import("jquery");
    </script>

webpack config ( it works well locally )

module.exports = {
  externals: {
    jquery: ["jQuery"],
  },
};

Note: After the build, if I run it in server, I get the error:

Uncaught ReferenceError: jQuery is not defined
    at Object.xeH2 (main-es2015.3ee70c890346f45d7daa.js:2)
    at l (runtime-es2015.cdfb0ddb511f65fdc0a0.js:1)
    at Module.zUnb (main-es2015.3ee70c890346f45d7daa.js:2)
    at l (runtime-es2015.cdfb0ddb511f65fdc0a0.js:1)
    at Object.0 (main-es2015.3ee70c890346f45d7daa.js:2)
    at l (runtime-es2015.cdfb0ddb511f65fdc0a0.js:1)
    at t (runtime-es2015.cdfb0ddb511f65fdc0a0.js:1)
    at Array.r [as push] (runtime-es2015.cdfb0ddb511f65fdc0a0.js:1)
    at main-es2015.3ee70c890346f45d7daa.js:2

My server try to download the jquery from an external source.

here is the network in server


Solution

  • Explanation

    When webpack externals are an object, the keys are the name you import in your code, and the values are the name of the module in the runtime environment.

    The "runtime environment" used by the webpack bundle could either be global variables or the SystemJS module registry, depending on your webpack config's output.libraryTarget. The behavior of webpack externals changes for different libraryTargets.

    If your libraryTarget is "system" (recommended for SystemJS loading), "umd", or "amd", then the bug here is that the name of the module in SystemJS module registry is jquery, but your webpack config expects it to be jQuery. SystemJS module names are case sensitive.

    If your libraryTarget is unspecified or var, then webpack will look for a global variable called jQuery. If you're using the systemjs amd.js extra, then jQuery will not be created as a global variable. But if you are not using amd.js, then jQuery will be created as a global variable.

    Possible fixes

    1. Change your webpack config to expect the runtime environment to provide jquery instead of jQuery. This will only work if the webpack libraryTarget is system, umd, or amd (as explained above).
    // webpack.config.js
    module.exports = {
        externals: {
            jquery: "jquery",
        },
    };
    

    That webpack config is equivalent to providing externals as an array of strings:

    // webpack.config.js
    module.exports = {
        externals: ["jquery"]
    };
    
    1. Remove the SystemJS amd.js extra from your index.html file. This will ensure that jQuery is created as a global variable. Then make sure the webpack config's libraryTarget is either unspecified or var.

    Further diagnosis

    To diagnose the issues here, you can run the following in the browser console:

    await System.import('jquery')
    

    This will print how the jquery module was loaded by SystemJS. You should click on the logged value to expand it and see the keys. You should see jquery functions that you're familiar with it.