diff --git a/examples/razzle/razzle.config.js b/examples/razzle/razzle.config.js index d90b12303..183a7c89b 100644 --- a/examples/razzle/razzle.config.js +++ b/examples/razzle/razzle.config.js @@ -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 }, + }), ] } diff --git a/packages/server/src/util.js b/packages/server/src/util.js index ad2d94e8f..4cb99edae 100644 --- a/packages/server/src/util.js +++ b/packages/server/src/util.js @@ -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) => { diff --git a/packages/webpack-plugin/README.md b/packages/webpack-plugin/README.md index 144c3bace..5142573a7 100644 --- a/packages/webpack-plugin/README.md +++ b/packages/webpack-plugin/README.md @@ -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 }) diff --git a/packages/webpack-plugin/src/index.js b/packages/webpack-plugin/src/index.js index 0d302d2ac..c31bbaa16 100644 --- a/packages/webpack-plugin/src/index.js +++ b/packages/webpack-plugin/src/index.js @@ -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 @@ -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) { @@ -38,64 +45,19 @@ 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') { @@ -103,7 +65,7 @@ class LoadablePlugin { } } - fs.writeFileSync(filePath, manifest) + fs.writeFileSync(outputFile, manifest) } apply(compiler) { diff --git a/website/src/pages/docs/api-loadable-webpack-plugin.mdx b/website/src/pages/docs/api-loadable-webpack-plugin.mdx index 3103d2b05..993f8d10c 100644 --- a/website/src/pages/docs/api-loadable-webpack-plugin.mdx +++ b/website/src/pages/docs/api-loadable-webpack-plugin.mdx @@ -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 })