Skip to content

Commit

Permalink
feat(webpack-plugin): add writeToDisk option (gregberge#161)
Browse files Browse the repository at this point in the history
  • Loading branch information
dlebedynskyi committed Nov 26, 2018
1 parent 8d4f8b3 commit 9457a54
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 23 deletions.
18 changes: 18 additions & 0 deletions packages/webpack-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ module.exports = {
}
```

## API

### LoadablePlugin

Create a webpack loadable plugin.

| Arguments | Description |
| --------------------- | ------------------------------------------------- |
| `options` | Optional options |
| `options.filename` | Stats filename (default to `loadable-stats.json`) |
| `options.writeToDisk` | Always write assets to disk (default to `false`) |

```js
new LoadablePlugin({ filename: 'stats.json', writeToDisk: true })
```

> Writing file to disk can be useful if you are using `razzle` or `webpack-dev-server`.
## License

MIT
126 changes: 103 additions & 23 deletions packages/webpack-plugin/src/index.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,113 @@
const path = require('path')
const fs = require('fs')

class LoadablePlugin {
constructor({ filename = 'loadable-stats.json' } = {}) {
this.opts = { filename }
constructor({ filename = 'loadable-stats.json', writeToDisk = false } = {}) {
this.opts = { filename, writeToDisk }
}

handleEmit = (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
*
* @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.tap('@loadable/webpack-plugin', hookCompiler => {
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
},
}
})
compiler.hooks.emit.tapAsync('@loadable/webpack-plugin', this.handleEmit)
}
}

Expand Down

0 comments on commit 9457a54

Please sign in to comment.