index.js 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. const utils = require('./utils');
  2. const scopedModuleRegex = new RegExp(
  3. '@[a-zA-Z0-9][\\w-.]+/[a-zA-Z0-9][\\w-.]+([a-zA-Z0-9./]+)?',
  4. 'g'
  5. );
  6. function getModuleName(request, includeAbsolutePaths) {
  7. let req = request;
  8. const delimiter = '/';
  9. if (includeAbsolutePaths) {
  10. req = req.replace(/^.*?\/node_modules\//, '');
  11. }
  12. // check if scoped module
  13. if (scopedModuleRegex.test(req)) {
  14. // reset regexp
  15. scopedModuleRegex.lastIndex = 0;
  16. return req.split(delimiter, 2).join(delimiter);
  17. }
  18. return req.split(delimiter)[0];
  19. }
  20. module.exports = function nodeExternals(options) {
  21. options = options || {};
  22. const mistakes = utils.validateOptions(options) || [];
  23. if (mistakes.length) {
  24. mistakes.forEach((mistake) => {
  25. utils.error(mistakes.map((mistake) => mistake.message));
  26. utils.log(mistake.message);
  27. });
  28. }
  29. const webpackInternalAllowlist = [/^webpack\/container\/reference\//];
  30. const allowlist = []
  31. .concat(webpackInternalAllowlist)
  32. .concat(options.allowlist || []);
  33. const binaryDirs = [].concat(options.binaryDirs || ['.bin']);
  34. const importType = options.importType || 'commonjs';
  35. const modulesDir = options.modulesDir || 'node_modules';
  36. const modulesFromFile = !!options.modulesFromFile;
  37. const includeAbsolutePaths = !!options.includeAbsolutePaths;
  38. const additionalModuleDirs = options.additionalModuleDirs || [];
  39. // helper function
  40. function isNotBinary(x) {
  41. return !utils.contains(binaryDirs, x);
  42. }
  43. // create the node modules list
  44. let nodeModules = modulesFromFile
  45. ? utils.readFromPackageJson(options.modulesFromFile)
  46. : utils.readDir(modulesDir).filter(isNotBinary);
  47. additionalModuleDirs.forEach(function (additionalDirectory) {
  48. nodeModules = nodeModules.concat(
  49. utils.readDir(additionalDirectory).filter(isNotBinary)
  50. );
  51. });
  52. // return an externals function
  53. return function (...args) {
  54. const [arg1, arg2, arg3] = args;
  55. // let context = arg1;
  56. let request = arg2;
  57. let callback = arg3;
  58. // in case of webpack 5
  59. if (arg1 && arg1.context && arg1.request) {
  60. // context = arg1.context;
  61. request = arg1.request;
  62. callback = arg2;
  63. }
  64. const moduleName = getModuleName(request, includeAbsolutePaths);
  65. if (
  66. utils.contains(nodeModules, moduleName) &&
  67. !utils.containsPattern(allowlist, request)
  68. ) {
  69. if (typeof importType === 'function') {
  70. return callback(null, importType(request));
  71. }
  72. // mark this module as external
  73. // https://webpack.js.org/configuration/externals/
  74. return callback(null, importType + ' ' + request);
  75. }
  76. callback();
  77. };
  78. };