Skip to content

Instantly share code, notes, and snippets.

@Hendrixer
Created August 28, 2016 19:17
Show Gist options
  • Select an option

  • Save Hendrixer/46bcf8ddfa3edad2f28e007f9cff6d43 to your computer and use it in GitHub Desktop.

Select an option

Save Hendrixer/46bcf8ddfa3edad2f28e007f9cff6d43 to your computer and use it in GitHub Desktop.

Revisions

  1. Hendrixer created this gist Aug 28, 2016.
    58 changes: 58 additions & 0 deletions InstallMissingModules.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,58 @@
    const thenify = require('thenify')
    const webpack = require('webpack')
    const MemoryFS = require('memory-fs')
    const validateNpmPackageName = require('validate-npm-package-name')

    class InstallMissingModules {
    constructor(options) {
    this.options = options
    }

    apply(compiler) {
    const runCompilerThenCallback = (...args) => {
    const callback = args[args.length - 1]
    this._runCompiler(compiler)
    .then(() => callback(), callback)
    };

    compiler.plugin(`run`, runCompilerThenCallback)
    compiler.plugin(`watch-run`, runCompilerThenCallback)
    }

    _runCompiler(compiler) {
    const { options } = compiler
    const { plugins } = options

    return this._findMissingModuleList(Object.assign({}, options, {
    plugins: plugins.filter(plugin => plugin.constructor !== InstallMissingModules)
    }))
    .then(list => this.options.callback(list))
    }

    _findMissingModuleList(webpackConfig) {
    const webpackCompiler = webpack(webpackConfig)
    webpackCompiler.outputFileSystem = new MemoryFS()
    return new Promise((resolve, reject) => {
    webpackCompiler.run((error, stats) => {
    const { errors } = stats.toJson()

    const list = errors.map(error => {
    if (/Module not found: Error: Cannot resolve module '(\S+)' in/.test(error)) {
    return RegExp.$1
    } else if (/Cannot find module '(\S+)'/.test(error)) {
    return RegExp.$1
    } else {
    return undefined
    }
    })
    .filter(it => !!it)
    .map(it => it.split('/')[0])
    .filter(it => validateNpmPackageName(it).validForNewPackages)

    resolve(list)
    })
    })
    }
    }

    module.exports = InstallMissingModules