JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 39
  • Score
    100M100P100Q61948F
  • License MIT

CodeCoupler Webpack Externals Factory

Package Exports

  • @codecoupler/cc-webpack-externals-plugin

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@codecoupler/cc-webpack-externals-plugin) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Webpack Externals Configuration Concept

Let's start with an simple example: You are developing a library, processed with Webpack, that requires jQuery and Bootstrap. The library itself do not contain jQuery or Bootstrap.

You start of course with installing the modules with npm i jquery --save and npm i bootstrap --save. In your code you use then something like var $ = require('jquery'); or require('bootstrap');. After that you add these modules into the externals configuration of webpack, so they will not get bundled with your library. Then you modify your HTML files to load the external libraries from a folder or from a CDN. Last but not least you have to write into your documentation what libraries are needed to use your library and how to include them.

With this plugin you can just install these modules with npm i some_module --save and define these modules in a simple configuration file. The most of the other steps will be executed automatically.

Setup

Install package:

npm i @codecoupler/cc-webpack-externals-plugin -D

Add to your Webpack configuration:

const ccWebpackExternalsPlugin = require("@codecoupler/cc-webpack-externals-plugin");
module.exports = {
  plugins: [new ccWebpackExternalsPlugin()]
};

The configuration file

You have to define every module that should be handled as external in a file named webpack.externals.js in your root project folder. An absolute minimum file content would be:

module.exports = [];

As you can see an array will be defined here. Every item in this array is an object which define an external module. Here is an example to define jQuery as an external library:

module.exports = [
  {
    module: "jquery",
    global: "jQuery",
    entries: "dist/jquery.min.js"
  }
];

This configuration will:

  1. Exclude the module jquery from the build
  2. Define the global variable jQuery as the source for this library
  3. Copy the file dist/jquery.min.js from the node_modules folder of jQuery to a subdirectory of your dist folder named vendor/jquery-X.X.X/dist/jquery.min.js (the current version will be read from the current installed package)
  4. Copy the corresponding source map (if exists of course) dist/jquery.min.js.map also to the destination folder
  5. Inject a link like <script src="vendor/jquery/dist/jquery.min.js"> to your HTML files processed by the html-webpack-plugin

Now we extend the example by adding the Bootstrap module into the configuration:

module.exports = [
  {
    module: "jquery",
    global: "jQuery",
    entries: "dist/jquery.min.js"
  },
  {
    module: "bootstrap",
    entries: ["dist/css/bootstrap.min.css", "dist/js/bootstrap.bundle.min.js"]
  }
];

As you can see, the key global is not necessary and entries can be a single string or an array of strings. All entries must end with .js or .css. All other exetensions will be ignored.

Last but not least we add the module of Font Awesome to the configuration:

module.exports = [
  {
    module: "jquery",
    global: "jQuery",
    entries: "dist/jquery.min.js"
  },
  {
    module: "bootstrap",
    entries: ["dist/css/bootstrap.min.css", "dist/js/bootstrap.bundle.min.js"]
  },
  {
    module: "@fortawesome/fontawesome-free",
    entries: "css/all.min.css",
    copy: ["webfonts/"]
  }
];

Here you see the key copy in action. This can be a string or an array of strings. All the globs defined here will be just copied to the destination folder but not injected anywhere. Here you can define single files or folders.

Switching to CDN

If you do not want to copy any files to your destination folder you can switch to CDN with just one option:

new ccWebpackExternalsPlugin({
  useCdn: true
});

This will replace the urls in the script and the link tags with CDN targets, pointing to the exact version of the locally installed package. Here an example of using jQuery from CDN:

<script src="//cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.min.js">

You can of course specify your own conversion function. Here is an example how to use unpkg instead of jsdelivr:

new ccWebpackExternalsPlugin({
  useCdn: true,
  getCdnPath: (name, version, path) => "//unpkg.com/${name}@${version}/${path}"
});

Recursively include further externals

Now that you have written your library and you want to publish it, you should include the webpack.externals.js in you package. Because this will simplify some steps for the developer using your library.

The developer could install your library with npm i your_library. Because your library have all the external modules listed as depndencies they will be automatically installed, too. The the developer have just to install this plugin and point in the webpack.externals.js to your library like this:

module.exports = [
  {
    module: "your_library",
    entries: ["dist/your_library.js"]
  }
];

Now all the externals you have defined in your own webpack.externals.js will be automatically merged into his configuration. Your externals will be pretended to his externals.

If the developer is using a same module in his configuration, the keys entries and copy will be merged and deduplicated.

This principle will work recursively. That means that the developer using your library himself can include his own webpack.externals.js pointing to your library and publish his work. The next developer have just to point to this library and your externals will also be included.

You can stop including externals of modules by setting includeExternals: false:

module.exports = [
  {
    module: "your_library",
    entries: ["dist/your_library.js"],
    includeExternals: false
  }
];

Thanks goes to

The basic functionality will be done by the underlying https://github.com/jharris4/html-webpack-deploy-plugin. This plugin is just an wrapper for the recursive inclusion and some simplifications.