diff options
Diffstat (limited to 'node_modules/webpack-dev-middleware/lib')
| -rw-r--r-- | node_modules/webpack-dev-middleware/lib/DevMiddlewareError.js | 5 | ||||
| -rw-r--r-- | node_modules/webpack-dev-middleware/lib/context.js | 103 | ||||
| -rw-r--r-- | node_modules/webpack-dev-middleware/lib/fs.js | 73 | ||||
| -rw-r--r-- | node_modules/webpack-dev-middleware/lib/middleware.js | 98 | ||||
| -rw-r--r-- | node_modules/webpack-dev-middleware/lib/reporter.js | 30 | ||||
| -rw-r--r-- | node_modules/webpack-dev-middleware/lib/util.js | 173 |
6 files changed, 482 insertions, 0 deletions
diff --git a/node_modules/webpack-dev-middleware/lib/DevMiddlewareError.js b/node_modules/webpack-dev-middleware/lib/DevMiddlewareError.js new file mode 100644 index 00000000..0ae2ce81 --- /dev/null +++ b/node_modules/webpack-dev-middleware/lib/DevMiddlewareError.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = class DevMiddlewareError extends Error { + +}; diff --git a/node_modules/webpack-dev-middleware/lib/context.js b/node_modules/webpack-dev-middleware/lib/context.js new file mode 100644 index 00000000..5e9abba7 --- /dev/null +++ b/node_modules/webpack-dev-middleware/lib/context.js @@ -0,0 +1,103 @@ +'use strict'; + +const weblog = require('webpack-log'); + +module.exports = function ctx(compiler, options) { + const context = { + state: false, + webpackStats: null, + callbacks: [], + options, + compiler, + watching: null, + forceRebuild: false + }; + + if (options.logger) { + context.log = options.logger; + } else { + context.log = weblog({ + level: options.logLevel || 'info', + name: 'wdm', + timestamp: options.logTime + }); + } + + const { log } = context; + + function done(stats) { + // We are now on valid state + context.state = true; + context.webpackStats = stats; + + // Do the stuff in nextTick, because bundle may be invalidated + // if a change happened while compiling + process.nextTick(() => { + // check if still in valid state + if (!context.state) { + return; + } + + // print webpack output + context.options.reporter(context.options, { + log, + state: true, + stats + }); + + // execute callback that are delayed + const cbs = context.callbacks; + context.callbacks = []; + cbs.forEach((cb) => { + cb(stats); + }); + }); + + // In lazy mode, we may issue another rebuild + if (context.forceRebuild) { + context.forceRebuild = false; + rebuild(); + } + } + + function invalid(callback) { + if (context.state) { + context.options.reporter(context.options, { + log, + state: false + }); + } + + // We are now in invalid state + context.state = false; + if (typeof callback === 'function') { + callback(); + } + } + + function rebuild() { + if (context.state) { + context.state = false; + context.compiler.run((err) => { + if (err) { + log.error(err.stack || err); + if (err.details) { + log.error(err.details); + } + } + }); + } else { + context.forceRebuild = true; + } + } + + context.rebuild = rebuild; + context.compiler.hooks.invalid.tap('WebpackDevMiddleware', invalid); + context.compiler.hooks.run.tap('WebpackDevMiddleware', invalid); + context.compiler.hooks.done.tap('WebpackDevMiddleware', done); + context.compiler.hooks.watchRun.tap('WebpackDevMiddleware', (comp, callback) => { + invalid(callback); + }); + + return context; +}; diff --git a/node_modules/webpack-dev-middleware/lib/fs.js b/node_modules/webpack-dev-middleware/lib/fs.js new file mode 100644 index 00000000..1823b67a --- /dev/null +++ b/node_modules/webpack-dev-middleware/lib/fs.js @@ -0,0 +1,73 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const MemoryFileSystem = require('memory-fs'); +const { colors } = require('webpack-log'); +const NodeOutputFileSystem = require('webpack/lib/node/NodeOutputFileSystem'); +const DevMiddlewareError = require('./DevMiddlewareError'); + +const { mkdirp } = new NodeOutputFileSystem(); + +module.exports = { + toDisk(context) { + const compilers = context.compiler.compilers || [context.compiler]; + for (const compiler of compilers) { + compiler.hooks.afterEmit.tap('WebpackDevMiddleware', (compilation) => { + const { assets } = compilation; + const { log } = context; + const { writeToDisk: filter } = context.options; + let { outputPath } = compiler; + + if (outputPath === '/') { + outputPath = compiler.context; + } + + for (const assetPath of Object.keys(assets)) { + const asset = assets[assetPath]; + const source = asset.source(); + const isAbsolute = path.isAbsolute(assetPath); + const writePath = isAbsolute ? assetPath : path.join(outputPath, assetPath); + const relativePath = path.relative(process.cwd(), writePath); + const allowWrite = filter && typeof filter === 'function' ? filter(writePath) : true; + + if (allowWrite) { + let output = source; + + mkdirp.sync(path.dirname(writePath)); + + if (Array.isArray(source)) { + output = source.join('\n'); + } + + try { + fs.writeFileSync(writePath, output, 'utf-8'); + log.debug(colors.cyan(`Asset written to disk: ${relativePath}`)); + } catch (e) { + log.error(`Unable to write asset to disk:\n${e}`); + } + } + } + }); + } + }, + + setFs(context, compiler) { + if (typeof compiler.outputPath === 'string' && !path.posix.isAbsolute(compiler.outputPath) && !path.win32.isAbsolute(compiler.outputPath)) { + throw new DevMiddlewareError('`output.path` needs to be an absolute path or `/`.'); + } + + let fileSystem; + // store our files in memory + const isMemoryFs = !compiler.compilers && compiler.outputFileSystem instanceof MemoryFileSystem; + + if (isMemoryFs) { + fileSystem = compiler.outputFileSystem; + } else { + fileSystem = new MemoryFileSystem(); + compiler.outputFileSystem = fileSystem; + } + + context.fs = fileSystem; + } +}; diff --git a/node_modules/webpack-dev-middleware/lib/middleware.js b/node_modules/webpack-dev-middleware/lib/middleware.js new file mode 100644 index 00000000..602632b6 --- /dev/null +++ b/node_modules/webpack-dev-middleware/lib/middleware.js @@ -0,0 +1,98 @@ +'use strict'; + +const path = require('path'); +const mime = require('mime'); +const DevMiddlewareError = require('./DevMiddlewareError'); +const { getFilenameFromUrl, handleRangeHeaders, handleRequest, ready } = require('./util'); + +module.exports = function wrapper(context) { + return function middleware(req, res, next) { + // fixes #282. credit @cexoso. in certain edge situations res.locals is + // undefined. + res.locals = res.locals || {}; + + function goNext() { + if (!context.options.serverSideRender) { + return next(); + } + + return new Promise(((resolve) => { + ready(context, () => { + res.locals.webpackStats = context.webpackStats; + res.locals.fs = context.fs; + resolve(next()); + }, req); + })); + } + + const acceptedMethods = context.options.methods || ['GET']; + if (acceptedMethods.indexOf(req.method) === -1) { + return goNext(); + } + + let filename = getFilenameFromUrl(context.options.publicPath, context.compiler, req.url); + + if (filename === false) { + return goNext(); + } + + return new Promise(((resolve) => { + handleRequest(context, filename, processRequest, req); + function processRequest() { + try { + let stat = context.fs.statSync(filename); + + if (!stat.isFile()) { + if (stat.isDirectory()) { + let { index } = context.options; + + if (index === undefined || index === true) { + index = 'index.html'; + } else if (!index) { + throw new DevMiddlewareError('next'); + } + + filename = path.posix.join(filename, index); + stat = context.fs.statSync(filename); + if (!stat.isFile()) { + throw new DevMiddlewareError('next'); + } + } else { + throw new DevMiddlewareError('next'); + } + } + } catch (e) { + return resolve(goNext()); + } + + // server content + let content = context.fs.readFileSync(filename); + content = handleRangeHeaders(content, req, res); + + let contentType = mime.getType(filename); + + // do not add charset to WebAssembly files, otherwise compileStreaming will fail in the client + if (!/\.wasm$/.test(filename)) { + contentType += '; charset=UTF-8'; + } + + res.setHeader('Content-Type', contentType); + res.setHeader('Content-Length', content.length); + + const { headers } = context.options; + if (headers) { + for (const name in headers) { + if ({}.hasOwnProperty.call(headers, name)) { + res.setHeader(name, context.options.headers[name]); + } + } + } + // Express automatically sets the statusCode to 200, but not all servers do (Koa). + res.statusCode = res.statusCode || 200; + if (res.send) res.send(content); + else res.end(content); + resolve(); + } + })); + }; +}; diff --git a/node_modules/webpack-dev-middleware/lib/reporter.js b/node_modules/webpack-dev-middleware/lib/reporter.js new file mode 100644 index 00000000..3c820f7e --- /dev/null +++ b/node_modules/webpack-dev-middleware/lib/reporter.js @@ -0,0 +1,30 @@ +'use strict'; + +module.exports = function reporter(middlewareOptions, options) { + const { log, state, stats } = options; + + if (state) { + const displayStats = (middlewareOptions.stats !== false); + + if (displayStats) { + if (stats.hasErrors()) { + log.error(stats.toString(middlewareOptions.stats)); + } else if (stats.hasWarnings()) { + log.warn(stats.toString(middlewareOptions.stats)); + } else { + log.info(stats.toString(middlewareOptions.stats)); + } + } + + let message = 'Compiled successfully.'; + + if (stats.hasErrors()) { + message = 'Failed to compile.'; + } else if (stats.hasWarnings()) { + message = 'Compiled with warnings.'; + } + log.info(message); + } else { + log.info('Compiling...'); + } +}; diff --git a/node_modules/webpack-dev-middleware/lib/util.js b/node_modules/webpack-dev-middleware/lib/util.js new file mode 100644 index 00000000..e8a70bef --- /dev/null +++ b/node_modules/webpack-dev-middleware/lib/util.js @@ -0,0 +1,173 @@ +'use strict'; + +const path = require('path'); +const { parse } = require('url'); +const querystring = require('querystring'); +const parseRange = require('range-parser'); + +const HASH_REGEXP = /[0-9a-f]{10,}/; + +// support for multi-compiler configuration +// see: https://github.com/webpack/webpack-dev-server/issues/641 +function getPaths(publicPath, compiler, url) { + const compilers = compiler && compiler.compilers; + if (Array.isArray(compilers)) { + let compilerPublicPath; + + // the path portion of compilerPublicPath + let compilerPublicPathBase; + + for (let i = 0; i < compilers.length; i++) { + compilerPublicPath = compilers[i].options + && compilers[i].options.output + && compilers[i].options.output.publicPath; + + if (compilerPublicPath) { + if (compilerPublicPath.indexOf('/') === 0) { + compilerPublicPathBase = compilerPublicPath; + } else { + // handle the case where compilerPublicPath is a URL with hostname + compilerPublicPathBase = parse(compilerPublicPath).pathname; + } + + // check the url vs the path part of the compilerPublicPath + if (url.indexOf(compilerPublicPathBase) === 0) { + return { + publicPath: compilerPublicPath, + outputPath: compilers[i].outputPath + }; + } + } + } + } + return { + publicPath, + outputPath: compiler.outputPath + }; +} + +function ready(context, fn, req) { + if (context.state) { + return fn(context.webpackStats); + } + + context.log.info(`wait until bundle finished: ${req.url || fn.name}`); + context.callbacks.push(fn); +} + +module.exports = { + getFilenameFromUrl(pubPath, compiler, url) { + const { outputPath, publicPath } = getPaths(pubPath, compiler, url); + // localPrefix is the folder our bundle should be in + const localPrefix = parse(publicPath || '/', false, true); + const urlObject = parse(url); + let filename; + + // publicPath has the hostname that is not the same as request url's, should fail + if (localPrefix.hostname !== null && urlObject.hostname !== null && + localPrefix.hostname !== urlObject.hostname) { + return false; + } + + // publicPath is not in url, so it should fail + if (publicPath && localPrefix.hostname === urlObject.hostname && + url.indexOf(publicPath) !== 0) { + return false; + } + + // strip localPrefix from the start of url + if (urlObject.pathname.indexOf(localPrefix.pathname) === 0) { + filename = urlObject.pathname.substr(localPrefix.pathname.length); + } + + if (!urlObject.hostname && localPrefix.hostname && + url.indexOf(localPrefix.path) !== 0) { + return false; + } + + let uri = outputPath; + + /* istanbul ignore if */ + if (process.platform === 'win32') { + // Path Handling for Microsoft Windows + if (filename) { + uri = path.posix.join((outputPath || ''), querystring.unescape(filename)); + + if (!path.win32.isAbsolute(uri)) { + uri = `/${uri}`; + } + } + + return uri; + } + + // Path Handling for all other operating systems + if (filename) { + uri = path.posix.join((outputPath || ''), filename); + + if (!path.posix.isAbsolute(uri)) { + uri = `/${uri}`; + } + } + + // if no matches, use outputPath as filename + return querystring.unescape(uri); + }, + + handleRangeHeaders(content, req, res) { + // assumes express API. For other servers, need to add logic to access + // alternative header APIs + res.setHeader('Accept-Ranges', 'bytes'); + + if (req.headers.range) { + const ranges = parseRange(content.length, req.headers.range); + + // unsatisfiable + if (ranges === -1) { + res.setHeader('Content-Range', `bytes */${content.length}`); + res.statusCode = 416; + } + + // valid (syntactically invalid/multiple ranges are treated as a + // regular response) + if (ranges !== -2 && ranges.length === 1) { + const { length } = content; + + // Content-Range + res.statusCode = 206; + res.setHeader( + 'Content-Range', + `bytes ${ranges[0].start}-${ranges[0].end}/${length}` + ); + + content = content.slice(ranges[0].start, ranges[0].end + 1); + } + } + + return content; + }, + + handleRequest(context, filename, processRequest, req) { + // in lazy mode, rebuild on bundle request + if (context.options.lazy && (!context.options.filename || context.options.filename.test(filename))) { + context.rebuild(); + } + + if (HASH_REGEXP.test(filename)) { + try { + if (context.fs.statSync(filename).isFile()) { + processRequest(); + return; + } + } catch (e) { + // eslint-disable-line + } + } + + ready(context, processRequest, req); + }, + + noop: () => {}, + + ready +}; |
