Skip to content

Commit

Permalink
add support for webpack5 'externals function'
Browse files Browse the repository at this point in the history
  • Loading branch information
jet2jet committed Apr 3, 2021
1 parent e871a9a commit 06d7258
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 7 deletions.
47 changes: 40 additions & 7 deletions resolvers/webpack/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,14 @@ exports.resolve = function (source, file, settings) {

log('Using config: ', webpackConfig);

const resolveSync = getResolveSync(configPath, webpackConfig, cwd);

// externals
if (findExternal(source, webpackConfig.externals, path.dirname(file))) {
if (findExternal(source, webpackConfig.externals, path.dirname(file), resolveSync)) {
return { found: true, path: null };
}

// otherwise, resolve "normally"
const resolveSync = getResolveSync(configPath, webpackConfig, cwd);

try {
return { found: true, path: resolveSync(path.dirname(file), source) };
Expand Down Expand Up @@ -322,15 +323,15 @@ function makeRootPlugin(ModulesInRootPlugin, name, root) {
}
/* eslint-enable */

function findExternal(source, externals, context) {
function findExternal(source, externals, context, resolveSync) {
if (!externals) return false;

// string match
if (typeof externals === 'string') return (source === externals);

// array: recurse
if (externals instanceof Array) {
return externals.some(function (e) { return findExternal(source, e, context); });
return externals.some(function (e) { return findExternal(source, e, context, resolveSync); });
}

if (externals instanceof RegExp) {
Expand All @@ -339,13 +340,45 @@ function findExternal(source, externals, context) {

if (typeof externals === 'function') {
let functionExternalFound = false;
externals.call(null, context, source, function(err, value) {
const callback = function (err, value) {
if (err) {
functionExternalFound = false;
} else {
functionExternalFound = findExternal(source, value, context);
functionExternalFound = findExternal(source, value, context, resolveSync);
}
});
};
// - for prior webpack 5, 'externals function' uses 3 arguments
// - for webpack 5, the count of arguments is less than 3
if (externals.length === 3) {
externals.call(null, context, source, callback);
} else {
const ctx = {
context,
request: source,
contextInfo: {
issuer: '',
issuerLayer: null,
compiler: '',
},
getResolve: () => (resolveContext, requestToResolve, cb) => {
if (cb) {
try {
cb(null, resolveSync(resolveContext, requestToResolve));
} catch (e) {
cb(e);
}
} else {
log('getResolve without callback not supported');
return Promise.reject(new Error('Not supported'));
}
},
};
const result = externals.call(null, ctx, callback);
// todo handling Promise object (using synchronous-promise package?)
if (result && result.then) {
log('Asynchronous functions for externals not supported');
}
}
return functionExternalFound;
}

Expand Down
29 changes: 29 additions & 0 deletions resolvers/webpack/test/externals.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ const webpack = require('../index');
const file = path.join(__dirname, 'files', 'dummy.js');

describe('externals', function () {
const settingsWebpack5 = {
config: require(path.join(__dirname, './files/webpack.config.webpack5.js')),
};
const settingsWebpack5Async = {
config: require(path.join(__dirname, './files/webpack.config.webpack5.async-externals.js')),
};

it('works on just a string', function () {
const resolved = webpack.resolve('bootstrap', file);
expect(resolved).to.have.property('found', true);
Expand All @@ -32,4 +39,26 @@ describe('externals', function () {
expect(resolved).to.have.property('found', true);
expect(resolved).to.have.property('path', null);
});

it('works on a function (synchronous) for webpack 5', function () {
const resolved = webpack.resolve('underscore', file, settingsWebpack5);
expect(resolved).to.have.property('found', true);
expect(resolved).to.have.property('path', null);
});

it('works on a function (synchronous) which uses getResolve for webpack 5', function () {
const resolved = webpack.resolve('graphql', file, settingsWebpack5);
expect(resolved).to.have.property('found', true);
expect(resolved).to.have.property('path', null);
});

it('prevents using an asynchronous function for webpack 5', function () {
const resolved = webpack.resolve('underscore', file, settingsWebpack5Async);
expect(resolved).to.have.property('found', false);
});

it('prevents using a function which uses Promise returned by getResolve for webpack 5', function () {
const resolved = webpack.resolve('graphql', file, settingsWebpack5Async);
expect(resolved).to.have.property('found', false);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module.exports = {
externals: [
{ 'jquery': 'jQuery' },
'bootstrap',
async function ({ request },) {
if (request === 'underscore') {
return 'underscore'
}
},
function ({ request, getResolve }, callback) {
if (request === 'graphql') {
const resolve = getResolve()
// dummy call (some-module should be resolved on __dirname)
resolve(__dirname, 'some-module').then(
function () { callback(null, 'graphql') },
function (e) { callback(e) }
)
}
},
],
}
27 changes: 27 additions & 0 deletions resolvers/webpack/test/files/webpack.config.webpack5.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module.exports = {
externals: [
{ 'jquery': 'jQuery' },
'bootstrap',
function ({ request }, callback) {
if (request === 'underscore') {
return callback(null, 'underscore')
}
callback()
},
function ({ request, getResolve }, callback) {
if (request === 'graphql') {
const resolve = getResolve()
// dummy call (some-module should be resolved on __dirname)
resolve(__dirname, 'some-module', function (err, value) {
if (err) {
callback(err)
} else {
callback(null, 'graphql')
}
})
} else {
callback()
}
},
],
}

0 comments on commit 06d7258

Please sign in to comment.