Socket
Socket
Sign inDemoInstall

grunt-webpack

Package Overview
Dependencies
Maintainers
4
Versions
64
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

grunt-webpack - npm Package Compare versions

Comparing version 4.0.3 to 5.0.0

src/options/__mocks__/TestOptionHelper.js

15

package.json
{
"name": "grunt-webpack",
"description": "Use webpack with grunt.",
"version": "4.0.3",
"version": "5.0.0",
"homepage": "https://github.com/webpack-contrib/grunt-webpack",

@@ -17,3 +17,3 @@ "author": {

"engines": {
"node": ">=10.13.0"
"node": ">=12.13.0"
},

@@ -40,13 +40,14 @@ "files": [

"babel-loader": "^8.1.0",
"eslint": "^7.5.0",
"eslint": "^8.2.0",
"eslint-config-prettier": "^8.2.0",
"eslint-config-webpack": "^1.2.5",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-prettier": "^4.0.0",
"fast-glob": "^3.2.4",
"fs-extra": "^9.0.1",
"fs-extra": "^10.0.0",
"grunt": "^1.2.1",
"jest": "^26.1.0",
"jest": "^27.3.1",
"prettier": "^2.0.5",
"webpack": "^4.17.1"
"webpack": "^5.62.1",
"webpack-dev-server": "^4.4.0"
},

@@ -53,0 +54,0 @@ "dependencies": {

@@ -17,4 +17,3 @@ [![npm][npm]][npm-url]

- Version 4 of `grunt-webpack` supports webpack version 4 and 5.
- Version 3.2.0 of `webpack-dev-server` is needed if used (optional).
- Version 5 of `grunt-webpack` supports webpack version 4 and 5 and (optional) `webpack-dev-server` version 4.

@@ -60,3 +59,3 @@ <h2 align="center">Install</h2>

`webpack-grunt` offers two different tasks `webpack` and `webpack-dev-server`. Both support all webpack options as
can be seen in the [webpack documentation][3]. For exceptions and additions see this list.
can be seen in the [webpack documentation][webpack-config]. For exceptions and additions see this list.

@@ -66,2 +65,3 @@ ### Both Tasks

#### progress
Type: `bool`

@@ -72,29 +72,20 @@ Default: `true` (`false` if no TTY present)

#### keepalive
Type: `bool`
Default: `false` (`true` if watch mode is used and for `webpack-dev-server` task)
### Webpack Task
When set to true the grunt process/task will be kept alive after webpack task is finished. This is especially useful for `watch` and `webpack-dev-server` as these usually need to run as long as not manually killed.
#### failOnError
### Webpack Task
#### watch
Type: `bool`
Default: `undefined`
Default: `true` (`false` if watch mode is used)
> Turn on watch mode. This means that after the initial build, webpack will continue to watch for changes in any of the resolved files.
Will terminate the grunt process when an error happens if set to `true`. If set to `false` the grunt process will not be immediately terminated on error and instead continue to run.
Turning on watch mode also sets the following defaults:
#### keepalive
- Default `cache` to `true`
- Default `keepalive` to `true`
- Default `failOnError` to `false`
#### failOnError
Type: `bool`
Default: `true` (`false` if watch mode is used)
Default: `false` (`true` if watch mode is used and for `webpack-dev-server` task)
Will terminate the grunt process when an error happens if set to `true`. If set to `false` the grunt process will not be immediately terminated on error and instead continue to run.
When set to true the grunt process/task will be kept alive after webpack task is finished. This is especially useful for `watch` and `webpack-dev-server` as these usually need to run as long as not manually killed.
#### storeStatsTo
Type: `string`

@@ -115,8 +106,25 @@ Default: `null`

> For more information about grunt template tags have a look at the [grunt docs][2].
> For more information about grunt template tags have a look at the [grunt docs][grunt-template].
#### watch
Type: `bool`
Default: `undefined`
> Turn on watch mode. This means that after the initial build, webpack will continue to watch for changes in any of the resolved files.
Turning on watch mode also sets the following defaults:
- Default `cache` to `true`
- Default `keepalive` to `true`
- Default `failOnError` to `false`
### Webpack-dev-server Task
The webpack-dev-server options [`host`][5], [`hotOnly`][6], [`inline`][1], [`port`][4] and [`public`][7] which are usually only available in the CLI can also be used in this grunt-plugin.
There are no special options for this task. Some changed defaults for WebpackDevServer options are:
| Name | default value |
| -------------- | ------------- |
| devServer.host | localhost |
<h2 align="center">Examples</h2>

@@ -131,21 +139,21 @@

``` javascript
const webpackConfig = require('./webpack.config.js');
```javascript
const webpackConfig = require("./webpack.config.js");
module.exports = function(grunt) {
module.exports = function (grunt) {
grunt.initConfig({
webpack: {
options: {
stats: !process.env.NODE_ENV || process.env.NODE_ENV === 'development'
stats: !process.env.NODE_ENV || process.env.NODE_ENV === "development",
},
prod: webpackConfig,
dev: Object.assign({ watch: true }, webpackConfig)
}
dev: Object.assign({ watch: true }, webpackConfig),
},
});
grunt.loadNpmTasks('grunt-webpack');
grunt.loadNpmTasks("grunt-webpack");
};
```
> The webpack task in this example has two targets called `prod` and `dev`. They can be renamed to everything besides `options`. See the [grunt docs][8] for more information about targets.
> The webpack task in this example has two targets called `prod` and `dev`. They can be renamed to everything besides `options`. See the [grunt docs][grunt-targets] for more information about targets.

@@ -165,3 +173,3 @@ On the command line you can then do the following.

> For more examples and information have a look at the [webpack documentation][9] which mostly also applies here besides the noted differences above.
> For more examples and information have a look at the [webpack documentation][webpack-start] which mostly also applies here besides the noted differences above.

@@ -173,5 +181,3 @@ #### Lazy config loading

```js
const webpackConfig = require('./webpack.config.js');
module.exports = function(grunt) {
module.exports = function (grunt) {
grunt.initConfig({

@@ -189,6 +195,22 @@ webpack: {

grunt.loadNpmTasks('grunt-webpack');
grunt.loadNpmTasks("grunt-webpack");
};
```
You could also use a promise
```js
const webpackConfig = require("./webpack.config.js");
module.exports = function (grunt) {
grunt.initConfig({
webpack: {
myconfig: Promise.resolve(webpackConfig),
},
});
grunt.loadNpmTasks("grunt-webpack");
};
```
#### Grunt templates

@@ -201,5 +223,3 @@

```js
const webpackConfig = require('./webpack.config.js');
module.exports = function(grunt) {
module.exports = function (grunt) {
grunt.initConfig({

@@ -218,3 +238,3 @@ outputFileName: "output.js",

grunt.loadNpmTasks('grunt-webpack');
grunt.loadNpmTasks("grunt-webpack");
};

@@ -226,10 +246,8 @@ ```

```js
const webpackConfig = require('./webpack.config.js');
module.exports = function(grunt) {
module.exports = function (grunt) {
grunt.initConfig({
name: "Webpack",
pkg: {
copyright: '<%= name %>',
version: '6.55.345',
copyright: "<%= name %>",
version: "6.55.345",
},

@@ -245,3 +263,5 @@ webpack: {

new webpack.BannerPlugin({
banner: `/*! ${config.pkg.copyright} - Version ${config.pkg.version} dated ${grunt.template.today()} */`,
banner: `/*! ${config.pkg.copyright} - Version ${
config.pkg.version
} dated ${grunt.template.today()} */`,
raw: true,

@@ -254,6 +274,41 @@ }),

grunt.loadNpmTasks('grunt-webpack');
grunt.loadNpmTasks("grunt-webpack");
};
```
### Webpack-dev-server
#### imported config
This is a simple example that requires the webpack config from the config file. Read how to configure webpack-dev-server in the [webpack-dev-server documentation][webpack-dev-server-config].
```javascript
const webpackConfig = require("./webpack.config.js");
module.exports = function (grunt) {
grunt.initConfig({
"webpack-dev-server": {
dev: webpackConfig,
},
});
grunt.loadNpmTasks("grunt-webpack");
};
```
> The webpack-dev-server task in this example has one target called `dev`. They can be renamed to everything besides `options`. See the [grunt docs][grunt-targets] for more information about targets.
On the command line you can then do the following.
```bash
# Run webpack-dev-server with the `dev` target
> grunt webpack-dev-server:dev
# Run webpack for all possible targets
> grunt webpack-dev-server
```
> For more examples and information have a look at the [webpack documentation]5] which mostly also applies here besides the noted differences above.
<h2 align="center">Troubleshooting</h2>

@@ -269,5 +324,5 @@

```js
const webpackConfig = require('./webpack.config.js');
const webpackConfig = require("./webpack.config.js");
module.exports = function(grunt) {
module.exports = function (grunt) {
grunt.initConfig({

@@ -279,3 +334,3 @@ webpack: {

grunt.loadNpmTasks('grunt-webpack');
grunt.loadNpmTasks("grunt-webpack");
};

@@ -323,13 +378,8 @@ ```

[1]: https://webpack.js.org/configuration/dev-server/#devserver-inline-cli-only
[2]: http://gruntjs.com/api/grunt.template
[3]: https://webpack.js.org/configuration/
[4]: https://webpack.js.org/configuration/dev-server/#devserver-port-cli-only
[5]: https://webpack.js.org/configuration/dev-server/#devserver-host-cli-only
[6]: https://webpack.js.org/configuration/dev-server/#devserver-hotonly-cli-only
[7]: https://webpack.js.org/configuration/dev-server/#devserver-public-cli-only
[8]: https://gruntjs.com/configuring-tasks#task-configuration-and-targets
[9]: https://webpack.js.org/guides/get-started/
[grunt-template]: http://gruntjs.com/api/grunt.template
[webpack-config]: https://webpack.js.org/configuration/
[webpack-dev-server-config]: https://webpack.js.org/configuration/dev-server/
[grunt-targets]: https://gruntjs.com/configuring-tasks#task-configuration-and-targets
[webpack-start]: https://webpack.js.org/guides/get-started/
[npm]: https://img.shields.io/npm/v/grunt-webpack.svg
[npm-url]: https://npmjs.com/package/grunt-webpack

@@ -1,2 +0,2 @@

import { gruntOptions } from "../default";
import { gruntOptions, mergeOptions } from "../default";

@@ -55,2 +55,56 @@ describe("default options", () => {

});
describe("mergeOptions", () => {
test("all single objects", () => {
expect(
mergeOptions({ default: 1 }, { options: 1 }, { target: 1 }),
).toMatchSnapshot();
});
test("merges sub arrays", () => {
expect(
mergeOptions({ array: [1] }, { array: [2] }, { array: [3] }),
).toMatchSnapshot();
});
test("options as array", () => {
expect(
mergeOptions({ default: 1 }, [{ options1: 1 }, { options2: 1 }], {
target: 1,
}),
).toMatchSnapshot();
});
test("target as array", () => {
expect(
mergeOptions(
{ default: 1 },
{
options: 1,
},
[{ target1: 1 }, { target2: 1 }],
),
).toMatchSnapshot();
});
test("options and target as array", () => {
expect(
mergeOptions(
{ default: 1 },
[{ options1: 1 }, { options2: 1 }],
[{ target1: 1 }, { target2: 1 }],
),
).toMatchSnapshot();
});
test("fails on options and target as unequal array", () => {
expect(() =>
mergeOptions(
{ default: 1 },
[{ options1: 1 }, { options2: 1 }, { options3: 1 }],
[{ target1: 1 }, { target2: 1 }],
),
).toThrowError();
});
});
});

@@ -7,3 +7,3 @@ "use strict";

failOnError: (options) => {
// if watch enabled also default to failOnError false
// if watch enabled default to failOnError false
return Array.isArray(options)

@@ -16,3 +16,3 @@ ? options.every((option) => !option.watch)

keepalive: (options) => {
// if watch enabled also default to keepalive true
// if watch enabled default to keepalive true
return Array.isArray(options)

@@ -40,11 +40,9 @@ ? options.some((option) => option.watch)

const webpackDevServerOptions = {
port: 8080,
host: "localhost",
inline: true,
keepalive: true,
publicPath: "/",
devServer: {
host: "localhost",
},
stats: {
colors: true,
cached: false,
cachedAssets: false,
colors: true,
},

@@ -61,18 +59,25 @@ };

function mergeOptions(defaultOptions, options, targetOptions) {
let result;
if (Array.isArray(targetOptions) && Array.isArray(options)) {
if (targetOptions.length !== options.length) {
throw new Error(
"Cannot have both `options` and `target` be an array with different length. " +
"If using arrays for both please ensure they are the same size.",
);
}
return targetOptions.map((opt, index) =>
mergeWith({}, defaultOptions, options[index], opt, mergeCustomize),
);
}
if (Array.isArray(targetOptions)) {
result = targetOptions.map((opt) =>
return targetOptions.map((opt) =>
mergeWith({}, defaultOptions, options, opt, mergeCustomize),
);
} else {
result = mergeWith(
{},
defaultOptions,
options,
targetOptions,
mergeCustomize,
} else if (Array.isArray(options)) {
return options.map((opt) =>
mergeWith({}, defaultOptions, opt, targetOptions, mergeCustomize),
);
}
return result;
return mergeWith({}, defaultOptions, options, targetOptions, mergeCustomize);
}

@@ -79,0 +84,0 @@

@@ -13,14 +13,30 @@ "use strict";

generateOptions() {
const baseOptions = this.getRawConfig([this.taskName, "options"]);
if (Array.isArray(baseOptions)) {
throw new Error(
"webpack.options must be an object, but array was provided",
);
preloadOptions(done) {
if (!this.options) {
this.generateOptions()
.then((options) => {
this.options = options;
done();
})
.catch((error) => {
// eslint-disable-next-line no-console
console.error(error);
done();
});
} else {
process.nextTick(done);
}
}
async generateOptions() {
const baseOptions = await this.readRawConfig([this.taskName, "options"]);
const targetOptions = await this.readRawConfig([
this.taskName,
this.target,
]);
return defaults.mergeOptions(
this.getDefaultOptions(),
baseOptions,
this.getRawConfig([this.taskName, this.target]),
targetOptions,
);

@@ -31,3 +47,3 @@ }

if (!this.options) {
this.options = this.generateOptions();
throw new Error("Options need to be preloaded with `preloadOptions()`");
}

@@ -57,3 +73,3 @@

getRawConfig(ns) {
async readRawConfig(ns) {
let obj = this.grunt.config.getRaw(ns) || {};

@@ -65,3 +81,6 @@

deepForEach(obj, (value, key, parent) => {
// Might be a Promise
const options = await obj;
deepForEach(options, (value, key, parent) => {
if (typeof value === "string") {

@@ -72,3 +91,3 @@ parent[key] = this.grunt.config.process(value);

return obj;
return options;
}

@@ -75,0 +94,0 @@

@@ -16,3 +16,3 @@ "use strict";

getWebpackOptions() {
const options = this.getOptions().webpack;
const options = this.getOptions();

@@ -29,5 +29,13 @@ if (Array.isArray(options)) {

delete options.webpack;
if (Array.isArray(options)) {
return options.reduce(
(previous, current) => ({
...previous,
...current.devServer,
}),
{},
);
}
return this.filterGruntOptions(options);
return options.devServer;
}

@@ -34,0 +42,0 @@ }

@@ -5,8 +5,8 @@ "use strict";

try {
// webpack 5
CachePlugin = require("webpack/lib/cache/MemoryCachePlugin");
} catch (e) {
// webpack 4
// eslint-disable-next-line import/no-unresolved,import/extensions
CachePlugin = require("webpack/lib/CachePlugin");
} catch (e) {
// webpack 5
// eslint-disable-next-line import/no-unresolved
CachePlugin = require("webpack/lib/cache/MemoryCachePlugin");
}

@@ -13,0 +13,0 @@

@@ -7,45 +7,6 @@ "use strict";

function colorInfo(useColor, msg) {
// Make text blue and bold, so it *pops*
if (useColor) return `\u001b[1m\u001b[34m${msg}\u001b[39m\u001b[22m`;
return msg;
}
function reportReadiness(uri, options, grunt) {
const useColor = !options.stats || options.stats.colors;
grunt.log.writeln(
`${options.progress ? "\n" : ""}Project is running at ${colorInfo(
useColor,
uri,
)}`,
);
grunt.log.writeln(
`webpack output is served from ${colorInfo(useColor, options.publicPath)}`,
);
const contentBase = Array.isArray(options.contentBase)
? options.contentBase.join(", ")
: options.contentBase;
if (contentBase)
grunt.log.writeln(
`Content not from webpack is served from ${colorInfo(
useColor,
contentBase,
)}`,
);
if (options.historyApiFallback)
grunt.log.writeln(
`404s will fallback to ${colorInfo(
useColor,
options.historyApiFallback.index || "/index.html",
)}`,
);
}
module.exports = (grunt) => {
let WebpackDevServer;
try {
// eslint-disable-next-line import/no-unresolved
// eslint-disable-next-line import/no-extraneous-dependencies
WebpackDevServer = require("webpack-dev-server");

@@ -71,11 +32,2 @@ } catch (err) {

let createDomain;
try {
// eslint-disable-next-line import/no-unresolved
createDomain = require("webpack-dev-server/lib/utils/createDomain");
} catch (err) {
// eslint-disable-next-line import/no-unresolved
createDomain = require("webpack-dev-server/lib/util/createDomain");
}
const processPluginFactory = new ProgressPluginFactory(grunt);

@@ -98,3 +50,2 @@

let runningTargetCount = targets.length;
let keepalive = false;

@@ -117,30 +68,17 @@ if (runningTargetCount === 0) {

const optionHelper = new OptionHelper(grunt, this.name, target);
const opts = optionHelper.getOptions();
const webpackOptions = optionHelper.getWebpackOptions();
optionHelper.preloadOptions(() => {
const opts = optionHelper.getOptions();
const webpackOptions = optionHelper.getWebpackOptions();
WebpackDevServer.addDevServerEntrypoints(webpackOptions, opts);
const compiler = webpack(webpackOptions);
if (opts.progress) {
processPluginFactory.addPlugin(compiler, webpackOptions);
}
const compiler = webpack(webpackOptions);
const server = new WebpackDevServer(
optionHelper.getWebpackDevServerOptions(),
compiler,
);
if (opts.progress)
processPluginFactory.addPlugin(compiler, webpackOptions);
new WebpackDevServer(
compiler,
optionHelper.getWebpackDevServerOptions(),
).listen(opts.port, opts.host, () => {
const app = {
address() {
return { port: opts.port };
},
};
const suffix =
opts.inline !== false || opts.lazy === true
? "/"
: "/webpack-dev-server/";
const uri = createDomain(opts, app) + suffix;
reportReadiness(uri, opts, grunt);
keepalive = keepalive || opts.keepalive;
if (--runningTargetCount === 0 && !keepalive) done();
server.startCallback(() => {});
});

@@ -147,0 +85,0 @@ });

@@ -46,68 +46,70 @@ "use strict";

const watch = optionHelper.get("watch");
const opts = {
cache: watch ? false : optionHelper.get("cache"),
failOnError: optionHelper.get("failOnError"),
keepalive: optionHelper.get("keepalive"),
progress: optionHelper.get("progress"),
stats: optionHelper.get("stats"),
storeStatsTo: optionHelper.get("storeStatsTo"),
watch,
};
optionHelper.preloadOptions(() => {
const watch = optionHelper.get("watch");
const opts = {
cache: watch ? false : optionHelper.get("cache"),
failOnError: optionHelper.get("failOnError"),
keepalive: optionHelper.get("keepalive"),
progress: optionHelper.get("progress"),
stats: optionHelper.get("stats"),
storeStatsTo: optionHelper.get("storeStatsTo"),
watch,
};
const webpackOptions = optionHelper.getWebpackOptions();
const webpackOptions = optionHelper.getWebpackOptions();
const compiler = webpack(webpackOptions);
const compiler = webpack(webpackOptions);
if (opts.cache) {
cachePluginFactory.addPlugin(target, compiler);
}
if (opts.progress) {
processPluginFactory.addPlugin(compiler, webpackOptions);
}
const handler = (err, stats) => {
if (err) {
done(err);
return;
if (opts.cache) {
cachePluginFactory.addPlugin(target, compiler);
}
if (opts.stats && !stats.hasErrors()) {
grunt.log.writeln(
stats
.toString(opts.stats)
// add plugin version with and without colors
.replace(
/(\n(.*)Version: webpack (.*)\d+\.\d+\.\d+(.*))\n/,
`$1$2 / grunt-webpack $3${pkg.version}$4\n`,
),
);
if (opts.progress) {
processPluginFactory.addPlugin(compiler, webpackOptions);
}
if (typeof opts.storeStatsTo === "string") {
grunt.config.set(opts.storeStatsTo, stats.toJson(opts.stats));
}
if (stats.hasErrors()) {
// in case opts.stats === false we still want to display errors.
grunt.log.writeln(stats.toString(opts.stats || "errors-only"));
if (opts.failOnError) {
// construct error without stacktrace, as the stack is not relevant here
const error = new Error();
error.stack = null;
done(error);
const handler = (err, stats) => {
if (err) {
done(err);
return;
}
}
keepalive = keepalive || opts.keepalive;
if (opts.stats && !stats.hasErrors()) {
grunt.log.writeln(
stats
.toString(opts.stats)
// add plugin version with and without colors
.replace(
/(\n(.*)Version: webpack (.*)\d+\.\d+\.\d+(.*))\n/,
`$1$2 / grunt-webpack $3${pkg.version}$4\n`,
),
);
}
if (--runningTargetCount === 0 && !keepalive) done();
};
if (typeof opts.storeStatsTo === "string") {
grunt.config.set(opts.storeStatsTo, stats.toJson(opts.stats));
}
if (opts.watch) {
compiler.watch(webpackOptions.watchOptions || {}, handler);
} else {
compiler.run(handler);
}
if (stats.hasErrors()) {
// in case opts.stats === false we still want to display errors.
grunt.log.writeln(stats.toString(opts.stats || "errors-only"));
if (opts.failOnError) {
// construct error without stacktrace, as the stack is not relevant here
const error = new Error();
error.stack = null;
done(error);
return;
}
}
keepalive = keepalive || opts.keepalive;
if (--runningTargetCount === 0 && !keepalive) done();
};
if (opts.watch) {
compiler.watch(webpackOptions.watchOptions || {}, handler);
} else {
compiler.run(handler);
}
});
});

@@ -114,0 +116,0 @@ },

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc