Skip to content

Instantly share code, notes, and snippets.

@dlebedynskyi
Created November 20, 2018 23:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dlebedynskyi/7fd345f3d193bb78790c0e122e23012c to your computer and use it in GitHub Desktop.
Save dlebedynskyi/7fd345f3d193bb78790c0e122e23012c to your computer and use it in GitHub Desktop.
loadable-component emit file webpack plugin
const path = require('path')
const fs = require('fs')
class LoadablePlugin {
constructor({ filename = 'loadable-stats.json', writeToDisk = false } = {}) {
this.opts = { filename, writeToDisk }
}
gather = (hookCompiler, callback) => {
const stats = hookCompiler.getStats().toJson({
hash: true,
publicPath: true,
assets: true,
chunks: false,
modules: false,
source: false,
errorDetails: false,
timings: false,
})
const result = JSON.stringify(stats, null, 2)
hookCompiler.assets[this.opts.filename] = {
source() {
return result
},
size() {
return result.length
},
}
if (this.opts.writeToDisk) {
this.writeAssetsFile(result)
}
callback()
}
/**
* Check if request is from Dev Server
* aka webpack-dev-server
* @method isRequestFromDevServer
* @returns {boolean} - True or False
*/
isRequestFromDevServer = () => {
if (process.argv.some(arg => arg.includes('webpack-dev-server'))) {
return true
}
return (
this.compiler.outputFileSystem &&
this.compiler.outputFileSystem.constructor.name === 'MemoryFileSystem'
)
}
/**
* Get assets manifest output path
* @see https://github.com/webdeveric/webpack-assets-manifest/blob/master/src/WebpackAssetsManifest.js
* @method getManifestOutputPath
* @returns {string} - Output path containing path + filename.
*/
getManifestOutputPath = () => {
if (path.isAbsolute(this.opts.filename)) {
return this.opts.filename
}
if (this.isRequestFromDevServer() && this.compiler.options.devServer) {
let outputPath =
this.compiler.options.devServer.outputPath ||
this.compiler.outputPath ||
'/'
if (outputPath === '/') {
// eslint-disable-next-line no-console
console.warn(
'Please use an absolute path in options.output when using webpack-dev-server.',
)
outputPath = this.compiler.context || process.cwd()
}
return path.resolve(outputPath, this.opts.filename)
}
return path.resolve(this.compiler.outputPath, this.opts.filename)
}
/**
* Write Assets Manifest file
* @method writeAssetsFile
*/
writeAssetsFile = manifest => {
const filePath = this.getManifestOutputPath()
const fileDir = path.dirname(filePath)
try {
if (!fs.existsSync(fileDir)) {
fs.mkdirSync(fileDir)
}
} catch (err) {
if (err.code !== 'EEXIST') {
throw err
}
}
fs.writeFileSync(filePath, manifest)
}
apply(compiler) {
// Add a custom output.jsonpFunction: __LOADABLE_LOADED_CHUNKS__
compiler.options.output.jsonpFunction = '__LOADABLE_LOADED_CHUNKS__'
compiler.hooks.emit.tapAsync('@loadable/webpack-plugin', this.gather)
}
}
module.exports = LoadablePlugin
module.exports.default = LoadablePlugin
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment