What I want:
All JavaScript/TypeScript files that require jQuery to contain it, but all my async chunks that require jQuery to not contain jQuery and use the window.jQuery
variable instead.
The Problem:
The thing is: there is a jQuery plugin (external code) loaded as a chunk that require jQuery in its code (UMD) so the chunk itself contains its own jQuery after Webpack build ... :(
Context:
I have a main file that imports jQuery and makes it available as a global in window because of legacy code. Then this main file will async load some chunks.
One of the chunk is an external package (so I can not change the code). It is a jQuery plugin written with UMD.
It kind of look like it:
// main.js
import $ from 'jquery';
window.$ = window.jQuery = $; // In reality with expose-loader.
import(/* webpackChunkName: jquery.plugin */ 'jquery-plugin').then(() => {
$('element').plugin();
});
The UMD of the plugin looks like that:
// jquery-plugin.js
(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Webpack gets here by default.
define(['jquery'], factory);
} else if (typeof exports === 'object' && typeof require === 'function') {
// Webpack gets here if I disable AMD in Webpack config.
factory(require('jquery'));
} else {
// I would like Webpack to get here.
factory(jQuery); // Browser global
}
}(function($) { /* plugin code */ })
What I tried:
I have seen webpack.ProvidePlugin
but it seems to be applied to all files only, so my main.js will not contain jQuery which would be a big problem.
Ignoring jQuery in the specific library with webpack.IgnorePlugin
but it results in a module not found error since the file does not contain jQuery anymore but the jQuery plugin code has not change and still requires jQuery ...
// webpack.config.js
{
plugins: [
new webpack.IgnorePlugin(/^jquery$/, /node_modules\/jquery-plugin/),
]
}
jquery.autocomplete.js:19 Uncaught (in promise) Error: Cannot find module 'jquery'
From what I have understood, I can not use externals
as object because it would be external for all files. So I tried it with the function syntaxe but did not make it work. I feel like it may be the solution, but I am missing something:
// webpack.config.js
{
externals: [
function(context, request, callback) {
if (/^jquery$/.test(request) && /node_modules\/jquery-plugin/.test(context)){
return callback(null, 'amd ' + request);
}
callback();
},
],
}
external_"jquery":1 Uncaught (in promise) ReferenceError: WEBPACK_EXTERNAL_MODULE__638 is not defined
Maybe there are some splitChunk options to deal with something like that?
IDK :'(
Help is very welcome ^^'
Thanks
Heymath