forked from mui/material-ui
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Webpack DLLs and HappyPack (mui#135)
Adds a HappyPack and Vendor DLL implementation to improve the development experience. The Vendor DLL is automatically calculated and build within the development server, reducing any management overhead. We use a md5 hash against the project's dependencies to know when to rebuild the vendor dll.
- Loading branch information
Showing
11 changed files
with
335 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,3 +34,6 @@ npm-debug.log | |
|
||
# Flow Coverage Report | ||
flow-coverage/ | ||
|
||
# Happypack | ||
.happypack |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ | ||
"rules": { | ||
"global-require": 0, | ||
"no-console": 0, | ||
"no-underscore-dangle": 0, | ||
"import/no-extraneous-dependencies": 0, | ||
"import/no-dynamic-require": 0, | ||
"import/newline-after-import": 0 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
const pathResolve = require('path').resolve; | ||
const appRootPath = require('app-root-path').toString(); | ||
const envVars = require('./envVars'); | ||
|
||
const dllName = 'vendor'; | ||
const bundleSubDir = '/client/dlls'; | ||
const dllOutputDir = pathResolve(appRootPath, envVars.BUNDLE_OUTPUT_PATH, `.${bundleSubDir}`); | ||
const dllWebPath = `${bundleSubDir}/${dllName}.js`; | ||
const dllPath = pathResolve(dllOutputDir, `${dllName}.js`); | ||
const dllJsonPath = pathResolve(dllOutputDir, `${dllName}.json`); | ||
const dependenciesHashFilePath = pathResolve(dllOutputDir, 'dependencies_hash'); | ||
|
||
module.exports = { | ||
dllName, | ||
dllOutputDir, | ||
dllPath, | ||
dllJsonPath, | ||
dependenciesHashFilePath, | ||
dllWebPath, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
const webpack = require('webpack'); | ||
const pathExtName = require('path').extname; | ||
const pathResolve = require('path').resolve; | ||
const md5 = require('md5'); | ||
const fs = require('fs'); | ||
const promisify = require('promisify-node'); | ||
const recursive = promisify(require('recursive-readdir')); | ||
const appRootPath = require('app-root-path').toString(); | ||
const vendorDLLPaths = require('../config/vendorDLLPaths'); | ||
const createNotification = require('./createNotification'); | ||
|
||
// ----------------------------------------------------------------------------- | ||
// PRIVATES | ||
|
||
const importRegex = /(from '|require\(')([\w\-_]+)/g; | ||
|
||
const { | ||
dllName, | ||
dllOutputDir, | ||
dllJsonPath, | ||
dependenciesHashFilePath, | ||
} = vendorDLLPaths; | ||
|
||
// 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 currentDependenciesHash = md5( | ||
JSON.stringify(require(pathResolve(appRootPath, 'package.json')).dependencies) | ||
); | ||
|
||
function webpackConfigFactory(modules) { | ||
return { | ||
// We only use this for development, so lets always include source maps. | ||
devtool: 'inline-source-map', | ||
entry: { [dllName]: modules }, | ||
output: { | ||
path: dllOutputDir, | ||
filename: `${dllName}.js`, | ||
library: dllName, | ||
}, | ||
plugins: [ | ||
new webpack.DllPlugin({ | ||
path: dllJsonPath, | ||
name: dllName, | ||
}), | ||
], | ||
}; | ||
} | ||
|
||
function buildVendorDLL() { | ||
return new Promise((resolve, reject) => { | ||
Promise.all([ | ||
recursive(pathResolve(appRootPath, 'src/client')), | ||
recursive(pathResolve(appRootPath, 'src/shared/universal')), | ||
]) | ||
.then(([clientFiles, universalFiles]) => { | ||
const isJsFile = file => pathExtName(file) === '.js'; | ||
const allJSFiles = [...clientFiles, ...universalFiles].filter(isJsFile); | ||
const modules = allJSFiles.reduce((acc, cur) => { | ||
const fileContents = fs.readFileSync(cur, 'utf8'); | ||
let match = importRegex.exec(fileContents); | ||
while (match != null) { | ||
acc.add(match[2]); | ||
match = importRegex.exec(fileContents); | ||
} | ||
return acc; | ||
}, new Set()); | ||
|
||
createNotification({ | ||
title: 'vendorDLL', | ||
level: 'info', | ||
message: 'Vendor DLL build complete. Check console for module list.', | ||
}); | ||
console.log([...modules]); | ||
|
||
const webpackConfig = webpackConfigFactory([...modules]); | ||
const vendorDLLCompiler = webpack(webpackConfig); | ||
vendorDLLCompiler.run((err) => { | ||
if (err) { | ||
reject(err); | ||
} | ||
// Update the dependency hash | ||
if (!fs.existsSync(dllOutputDir)) { | ||
fs.mkdirSync(dllOutputDir); | ||
} | ||
fs.writeFileSync(dependenciesHashFilePath, currentDependenciesHash); | ||
|
||
resolve(); | ||
}); | ||
}); | ||
}); | ||
} | ||
|
||
// ----------------------------------------------------------------------------- | ||
// DEFAULT EXPORT | ||
|
||
function ensureVendorDLLExists() { | ||
return new Promise((resolve, reject) => { | ||
if (!fs.existsSync(dependenciesHashFilePath)) { | ||
// builddll | ||
createNotification({ | ||
title: 'vendorDLL', | ||
level: 'warn', | ||
message: 'Generating a new vendor dll for boosted development performance...', | ||
}); | ||
buildVendorDLL().then(resolve).catch(reject); | ||
} else { | ||
// first check if the md5 hashes match | ||
const dependenciesHash = fs.readFileSync(dependenciesHashFilePath, 'utf8'); | ||
const dependenciesChanged = dependenciesHash !== currentDependenciesHash; | ||
|
||
if (dependenciesChanged) { | ||
createNotification({ | ||
title: 'vendorDLL', | ||
level: 'warn', | ||
message: 'New vendor dependencies detected. Regenerating the vendor dll...', | ||
}); | ||
buildVendorDLL().then(resolve).catch(reject); | ||
} else { | ||
createNotification({ | ||
title: 'vendorDLL', | ||
level: 'info', | ||
message: 'No changes to existing vendor dependencies. Using the existing vendor dll.', | ||
}); | ||
resolve(); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
module.exports = ensureVendorDLLExists; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.