diff --git a/.circleci/config.yml b/.circleci/config.yml
index 1146d5f..490b953 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -17,25 +17,25 @@ jobs:
key: dependency-cache-{{ checksum "package-lock.json" }}
paths:
- ./node_modules
- node-v10-latest:
- docker:
- - image: rollupcabal/circleci-node-v10:latest
+ node-v12-latest:
+ machine: true
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
- run:
- name: Node Info
- command: node --version && npm --version
- - run:
- name: Workaround for GoogleChrome/puppeteer#290
- command: 'sh .circleci/setup-puppeteer.sh'
- - run:
- name: NPM Rebuild
- command: npm install
- - run:
- name: Run unit tests.
- command: npm run ci:coverage
+ name: Setup Node 12 and Run Tests
+ command: |
+ set +e
+ touch $BASH_ENV
+ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
+ export NVM_DIR="/opt/circleci/.nvm"
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
+ nvm install 12
+ nvm alias default 12
+ node --version && npm --version
+ npm install
+ npm run ci:coverage
- run:
name: Submit coverage data to codecov.
command: bash <(curl -s https://codecov.io/bash)
@@ -70,7 +70,7 @@ workflows:
filters:
tags:
only: /.*/
- - node-v10-latest:
+ - node-v12-latest:
requires:
- analysis
filters:
diff --git a/README.md b/README.md
index 0caeeb3..605b7eb 100644
--- a/README.md
+++ b/README.md
@@ -224,6 +224,17 @@ If [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), the modul
If a value of `'minimal'` is set, the progress indicator will render as a small, colored bar at the top of the window. This can be useful when the default fancy progress indicator interferes with elements in the page.
+### `ramdisk`
+Type: `boolean`
+Default: `false`
+Support: MacOS and Linux, Windows with WSL 2.0.
+
+If `true`, will apply [`webpack-plugin-ramdisk`](https://www.npmjs.com/package/webpack-plugin-ramdisk) to the build. `output` configuration does not have to be modified, a symlink will be created from the original output path to the output path on the ramdisk. _**Note:** This will remove an existing directory at the defined output path._
+
+Leveraging this option can result in significant reduction of build time, which is especially useful when using `hmr: true` or `liveReload: true`. Typical build times can be cut by 25-32% or more depending on hardware and webpack configuration. This is also recommended for users with SSD, as it reduces hard disk thrashing.
+
+Windows users without WSL 2.0 are encouraged to install it to make use of this feature, or create a ramdisk manually using a tool like [ImDisk](https://sourceforge.net/projects/imdisk-toolkit/).
+
### `static`
Type: `String | Array(String) | Object`
Default: `compiler.context`
diff --git a/lib/errors.js b/lib/errors.js
index bd72754..df27a49 100644
--- a/lib/errors.js
+++ b/lib/errors.js
@@ -23,4 +23,12 @@ class PluginExistsError extends WebpackPluginServeError {
}
}
-module.exports = { PluginExistsError, WebpackPluginServeError };
+class RamdiskPathError extends WebpackPluginServeError {
+ constructor(...args) {
+ super(...args);
+ this.name = 'RamdiskPathError';
+ this.code = 'ERR_RAMDISK_PATH';
+ }
+}
+
+module.exports = { PluginExistsError, RamdiskPathError, WebpackPluginServeError };
diff --git a/lib/index.js b/lib/index.js
index 04f6421..9e31f71 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -15,7 +15,8 @@ const Koa = require('koa');
const nanoid = require('nanoid/generate');
const { DefinePlugin, ProgressPlugin } = require('webpack');
-const { init: initHmrPlugin } = require('./hmr-plugin');
+const { init: initHmrPlugin } = require('./plugins/hmr');
+const { init: initRamdiskPlugin } = require('./plugins/ramdisk');
const { forceError, getLogger } = require('./log');
const { start } = require('./server');
const { validate } = require('./validate');
@@ -34,6 +35,7 @@ const defaults = {
open: false,
port: 55555,
progress: true,
+ ramdisk: false,
secure: false,
static: null,
status: true
@@ -59,6 +61,7 @@ class WebpackPluginServe extends EventEmitter {
// NOTE: undocumented option. this is used primarily in testing to allow for multiple instances
// of the plugin to be tested within the same context. If you find this, use this at your own
// peril.
+ /* istanbul ignore if */
if (!opts.allowMany && instance) {
instance.log.error(
'Duplicate instances created. Only the first instance of this plugin will be active.'
@@ -117,6 +120,7 @@ class WebpackPluginServe extends EventEmitter {
this.compiler = compiler;
// only allow once instance of the plugin to run for a build
+ /* istanbul ignore if */
if (instance !== this) {
return;
}
@@ -169,6 +173,10 @@ class WebpackPluginServe extends EventEmitter {
initHmrPlugin(compiler, this.log);
}
+ if (this.options.ramdisk) {
+ initRamdiskPlugin.call(this, compiler);
+ }
+
if (!this.options.static.length) {
this.options.static.push(compiler.context);
}
@@ -187,6 +195,7 @@ class WebpackPluginServe extends EventEmitter {
// track subsequent builds from watching
this.on('invalid', () => {
+ /* istanbul ignore next */
this.state.compiling = new Promise((resolve) => {
this.once('done', () => resolve());
});
@@ -198,6 +207,7 @@ class WebpackPluginServe extends EventEmitter {
// webpack still has a 4 year old bug whereby in watch mode, file timestamps aren't properly
// accounted for, which will trigger multiple builds of the same hash.
// see: https://github.com/egoist/time-fix-plugin
+ /* istanbul ignore if */
if (this.lastHash === compilation.hash) {
return;
}
diff --git a/lib/log.js b/lib/log.js
index a7bb307..973a0d9 100644
--- a/lib/log.js
+++ b/lib/log.js
@@ -20,6 +20,7 @@ const colors = {
error: 'red'
};
+/* istanbul ignore next */
const forceError = (...args) => {
const { error } = console;
error(chalk.red(`${symbols.whoops} wps:`), ...args);
@@ -29,12 +30,14 @@ const getLogger = (options) => {
const prefix = {
level: ({ level }) => {
const color = colors[level];
+ /* istanbul ignore next */
const symbol = ['error', 'warn'].includes(level) ? symbols.whoops : symbols.ok;
return chalk[color](`${symbol} wps: `);
},
template: '{{level}}'
};
+ /* istanbul ignore if */
if (options.timestamp) {
prefix.template = `[{{time}}] ${prefix.template}`;
}
diff --git a/lib/hmr-plugin.js b/lib/plugins/hmr.js
similarity index 94%
rename from lib/hmr-plugin.js
rename to lib/plugins/hmr.js
index 8e13e51..58affe8 100644
--- a/lib/hmr-plugin.js
+++ b/lib/plugins/hmr.js
@@ -10,7 +10,7 @@
*/
const { HotModuleReplacementPlugin } = require('webpack');
-const { PluginExistsError } = require('./errors');
+const { PluginExistsError } = require('../errors');
const addPlugin = (compiler) => {
const hmrPlugin = new HotModuleReplacementPlugin();
@@ -27,6 +27,8 @@ const init = function init(compiler, log) {
const hasHMRPlugin = compiler.options.plugins.some(
(plugin) => plugin instanceof HotModuleReplacementPlugin
);
+
+ /* istanbul ignore else */
if (!hasHMRPlugin) {
addPlugin(compiler);
} else {
diff --git a/lib/plugins/ramdisk.js b/lib/plugins/ramdisk.js
new file mode 100644
index 0000000..f278613
--- /dev/null
+++ b/lib/plugins/ramdisk.js
@@ -0,0 +1,87 @@
+/*
+ Copyright © 2018 Andrew Powell
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of this Source Code Form.
+*/
+/* eslint-disable no-param-reassign */
+const crypto = require('crypto');
+const { existsSync, symlinkSync } = require('fs');
+const { basename, join, resolve } = require('path');
+
+const isCwd = require('is-path-cwd');
+const readPkgUp = require('read-pkg-up');
+const rm = require('rimraf');
+const { WebpackPluginRamdisk } = require('webpack-plugin-ramdisk');
+
+const { PluginExistsError, RamdiskPathError } = require('../errors');
+
+module.exports = {
+ init(compiler) {
+ const hasPlugin = compiler.options.plugins.some(
+ (plugin) => plugin instanceof WebpackPluginRamdisk
+ );
+
+ /* istanbul ignore if */
+ if (hasPlugin) {
+ this.log.error(
+ 'webpack-plugin-serve adds WebpackRamdiskPlugin automatically. Please remove it from your config.'
+ );
+ throw new PluginExistsError('WebpackRamdiskPlugin exists in the specified configuration.');
+ }
+
+ const pkg = readPkgUp.sync() || {};
+ const { path } = compiler.options.output;
+ const lastSegment = basename(path);
+ const errorInfo = `The ramdisk option creates a symlink from \`output.path\`, to the ramdisk build output path, and must remove any existing \`output.path\` to do so.`;
+
+ // if output.path is /batman/batcave, and the user is running the build with wsp from
+ // /batman/batcave, then the process will try and delete cwd, which we don't want for a number
+ // of reasons
+ // console.log('output.path:', resolve(path));
+ // console.log('process.cwd:', process.cwd());
+ if (isCwd(path)) {
+ throw new RamdiskPathError(
+ `Cannot remove current working directory. ${errorInfo} Please run from another path, or choose a different \`output.path\`.`
+ );
+ }
+
+ // if output.path is /batman/batcave, and the compiler context is not set and cwd is
+ // /batman/batcave, or the context is the same as output.path, then the process will try and
+ // delete the context directory, which probably contains src, configs, etc. throw an error
+ // and be overly cautious rather than let the user do something bad. oddly enough, webpack
+ // doesn't protect against context === output.path.
+ if (resolve(compiler.context) === resolve(path)) {
+ throw new RamdiskPathError(
+ `Cannot remove ${path}. ${errorInfo} Please set the \`context\` to a another path, choose a different \`output.path\`.`
+ );
+ }
+
+ if (!pkg.name) {
+ // use md5 for a short hash that'll be consistent between wps starts
+ const md5 = crypto.createHash('md5');
+ md5.update(path);
+ pkg.name = md5.digest('hex');
+ }
+
+ const newPath = join(pkg.name, lastSegment);
+
+ // clean up the output path in prep for the ramdisk plugin
+ compiler.options.output.path = newPath;
+
+ this.log.info(`Ramdisk enabled`);
+
+ const plugin = new WebpackPluginRamdisk({ name: 'wps' });
+ plugin.apply(compiler);
+
+ if (existsSync(path)) {
+ rm.sync(path);
+ }
+
+ symlinkSync(compiler.options.output.path, path);
+ }
+};
diff --git a/lib/validate.js b/lib/validate.js
index 73ffb45..38b8065 100644
--- a/lib/validate.js
+++ b/lib/validate.js
@@ -1,3 +1,13 @@
+/*
+ Copyright © 2018 Andrew Powell
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of this Source Code Form.
+*/
const Joi = require('@hapi/joi');
const isPromise = require('is-promise');
@@ -51,6 +61,7 @@ module.exports = {
// prettier-ignore
port: [number().integer().max(65535), any().promise()],
progress: [boolean(), string().valid('minimal')],
+ ramdisk: [boolean()],
secure: any().forbidden(),
// prettier-ignore
static: [
diff --git a/package-lock.json b/package-lock.json
index 8d58533..4dab6d5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -366,19 +366,19 @@
}
},
"@commitlint/cli": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-8.0.0.tgz",
- "integrity": "sha512-wFu+g9v73I2rMRTv27ItIbcrhWqge0ZpUNUIJ9fw8TF7XpmhaUFvGqa2kU6st1F0TyEOrq5ZMzwI8kQZNVLuXg==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-8.1.0.tgz",
+ "integrity": "sha512-83K5C2nIAgoZlzMegf0/MEBjX+ampUyc/u79RxgX9ZYjzos+RQtNyO7I43dztVxPXSwAnX9XRgoOfkGWA4nbig==",
"dev": true,
"requires": {
- "@commitlint/format": "^8.0.0",
- "@commitlint/lint": "^8.0.0",
- "@commitlint/load": "^8.0.0",
- "@commitlint/read": "^8.0.0",
+ "@commitlint/format": "^8.1.0",
+ "@commitlint/lint": "^8.1.0",
+ "@commitlint/load": "^8.1.0",
+ "@commitlint/read": "^8.1.0",
"babel-polyfill": "6.26.0",
"chalk": "2.3.1",
"get-stdin": "7.0.0",
- "lodash": "4.17.11",
+ "lodash": "4.17.14",
"meow": "5.0.0",
"resolve-from": "5.0.0",
"resolve-global": "1.0.0"
@@ -394,12 +394,6 @@
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.2.0"
}
- },
- "lodash": {
- "version": "4.17.11",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
- "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
- "dev": true
}
}
},
@@ -410,102 +404,85 @@
"dev": true
},
"@commitlint/ensure": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-8.0.0.tgz",
- "integrity": "sha512-rhBO79L9vXeb26JU+14cxZQq46KyyVqlo31C33VIe7oJndUtWrDhZTvMjJeB1pdXh4EU4XWdMo+yzBmuypFgig==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-8.1.0.tgz",
+ "integrity": "sha512-dBU4CcjN0vJSDNOeSpaHNgQ1ra444u4USvI6PTaHVAS4aeDpZ5Cds1rxkZNsocu48WNycUu0jP84+zjcw2pPLQ==",
"dev": true,
"requires": {
- "lodash": "4.17.11"
- },
- "dependencies": {
- "lodash": {
- "version": "4.17.11",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
- "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
- "dev": true
- }
+ "lodash": "4.17.14"
}
},
"@commitlint/execute-rule": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-8.0.0.tgz",
- "integrity": "sha512-E/A2xHqx3syclXAFl8vJY2o/+xtL9axrqbFFF42Bzke+Eflf0mOJviPxDodu2xP0wXMRQ9UokAi/reK9dMtA/A==",
- "dev": true,
- "requires": {
- "babel-runtime": "6.26.0"
- }
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-8.1.0.tgz",
+ "integrity": "sha512-+vpH3RFuO6ypuCqhP2rSqTjFTQ7ClzXtUvXphpROv9v9+7zH4L+Ex+wZLVkL8Xj2cxefSLn/5Kcqa9XyJTn3kg==",
+ "dev": true
},
"@commitlint/format": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-8.0.0.tgz",
- "integrity": "sha512-dFxKGLp1T4obi7+YZ2NcSAebJA/dBQwnerRJGz0hWtsO6pheJRe+qC50+GCb2fYGWUc5lIWawaRts0m7RkFGUw==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-8.1.0.tgz",
+ "integrity": "sha512-D0cmabUTQIKdABgt08d9JAvO9+lMRAmkcsZx8TMScY502R67HCw77JhzRDcw1RmqX5rN8JO6ZjDHO92Pbwlt+Q==",
"dev": true,
"requires": {
"chalk": "^2.0.1"
}
},
"@commitlint/is-ignored": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-8.0.0.tgz",
- "integrity": "sha512-geWr/NXGMrZ3qc3exDM+S1qV+nMDxp1LwN3rLpEN2gXTwW3rIXq49RQQUkn0n3BHcpqJJ9EBhjqFoMU1TYx7Ng==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-8.1.0.tgz",
+ "integrity": "sha512-HUSxx6kuLbqrQ8jb5QRzo+yR+CIXgA9HNcIcZ1qWrb+O9GOixt3mlW8li1IcfIgfODlaWoxIz0jYCxR08IoQLg==",
"dev": true,
"requires": {
- "semver": "6.0.0"
+ "@types/semver": "^6.0.1",
+ "semver": "6.1.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.1.tgz",
+ "integrity": "sha512-rWYq2e5iYW+fFe/oPPtYJxYgjBm8sC4rmoGdUOgBB7VnwKt6HrL793l2voH1UlsyYZpJ4g0wfjnTEO1s1NP2eQ==",
+ "dev": true
+ }
}
},
"@commitlint/lint": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-8.0.0.tgz",
- "integrity": "sha512-5nKiJpBDR2iei+fre4+6M7FUrSX1cIMoxXKdrnb1GMOXkw9CsZSF5OvdrX08zHAFmOAeDaohoCV+XN/UN/vWYg==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-8.1.0.tgz",
+ "integrity": "sha512-WYjbUgtqvnlVH3S3XPZMAa+N7KO0yQ+GuUG20Qra+EtER6SRYawykmEs4wAyrmY8VcFXUnKgSlIQUsqmGKwNZQ==",
"dev": true,
"requires": {
- "@commitlint/is-ignored": "^8.0.0",
- "@commitlint/parse": "^8.0.0",
- "@commitlint/rules": "^8.0.0",
+ "@commitlint/is-ignored": "^8.1.0",
+ "@commitlint/parse": "^8.1.0",
+ "@commitlint/rules": "^8.1.0",
"babel-runtime": "^6.23.0",
- "lodash": "4.17.11"
- },
- "dependencies": {
- "lodash": {
- "version": "4.17.11",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
- "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
- "dev": true
- }
+ "lodash": "4.17.14"
}
},
"@commitlint/load": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-8.0.0.tgz",
- "integrity": "sha512-JXC3YjO7hN7Rv2Z/SaYz+oIvShsQWLL7gnOCe8+YgI1EusBqjV4mPI0HnBXVe9volfdxbl+Af/GoQZs2dvyOFA==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-8.1.0.tgz",
+ "integrity": "sha512-ra02Dvmd7Gp1+uFLzTY3yGOpHjPzl5T9wYg/xrtPJNiOWXvQ0Mw7THw+ucd1M5iLUWjvdavv2N87YDRc428wHg==",
"dev": true,
"requires": {
- "@commitlint/execute-rule": "^8.0.0",
- "@commitlint/resolve-extends": "^8.0.0",
+ "@commitlint/execute-rule": "^8.1.0",
+ "@commitlint/resolve-extends": "^8.1.0",
"babel-runtime": "^6.23.0",
+ "chalk": "2.4.2",
"cosmiconfig": "^5.2.0",
- "lodash": "4.17.11",
+ "lodash": "4.17.14",
"resolve-from": "^5.0.0"
- },
- "dependencies": {
- "lodash": {
- "version": "4.17.11",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
- "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
- "dev": true
- }
}
},
"@commitlint/message": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-8.0.0.tgz",
- "integrity": "sha512-2oGUV8630nzsj17t6akq3mFguzWePADO069IwKJi+CN5L0YRBQj9zGRCB0P+zvh4EngjqMnuMwhEhaBEM8TTzA==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-8.1.0.tgz",
+ "integrity": "sha512-AjHq022G8jQQ/3YrBOjwVBD4xF75hvC3vcvFoBIb7cC8vad1QWq+1w+aks0KlEK5IW+/+7ORZXIH+oyW7h3+8A==",
"dev": true
},
"@commitlint/parse": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-8.0.0.tgz",
- "integrity": "sha512-6CyweJrBkI+Jqx7qkpYgVx2muBMoUZAZHWhUTgqHIDDmI+3d4UPZ2plGS2G0969KkHCgjtlwnwTjWqA9HLMwPA==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-8.1.0.tgz",
+ "integrity": "sha512-n4fEbZ5kdK5HChvne7Mj8rGGkKMfA4H11IuWiWmmMzgmZTNb/B04LPrzdUm4lm3f10XzM2JMM7PLXqofQJOGvA==",
"dev": true,
"requires": {
"conventional-changelog-angular": "^1.3.3",
@@ -514,63 +491,106 @@
}
},
"@commitlint/read": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-8.0.0.tgz",
- "integrity": "sha512-IhNMiKPqkB5yxphe/FiOKgX2uCysbR8fGK6KOXON3uJaVND0dctxnfdv+vY9gDv2CtjIXgNFO+v6FLnqMfIvwA==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-8.1.0.tgz",
+ "integrity": "sha512-PKsGMQFEr2sX/+orI71b82iyi8xFqb7F4cTvsLxzB5x6/QutxPVM3rg+tEVdi6rBKIDuqRIp2puDZQuREZs3vg==",
"dev": true,
"requires": {
- "@commitlint/top-level": "^8.0.0",
+ "@commitlint/top-level": "^8.1.0",
"@marionebl/sander": "^0.6.0",
"babel-runtime": "^6.23.0",
"git-raw-commits": "^1.3.0"
}
},
"@commitlint/resolve-extends": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-8.0.0.tgz",
- "integrity": "sha512-SPkH+dXMCpYboVwpIhtOhpg1xYdE7L77fuHmEJWveXSmgfi0GosFm4aJ7Cer9DjNjW+KbD0TUfzZU0TrYUESjQ==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-8.1.0.tgz",
+ "integrity": "sha512-r/y+CeKW72Oa9BUctS1+I/MFCDiI3lfhwfQ65Tpfn6eZ4CuBYKzrCRi++GTHeAFKE3y8q1epJq5Rl/1GBejtBw==",
"dev": true,
"requires": {
- "babel-runtime": "6.26.0",
+ "@types/node": "^12.0.2",
"import-fresh": "^3.0.0",
- "lodash": "4.17.11",
+ "lodash": "4.17.14",
"resolve-from": "^5.0.0",
"resolve-global": "^1.0.0"
- },
- "dependencies": {
- "lodash": {
- "version": "4.17.11",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
- "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
- "dev": true
- }
}
},
"@commitlint/rules": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-8.0.0.tgz",
- "integrity": "sha512-s9BehZQP5uAc/V4lMaUxwxFabVZTw5fZ18Ase1e5tbMKVIwq/7E00Ny1czN7xSFXfgffukWznsexpfFXYpbVsg==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-8.1.0.tgz",
+ "integrity": "sha512-hlM8VfNjsOkbvMteFyqn0c3akiUjqG09Iid28MBLrXl/d+8BR3eTzwJ4wMta4oz/iqGyrIywvg1FpHrV977MPA==",
"dev": true,
"requires": {
- "@commitlint/ensure": "^8.0.0",
- "@commitlint/message": "^8.0.0",
- "@commitlint/to-lines": "^8.0.0",
+ "@commitlint/ensure": "^8.1.0",
+ "@commitlint/message": "^8.1.0",
+ "@commitlint/to-lines": "^8.1.0",
"babel-runtime": "^6.23.0"
}
},
"@commitlint/to-lines": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-8.0.0.tgz",
- "integrity": "sha512-qqgNeyj+NJ1Xffwv6hGsipKlVFj30NmfPup751MS/me0GV8IBd//njTjiqHvf/3sKm/OcGn4Re4D7YXwTcC2RA==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-8.1.0.tgz",
+ "integrity": "sha512-Lh4OH1bInI8GME/7FggS0/XkIMEJdTObMbXRyPRGaPcWH5S7zpB6y+b4qjzBHXAbEv2O46QAAMjZ+ywPQCpmYQ==",
"dev": true
},
"@commitlint/top-level": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-8.0.0.tgz",
- "integrity": "sha512-If9hwfISHV8HXGKeXUKsUvOo4DuISWiU/VC2qHsKpeHSREAxkWESmQzzwYvOtyBjMiOTfAXfzgth18g36Fz2ow==",
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-8.1.0.tgz",
+ "integrity": "sha512-EvQuofuA/+0l1w9pkG/PRyIwACmZdIh9qxyax7w7mR8qqmSHscqf2jARIylh1TOx0uI9egO8MuPLiwC1RwyREA==",
"dev": true,
"requires": {
- "find-up": "^2.1.0"
+ "find-up": "^4.0.0"
+ },
+ "dependencies": {
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
+ "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true
+ }
}
},
"@concordance/react": {
@@ -723,6 +743,12 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.6.2.tgz",
"integrity": "sha512-gojym4tX0FWeV2gsW4Xmzo5wxGjXGm550oVUII7f7G5o4BV6c7DBdiG1RRQd+y1bvqRyYtPfMK85UM95vsapqQ=="
},
+ "@types/semver": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-6.0.1.tgz",
+ "integrity": "sha512-ffCdcrEE5h8DqVxinQjo+2d1q+FV5z7iNtPofw3JsrltSoSVlOGaW0rY8XxtO9XukdTn8TaCGWmk2VFGhI70mg==",
+ "dev": true
+ },
"@webassemblyjs/ast": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
diff --git a/package.json b/package.json
index 0d9eecc..f516a30 100644
--- a/package.json
+++ b/package.json
@@ -43,6 +43,7 @@
"connect-history-api-fallback": "^1.5.0",
"globby": "^10.0.1",
"http-proxy-middleware": "^0.19.0",
+ "is-path-cwd": "^2.2.0",
"is-promise": "^2.1.0",
"koa": "^2.5.3",
"koa-compress": "^3.0.0",
@@ -54,11 +55,14 @@
"onetime": "^5.1.0",
"opn": "^6.0.0",
"p-defer": "^3.0.0",
+ "read-pkg-up": "^6.0.0",
+ "rimraf": "^2.6.3",
"strip-ansi": "^5.0.0",
+ "webpack-plugin-ramdisk": "^0.1.2",
"ws": "^7.1.0"
},
"devDependencies": {
- "@commitlint/cli": "^8.0.0",
+ "@commitlint/cli": "^8.1.0",
"@commitlint/config-conventional": "^8.0.0",
"ava": "^2.2.0",
"cpy": "^7.0.1",
@@ -101,7 +105,7 @@
},
"nyc": {
"include": [
- "lib/*.js"
+ "lib/**/*.js"
],
"exclude": [
"lib/client*.js",
diff --git a/test/errors.test.js b/test/errors.test.js
new file mode 100644
index 0000000..8b1dfe2
--- /dev/null
+++ b/test/errors.test.js
@@ -0,0 +1,8 @@
+const test = require('ava');
+
+const { PluginExistsError, WebpackPluginServeError } = require('../lib/errors');
+
+test('errors', (t) => {
+ t.snapshot(new PluginExistsError());
+ t.snapshot(new WebpackPluginServeError());
+});
diff --git a/test/fixtures/ramdisk/app.js b/test/fixtures/ramdisk/app.js
new file mode 100644
index 0000000..ad15d30
--- /dev/null
+++ b/test/fixtures/ramdisk/app.js
@@ -0,0 +1,9 @@
+require('./component');
+
+if (module.hot) {
+ module.hot.accept((err) => {
+ if (err) {
+ console.error('HMR', err);
+ }
+ });
+}
diff --git a/test/fixtures/ramdisk/component.js b/test/fixtures/ramdisk/component.js
new file mode 100644
index 0000000..9262226
--- /dev/null
+++ b/test/fixtures/ramdisk/component.js
@@ -0,0 +1,2 @@
+const main = document.querySelector('main');
+main.innerHTML = 'main';
diff --git a/test/fixtures/ramdisk/config-context-error.js b/test/fixtures/ramdisk/config-context-error.js
new file mode 100644
index 0000000..fa0f821
--- /dev/null
+++ b/test/fixtures/ramdisk/config-context-error.js
@@ -0,0 +1,29 @@
+const { resolve } = require('path');
+
+const getPort = require('get-port');
+
+const { WebpackPluginServe: Serve } = require('../../../lib/');
+
+module.exports = {
+ context: __dirname,
+ entry: ['./app.js', 'webpack-plugin-serve/client'],
+ mode: 'development',
+ output: {
+ filename: './output.js',
+ path: __dirname,
+ publicPath: 'output/'
+ },
+ plugins: [
+ new Serve({
+ host: 'localhost',
+ port: getPort({ port: 55555 }),
+ ramdisk: true
+ })
+ ],
+ resolve: {
+ alias: {
+ 'webpack-plugin-serve/client': resolve(__dirname, '../../../client')
+ }
+ },
+ watch: true
+};
diff --git a/test/fixtures/ramdisk/config-cwd-error.js b/test/fixtures/ramdisk/config-cwd-error.js
new file mode 100644
index 0000000..b21c810
--- /dev/null
+++ b/test/fixtures/ramdisk/config-cwd-error.js
@@ -0,0 +1,29 @@
+const { resolve } = require('path');
+
+const getPort = require('get-port');
+
+const { WebpackPluginServe: Serve } = require('../../../lib/');
+
+module.exports = {
+ context: __dirname,
+ entry: ['./app.js', 'webpack-plugin-serve/client'],
+ mode: 'development',
+ output: {
+ filename: './output.js',
+ path: resolve(__dirname, 'cwd-error'),
+ publicPath: 'output/'
+ },
+ plugins: [
+ new Serve({
+ host: 'localhost',
+ port: getPort({ port: 55555 }),
+ ramdisk: true
+ })
+ ],
+ resolve: {
+ alias: {
+ 'webpack-plugin-serve/client': resolve(__dirname, '../../../client')
+ }
+ },
+ watch: true
+};
diff --git a/test/fixtures/ramdisk/cwd-error/.gitkeep b/test/fixtures/ramdisk/cwd-error/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/test/fixtures/ramdisk/index.html b/test/fixtures/ramdisk/index.html
new file mode 100644
index 0000000..fca1533
--- /dev/null
+++ b/test/fixtures/ramdisk/index.html
@@ -0,0 +1,10 @@
+
+
+