Skip to content

Commit

Permalink
feat(webpack-plugin): support custom path in writeToDisk option (#187)
Browse files Browse the repository at this point in the history
  • Loading branch information
tadeuszwojcik authored and gregberge committed Jan 17, 2019
1 parent c69c503 commit 4a6f84f
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 77 deletions.
7 changes: 5 additions & 2 deletions examples/razzle/razzle.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ module.exports = {
const appConfig = Object.assign({}, config)

if (target === 'web') {
const filename = path.resolve(__dirname, 'build/loadable-stats.json')
const filename = path.resolve(__dirname, 'build')

appConfig.plugins = [
...appConfig.plugins,
new LoadableWebpackPlugin({ writeToDisk: true, filename }),
new LoadableWebpackPlugin({
outputAsset: false,
writeToDisk: { filename },
}),
]
}

Expand Down
12 changes: 9 additions & 3 deletions packages/server/src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@ export const smartRequire = modulePath => {
clearModuleCache(modulePath)
}

// Use eval to prevent Webpack from compiling it
// Use __non_webpack_require__ to prevent Webpack from compiling it
// when the server-side code is compiled with Webpack
// eslint-disable-next-line no-eval
return eval('module.require')(modulePath)
// eslint-disable-next-line camelcase
if (typeof __non_webpack_require__ !== 'undefined') {
// eslint-disable-next-line no-undef
return __non_webpack_require__(modulePath)
}

// eslint-disable-next-line global-require, import/no-dynamic-require
return require(modulePath)
}

export const joinURLPath = (...paths) => {
Expand Down
11 changes: 6 additions & 5 deletions packages/webpack-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@ module.exports = {

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`) |
| Arguments | Description |
| --------------------- | ------------------------------------------------- |
| `options` | Optional options |
| `options.filename` | Stats filename (default to `loadable-stats.json`) |
| `options.path` | Stats file path (default to webpack config `output.path`) |
| `options.writeToDisk` | Always write assets to disk (default to `false`) |

```js
new LoadablePlugin({ filename: 'stats.json', writeToDisk: true })
Expand Down
86 changes: 24 additions & 62 deletions packages/webpack-plugin/src/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
const path = require('path')
const nodePath = require('path')
const fs = require('fs')

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

// The Webpack compiler instance
this.compiler = null
Expand All @@ -22,13 +27,15 @@ class LoadablePlugin {
})
const result = JSON.stringify(stats, null, 2)

hookCompiler.assets[this.opts.filename] = {
source() {
return result
},
size() {
return result.length
},
if (this.opts.outputAsset) {
hookCompiler.assets[this.opts.filename] = {
source() {
return result
},
size() {
return result.length
},
}
}

if (this.opts.writeToDisk) {
Expand All @@ -38,72 +45,27 @@ class LoadablePlugin {
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)
const outputFolder =
this.opts.writeToDisk.filename || this.compiler.options.output.path

const outputFile = nodePath.resolve(outputFolder, this.opts.filename)

try {
if (!fs.existsSync(fileDir)) {
fs.mkdirSync(fileDir)
if (!fs.existsSync(outputFolder)) {
fs.mkdirSync(outputFolder)
}
} catch (err) {
if (err.code !== 'EEXIST') {
throw err
}
}

fs.writeFileSync(filePath, manifest)
fs.writeFileSync(outputFile, manifest)
}

apply(compiler) {
Expand Down
9 changes: 4 additions & 5 deletions website/src/pages/docs/api-loadable-webpack-plugin.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ order: 30

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`) |
| Arguments | Description |
| ------------------------------ | ------------------------------------------------- |
| `options` | Optional options |
| `options.writeToDisk.filename` | Write assets to disk at given `filename` location |

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

0 comments on commit 4a6f84f

Please sign in to comment.