text: const fs = require('fs')
  const path = require('path')
  const webpack = require('webpack')
  const TerserPlugin = require('terser-webpack-plugin');
  
  const electronRoot = path.resolve(__dirname, '../..')
  
  const onlyPrintingGraph = !!process.env.PRINT_WEBPACK_GRAPH
  
  class AccessDependenciesPlugin {
    apply(compiler) {
      // Only hook into webpack when we are printing the dependency graph
      if (!onlyPrintingGraph) return
  
      compiler.hooks.compilation.tap('AccessDependenciesPlugin', compilation => {
        compilation.hooks.finishModules.tap('AccessDependenciesPlugin', modules => {
          const filePaths = modules.map(m => m.resource).filter(p => p).map(p => path.relative(electronRoot, p))
          console.info(JSON.stringify(filePaths))
        })
      })
    }
  }
  
  const defines = {
    BUILDFLAG: onlyPrintingGraph ? '(a => a)' : ''
  }
  
  const buildFlagsPrefix = '--buildflags='
  const buildFlagArg = process.argv.find(arg => arg.startsWith(buildFlagsPrefix));
  
  if (buildFlagArg) {
    const buildFlagPath = buildFlagArg.substr(buildFlagsPrefix.length)
  
    const flagFile = fs.readFileSync(buildFlagPath, 'utf8')
    for (const line of flagFile.split(/(\r\n|\r|\n)/g)) {
      const flagMatch = line.match(/#define BUILDFLAG_INTERNAL_(.+?)\(\) \(([01])\)/)
      if (flagMatch) {
        const [, flagName, flagValue] = flagMatch;
        defines[flagName] = JSON.stringify(Boolean(parseInt(flagValue, 10)));
      }
    }
  }
  
  const ignoredModules = []
  
  if (defines['ENABLE_DESKTOP_CAPTURER'] === 'false') {
    ignoredModules.push(
      '@electron/internal/browser/desktop-capturer',
      '@electron/internal/browser/api/desktop-capturer',
      '@electron/internal/renderer/api/desktop-capturer'
    )
  }
  
  if (defines['ENABLE_REMOTE_MODULE'] === 'false') {
    ignoredModules.push(
      '@electron/internal/browser/remote/server',
      '@electron/internal/renderer/api/remote'
    )
  }
  
  if (defines['ENABLE_VIEWS_API'] === 'false') {
    ignoredModules.push(
      '@electron/internal/browser/api/views/image-view.js'
    )
  }
  
  module.exports = ({
    alwaysHasNode,
    loadElectronFromAlternateTarget,
    targetDeletesNodeGlobals,
    target,
    wrapInitWithProfilingTimeout
  }) => {
    let entry = path.resolve(electronRoot, 'lib', target, 'init.ts')
    if (!fs.existsSync(entry)) {
      entry = path.resolve(electronRoot, 'lib', target, 'init.js')
    }
  
    return ({
      mode: 'development',
      devtool: false,
      entry,
      target: alwaysHasNode ? 'node' : 'web',
      output: {
        filename: `${target}.bundle.js`
      },
      wrapInitWithProfilingTimeout,
      resolve: {
        alias: {
          '@electron/internal': path.resolve(electronRoot, 'lib'),
          'electron': path.resolve(electronRoot, 'lib', loadElectronFromAlternateTarget || target, 'api', 'exports', 'electron.ts'),
          // Force timers to resolve to our dependency that doesn't use window.postMessage
          'timers': path.resolve(electronRoot, 'node_modules', 'timers-browserify', 'main.js')
        },
        extensions: ['.ts', '.js']
      },
      module: {
        rules: [{
          test: (moduleName) => !onlyPrintingGraph && ignoredModules.includes(moduleName),
          loader: 'null-loader',
        }, {
          test: /\.ts$/,
          loader: 'ts-loader',
          options: {
            configFile: path.resolve(electronRoot, 'tsconfig.electron.json'),
            transpileOnly: onlyPrintingGraph,
            ignoreDiagnostics: [
              // File '{0}' is not under 'rootDir' '{1}'.
              6059,
            ]
          }
        }]
      },
      node: {
        __dirname: false,
        __filename: false,
        // We provide our own "timers" import above, any usage of setImmediate inside
        // one of our renderer bundles should import it from the 'timers' package
        setImmediate: false,
      },
      optimization: {
        minimize: true,
        minimizer: [
          new TerserPlugin({
            terserOptions: {
              keep_classnames: true,
              keep_fnames: true,
            },
          }),
        ],
      },
      plugins: [
        new AccessDependenciesPlugin(),
        ...(targetDeletesNodeGlobals ? [
          new webpack.ProvidePlugin({
            process: ['@electron/internal/renderer/webpack-provider', 'process'],
            global: ['@electron/internal/renderer/webpack-provider', '_global'],
            Buffer: ['@electron/internal/renderer/webpack-provider', 'Buffer'],
          })
        ] : []),
        new webpack.ProvidePlugin({
          Promise: ['@electron/internal/common/webpack-globals-provider', 'Promise'],
        }),
        new webpack.DefinePlugin(defines),
      ]
    })
  }
  