Repository URL to install this package:
|
Version:
3.3.0 ▾
|
const { resolve } = require('path')
const { existsSync, writeFileSync, readFileSync } = require('fs')
const md5 = require('md5')
const webpack = require('webpack')
const { DllPlugin, DllReferencePlugin } = require('webpack')
const { config } = require('@skava/di')
const { log } = require('../../dist/utils')
const { resolveToRoot } = require('../../dist/resolveToRoot')
const appRootDir = config.get('appRootDir')
const pkgPath = process.cwd() + '/package.json'
const pkg = config.get('package') || require(pkgPath)
const exists = absolutePath => {
try {
return existsSync(absolutePath)
} catch (existsException) {
return false
}
}
const read = absolutePath => {
try {
return readFileSync(absolutePath, 'utf8')
} catch (existsException) {
console.log('___caught___')
console.error(existsException)
return false
}
}
const write = (absolutePath, content) => {
writeFileSync(absolutePath, content)
}
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`,
})
},
}
const bundledList = [
'react-dom',
'react-helmet',
'apollo-boost',
'apollo-cache-inmemory',
'apollo-client',
'apollo-link-error',
'react-fluckity',
'date-fns',
'lodash',
'ramda',
'uuid',
'shortid',
'classnames',
'cookie-parser',
'query-string',
'serialize-javascript',
'prop-types',
'fbjs',
'graphql',
'helmet',
'hoist-non-react-statics',
'json-stringify-safe',
'react-transition-group',
'url-search-params-polyfill',
'isomorphic-fetch',
'composition',
'chain-able-boost',
'chain-able-deps',
'chain-able-lego',
'@babel/polyfill',
'@skava/router',
'@skava/cookies',
'@skava/persistence',
'@skava/fixtures',
'@skava/is-error-like-response',
'ally.js',
'react-lazyload',
'xmobx',
'mobx',
'mobx-react',
'exotic',
'history',
'tslib',
].sort()
function createVendorDLL(bundleConfig = {}) {
const bundleName = 'development-browser-only'
const devDLLDependencies = bundledList
const name = '__dev_vendor_dll__'
const outputPathAbs = resolve(
appRootDir,
bundleConfig.outputPath || './public/static'
)
const resolveOutput = relative => resolve(outputPathAbs, relative)
config.set('outputPath', outputPathAbs)
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 = resolveOutput(`./${name}_hash`)
const dllPath = resolveOutput(`./${name}.json`)
// @todo do we need to resolve to node_modules as absolute?
// console.log(devDLLDependencies, dllDepsFromPkg)
function webpackConfigFactory() {
return {
mode: 'development',
// We only use this for development, so lets always include source maps.
devtool: 'inline-source-map',
// entry: devDLLDependencies,
entry: {
[name]: devDLLDependencies,
},
output: {
path: outputPathAbs,
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
write(vendorDLLHashFilePath, currentDependenciesHash)
successfullyCompiled()
}
return vendorDLLCompiler.run(onCompiler)
})
}
if (!exists(vendorDLLHashFilePath)) {
// build dll
logging.generating(bundleName)
return buildVendorDLL()
} else {
console.log('___else___')
// first check if the md5 hashes match
const dependenciesHash = read(vendorDLLHashFilePath)
const dependenciesChanged = dependenciesHash !== currentDependenciesHash
if (dependenciesChanged) {
logging.regenerating(bundleName)
return buildVendorDLL()
} else {
logging.unchanged(bundleName)
return Promise.resolve()
}
}
}
function inject(webpackConfig) {
// const configName = 'development-browser-only'
// const distFolder = './dist/dist/bundled'
// Install the vendor DLL plugin.
// const manifestPath = resolveToRoot(`${distFolder}/${configName}/${dllFileName}.json`)
const dllFileName = '__dev_vendor_dll__'
const distFolder = config.get('outputPath')
const manifestPath = resolveToRoot(`${distFolder}/${dllFileName}.json`)
// eslint-disable-next-line
const manifest = require(manifestPath)
const plugin = new DllReferencePlugin({ manifest })
webpackConfig.plugins.push(plugin)
}
exports.create = createVendorDLL
exports.inject = inject