Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
@skava/bs / src / development / dll / create.ts
Size: Mime:
import { resolve } from 'path'
import { existsSync, writeFileSync, readFileSync } from 'fs'
import md5 from 'md5'
import webpack from 'webpack'
import { DllPlugin } from 'webpack'
import { config } from '@skava/di'
// import { resolveToRoot, appRootDir } from '../../resolveToRoot'
import getConfig from '../../oneConfig/getConfigForEnv'
import { log } from '../../utils'

// const pkg = require('../../../package.json')
// const pkg = {
//   devDependencies: {},
//   dependencies: {},
//   bundledDependencies: [],
// }
const appRootDir = config.get('appRootDir')
const pkg = config.get('package')

const logging = {
  generating(bundleName) {
    log({
      title: 'vendorDLL',
      level: 'warn',
      message: `Generating a new "${bundleName}" Vendor DLL for boosted development performance.
      The Vendor DLL helps to speed up your development workflow by reducing Webpack build times.  It does this by seperating Vendor DLLs from your primary bundles, thereby allowing Webpack to ignore them when having to rebuild your code for changes.  We recommend that you add all your client bundle specific dependencies to the Vendor DLL configuration (within /config).`,
    })
  },
  regenerating(bundleName) {
    log({
      title: 'vendorDLL',
      level: 'warn',
      message: `New "${bundleName}" vendor dependencies detected. Regenerating the vendor dll...`,
    })
  },
  unchanged(bundleName) {
    log({
      title: 'vendorDLL',
      level: 'info',
      message: `No changes to existing "${bundleName}" vendor dependencies. Using the existing vendor dll.`,
    })
  },
  complete(devDLLDependencies) {
    log({
      title: 'vendorDLL',
      level: 'info',
      message: `Vendor DLL build complete. The following dependencies have been included:\n\t-${devDLLDependencies.join(
        '\n\t-'
      )}\n`,
    })
  },
}

function createVendorDLL(bundleName, bundleConfig) {
  const dllConfig = getConfig('bundles.client.devVendorDLL')
  const devDLLDependencies = dllConfig.include.sort()
  const { name } = dllConfig
  const { outputPath } = bundleConfig

  const resolveDepAgainstPkg = dep => [dep, pkg.dependencies[dep], pkg.devDependencies[dep]]

  // We calculate a hash of the package.json's dependencies, which we can use
  // to determine if dependencies have changed since the last time we built
  // the vendor dll.
  const dllDepsFromPkg = devDLLDependencies.map(resolveDepAgainstPkg)

  const dllDepsAsString = JSON.stringify(dllDepsFromPkg)

  // We do this to include any possible version numbers we may have for
  // a dependency. If these change then our hash should too, which will
  // result in a new dev dll build.
  const currentDependenciesHash = md5(dllDepsAsString)

  const vendorDLLHashFilePath = resolve(appRootDir, outputPath, `${name}_hash`)

  function webpackConfigFactory() {
    const dllPath = resolve(appRootDir, outputPath, `./${name}.json`)

    return {
      // We only use this for development, so lets always include source maps.
      devtool: 'inline-source-map',
      entry: {
        [name]: devDLLDependencies,
      },
      output: {
        path: outputPath,
        filename: `${name}.js`,
        library: name,
      },
      plugins: [
        new DllPlugin({
          path: dllPath,
          name,
        }),
      ],
    }
  }

  function buildVendorDLL() {
    logging.complete(devDLLDependencies)

    const webpackConfig = webpackConfigFactory()
    const vendorDLLCompiler = webpack(webpackConfig)

    return new Promise((successfullyCompiled, reject) => {
      const onCompiler = (vendorCompilationError, stats = {}) => {
        if (vendorCompilationError) {
          reject(vendorCompilationError)
        }

        // Update the dependency hash
        writeFileSync(vendorDLLHashFilePath, currentDependenciesHash)
        successfullyCompiled()
      }
      return vendorDLLCompiler.run(onCompiler)
    })
  }

  if (!existsSync(vendorDLLHashFilePath)) {
    // builddll
    logging.generating(bundleName)
    return buildVendorDLL()
  } else {
    // first check if the md5 hashes match
    const dependenciesHash = readFileSync(vendorDLLHashFilePath, 'utf8')
    const dependenciesChanged = dependenciesHash !== currentDependenciesHash

    if (dependenciesChanged) {
      logging.regenerating(bundleName)
      return buildVendorDLL()
    } else {
      logging.unchanged(bundleName)
      return Promise.resolve()
    }
  }
}

export { createVendorDLL }