aboutsummaryrefslogtreecommitdiff
path: root/node_modules/webpack-dev-middleware/lib
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/webpack-dev-middleware/lib')
-rw-r--r--node_modules/webpack-dev-middleware/lib/DevMiddlewareError.js5
-rw-r--r--node_modules/webpack-dev-middleware/lib/context.js103
-rw-r--r--node_modules/webpack-dev-middleware/lib/fs.js73
-rw-r--r--node_modules/webpack-dev-middleware/lib/middleware.js98
-rw-r--r--node_modules/webpack-dev-middleware/lib/reporter.js30
-rw-r--r--node_modules/webpack-dev-middleware/lib/util.js173
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
+};