UNPKG

webpack-watched-glob-entries-plugin

Version:

Webpack plugin to glob directories for entry files and also watch them for changes

156 lines (126 loc) 4.49 kB
// Fetch depencies const glob = require('glob'); const globParent = require('glob-parent'); const path = require('path'); let directories = []; /** * class WebpackWatchedGlobEntries */ class WebpackWatchedGlobEntries { /** * * @param globs * @param globOptions * @param pluginOptions_ * @returns {Function} */ static getEntries(globs, globOptions, pluginOptions_) { // Type check pluginOptions_ if (typeof pluginOptions_ !== 'undefined' && typeof pluginOptions_ !== 'object') { throw new TypeError('pluginOptions_ must be an object'); } // Options defaults const pluginOptions = Object.assign({ basename_as_entry_id: false }, pluginOptions_); return function() { // Check if globs are provided properly if (typeof globs !== 'string' && !Array.isArray(globs)) { throw new TypeError('globOptions must be a string or an array of strings'); } // Check globOptions if provided properly if (globOptions && typeof globOptions !== 'object') { throw new TypeError('globOptions must be an object'); } // Make entries an array if (!Array.isArray(globs)) { globs = [globs]; } // let globbedFiles = {}; // Map through the globs globs.forEach(function(globString) { let base = globParent(globString, {}); // Dont add if its already in the directories if (directories.indexOf(base) === -1) { directories.push(base); } // Get the globbedFiles let files = WebpackWatchedGlobEntries.getFiles(globString, globOptions, pluginOptions.basename_as_entry_name); // Set the globbed files for (const entryName in files) { if (!globbedFiles[entryName]) { globbedFiles[entryName] = []; } for (const file of files[entryName]) { if (!globbedFiles[entryName].includes(file)) { globbedFiles[entryName].push(file); } } } }); return globbedFiles; }; } /** * Create webpack file entry object * @param globString * @param globOptions * @param basename_as_entry_name * @returns {Object} */ static getFiles(globString, globOptions, basename_as_entry_name) { const files = {}; let base = globParent(globString, {}); glob.sync(globString, globOptions).forEach(function(file) { // Format the entryName let entryName = path .relative(base, file) .replace(path.extname(file), '') .split(path.sep) .join('/'); if (basename_as_entry_name) { entryName = path.basename(entryName); } if (!files[entryName]) { files[entryName] = []; } if (!files[entryName].includes(file)) { // Add the entry to the files obj files[entryName].push(file); } }); return files; } /** * Install Plugin * @param {Object} compiler */ apply(compiler) { if (compiler.hooks) { // Support Webpack >= 4 compiler.hooks.afterCompile.tapAsync(this.constructor.name, this.afterCompile.bind(this)); } else { // Support Webpack < 4 compiler.plugin('after-compile', this.afterCompile); } } /** * After compiling, give webpack the globbed files * @param {Object} compilation * @param {Function} callback */ afterCompile(compilation, callback) { if (Array.isArray(compilation.contextDependencies)) { // Support Webpack < 4 compilation.contextDependencies = compilation.contextDependencies.concat(directories); } else { // Support Webpack >= 4 for (const directory of directories) { compilation.contextDependencies.add(path.normalize(directory)); } } callback(); } } module.exports = WebpackWatchedGlobEntries;