Merge branch 'master' into dev-1

This commit is contained in:
Tobias Koppers 2020-04-14 12:28:55 +02:00
commit d5c31ab864
169 changed files with 8005 additions and 2117 deletions

View File

@ -2,6 +2,8 @@ module.exports = {
printWidth: 80,
useTabs: true,
tabWidth: 2,
trailingComma: "none",
arrowParens: "avoid",
overrides: [
{
files: "*.json",

View File

@ -15,7 +15,7 @@ that include your webpack.config.js, relevant files, and the full error message
**If you have discovered a bug or have a feature suggestion, please [create an issue on GitHub](https://github.com/webpack/webpack/issues/new).**
Do you want to fix an issue? Look at the issues with a tag of [X5: work required (PR / Help Wanted)](https://github.com/webpack/webpack/labels/X5%3A%20work%20required%20%28PR%20%2F%20Help%20Wanted%29). Each issue should be tagged with a difficulty tag -
Do you want to fix an issue? Look at the issues with a tag of [X5: work required (PR / Help Wanted)](https://github.com/webpack/webpack/labels/X5%3A%20work%20required%20%28PR%20%2F%20Help%20Wanted%29). Each issue should be tagged with a difficulty tag -
- D0: My First Commit (Contribution Difficulty)
- D1: Easy (Contribution Difficulty)
@ -41,9 +41,12 @@ your pull request should be accepted quickly.
Something that will increase the chance that your pull request is accepted:
* [Write tests](./test/README.md)
* Follow the existing coding style
* Write a [good commit message](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
- [Write tests](./test/README.md)
- Follow the existing coding style
- Write a [good commit message](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
- For a major fix/feature make sure your PR has an issue and if it doesn't, please create one. This would help discussion with the community, and polishing ideas in case of a new feature.
- Make sure your PR's description contains GitHub's special keyword references that automatically close the related issue when the PR is merged. ([More info](https://github.com/blog/1506-closing-issues-via-pull-requests))
- When you have lot of commits in your PR, it's good practice to squash all your commits in one single commit. ([Learn how to squash here](https://davidwalsh.name/squash-commits-git))
## Documentation
@ -55,3 +58,11 @@ or [check out the issues on the documentation website's repository](https://gith
## Discussions
Gitter is only for small questions. To discuss a subject in detail, please send a link to your forum or blog in the Gitter chat.
## Join the development
- Before you join development, please [set up the project](./_SETUP.md) on your local machine, run it and go through the application completely. Use any command you can find and see what it does. Explore.
> Don't worry ... Nothing will happen to the project or to you due to the exploring. Only thing that will happen is, you'll be more familiar with what is where and might even get some cool ideas on how to improve various aspects of the project.
- If you would like to work on an issue, drop in a comment at the issue. If it is already assigned to someone, but there is no sign of any work being done, please feel free to drop in a comment so that the issue can be assigned to you if the previous assignee has dropped it entirely.

181
README.md
View File

@ -83,11 +83,11 @@ or packaging just about any resource or asset.
**TL;DR**
* Bundles [ES Modules](https://www.2ality.com/2014/09/es6-modules-final.html), [CommonJS](http://wiki.commonjs.org/), and [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD) modules (even combined).
* Can create a single bundle or multiple chunks that are asynchronously loaded at runtime (to reduce initial loading time).
* Dependencies are resolved during compilation, reducing the runtime size.
* Loaders can preprocess files while compiling, e.g. TypeScript to JavaScript, Handlebars strings to compiled functions, images to Base64, etc.
* Highly modular plugin system to do whatever else your application requires.
- Bundles [ES Modules](https://www.2ality.com/2014/09/es6-modules-final.html), [CommonJS](http://wiki.commonjs.org/), and [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD) modules (even combined).
- Can create a single bundle or multiple chunks that are asynchronously loaded at runtime (to reduce initial loading time).
- Dependencies are resolved during compilation, reducing the runtime size.
- Loaders can preprocess files while compiling, e.g. TypeScript to JavaScript, Handlebars strings to compiled functions, images to Base64, etc.
- Highly modular plugin system to do whatever else your application requires.
### Get Started
@ -107,13 +107,13 @@ interface](https://webpack.js.org/plugins/). Most of the features
within webpack itself use this plugin interface. This makes webpack very
**flexible**.
|Name|Status|Install Size|Description|
|:--:|:----:|:----------:|:----------|
|[mini-css-extract-plugin][mini-css]|![mini-css-npm]|![mini-css-size]|Extracts CSS into separate files. It creates a CSS file per JS file which contains CSS.|
|[compression-webpack-plugin][compression]|![compression-npm]|![compression-size]|Prepares compressed versions of assets to serve them with Content-Encoding|
|[i18n-webpack-plugin][i18n]|![i18n-npm]|![i18n-size]|Adds i18n support to your bundles|
|[html-webpack-plugin][html-plugin]|![html-plugin-npm]|![html-plugin-size]| Simplifies creation of HTML files (`index.html`) to serve your bundles|
|[extract-text-webpack-plugin][extract]|![extract-npm]|![extract-size]|Extract text from a bundle, or bundles, into a separate file|
| Name | Status | Install Size | Description |
| :---------------------------------------: | :----------------: | :-----------------: | :-------------------------------------------------------------------------------------- |
| [mini-css-extract-plugin][mini-css] | ![mini-css-npm] | ![mini-css-size] | Extracts CSS into separate files. It creates a CSS file per JS file which contains CSS. |
| [compression-webpack-plugin][compression] | ![compression-npm] | ![compression-size] | Prepares compressed versions of assets to serve them with Content-Encoding |
| [i18n-webpack-plugin][i18n] | ![i18n-npm] | ![i18n-size] | Adds i18n support to your bundles |
| [html-webpack-plugin][html-plugin] | ![html-plugin-npm] | ![html-plugin-size] | Simplifies creation of HTML files (`index.html`) to serve your bundles |
| [extract-text-webpack-plugin][extract] | ![extract-npm] | ![extract-size] | Extract text from a bundle, or bundles, into a separate file |
[common-npm]: https://img.shields.io/npm/v/webpack.svg
[extract]: https://github.com/webpack-contrib/extract-text-webpack-plugin
@ -146,13 +146,12 @@ or are automatically applied via regex from your webpack configuration.
#### Files
|Name|Status|Install Size|Description|
|:--:|:----:|:----------:|:----------|
|[raw-loader][raw]|![raw-npm]|![raw-size]|Loads raw content of a file (utf-8)|
|[val-loader][val]|![val-npm]|![val-size]|Executes code as module and considers exports as JS code|
|[url-loader][url]|![url-npm]|![url-size]|Works like the file loader, but can return a Data Url if the file is smaller than a limit|
|[file-loader][file]|![file-npm]|![file-size]|Emits the file into the output folder and returns the (relative) url|
| Name | Status | Install Size | Description |
| :-----------------: | :---------: | :----------: | :---------------------------------------------------------------------------------------- |
| [raw-loader][raw] | ![raw-npm] | ![raw-size] | Loads raw content of a file (utf-8) |
| [val-loader][val] | ![val-npm] | ![val-size] | Executes code as module and considers exports as JS code |
| [url-loader][url] | ![url-npm] | ![url-size] | Works like the file loader, but can return a Data Url if the file is smaller than a limit |
| [file-loader][file] | ![file-npm] | ![file-size] | Emits the file into the output folder and returns the (relative) url |
[raw]: https://github.com/webpack-contrib/raw-loader
[raw-npm]: https://img.shields.io/npm/v/raw-loader.svg
@ -169,12 +168,11 @@ or are automatically applied via regex from your webpack configuration.
#### JSON
|Name|Status|Install Size|Description|
|:--:|:----:|:----------:|:----------|
|<a href="https://github.com/webpack-contrib/json-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/json.svg"></a>|![json-npm]|![json-size]|Loads a JSON file (included by default)|
|<a href="https://github.com/webpack-contrib/json5-loader"><img width="48" height="10.656" src="https://cdn.rawgit.com/json5/json5-logo/master/json5-logo.svg"></a>|![json5-npm]|![json5-size]|Loads and transpiles a JSON 5 file|
|<a href="https://github.com/awnist/cson-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a>|![cson-npm]|![cson-size]|Loads and transpiles a CSON file|
| Name | Status | Install Size | Description |
| :----------------------------------------------------------------------------------------------------------------------------------------------------------------: | :----------: | :-----------: | :-------------------------------------- |
| <a href="https://github.com/webpack-contrib/json-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/json.svg"></a> | ![json-npm] | ![json-size] | Loads a JSON file (included by default) |
| <a href="https://github.com/webpack-contrib/json5-loader"><img width="48" height="10.656" src="https://cdn.rawgit.com/json5/json5-logo/master/json5-logo.svg"></a> | ![json5-npm] | ![json5-size] | Loads and transpiles a JSON 5 file |
| <a href="https://github.com/awnist/cson-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a> | ![cson-npm] | ![cson-size] | Loads and transpiles a CSON file |
[json-npm]: https://img.shields.io/npm/v/json-loader.svg
[json-size]: https://packagephobia.now.sh/badge?p=json-loader
@ -185,15 +183,14 @@ or are automatically applied via regex from your webpack configuration.
#### Transpiling
|Name|Status|Install Size|Description|
|:--:|:----:|:----------:|:----------|
|<a href="https://github.com/webpack-contrib/script-loader">`<script>`</a>|![script-npm]|![script-size]|Executes a JavaScript file once in global context (like in script tag), `require()`s are not parsed|
|<a href="https://github.com/babel/babel-loader"><img width="48" height="48" title="babel-loader" src="https://worldvectorlogo.com/logos/babel-10.svg"></a>|![babel-npm]|![babel-size]|Loads ES2015+ code and transpiles to ES5 using <a href="https://github.com/babel/babel">Babel</a>|
|<a href="https://github.com/jupl/traceur-loader"><img width="48" height="48" src="https://google.github.com/traceur-compiler/logo/tc.svg"></a>|![traceur-npm]|![traceur-size]|Loads ES2015+ code and transpiles to ES5 using [Traceur](https://github.com/google/traceur-compiler)|
|<a href="https://github.com/TypeStrong/ts-loader"><img width="48" height="48" src="https://cdn.rawgit.com/Microsoft/TypeScript/master/doc/logo.svg"></a>|![type-npm]|![type-size]|Loads TypeScript like JavaScript|
|[`awesome-typescript-loader`](https://github.com/s-panferov/awesome-typescript-loader)|![awesome-typescript-npm]|![awesome-typescript-size]|Awesome TypeScript loader for webpack|
|<a href="https://github.com/webpack-contrib/coffee-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a>|![coffee-npm]|![coffee-size]|Loads CoffeeScript like JavaScript|
| Name | Status | Install Size | Description |
| :--------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------: | :------------------------: | :--------------------------------------------------------------------------------------------------- |
| <a href="https://github.com/webpack-contrib/script-loader">`<script>`</a> | ![script-npm] | ![script-size] | Executes a JavaScript file once in global context (like in script tag), `require()`s are not parsed |
| <a href="https://github.com/babel/babel-loader"><img width="48" height="48" title="babel-loader" src="https://worldvectorlogo.com/logos/babel-10.svg"></a> | ![babel-npm] | ![babel-size] | Loads ES2015+ code and transpiles to ES5 using <a href="https://github.com/babel/babel">Babel</a> |
| <a href="https://github.com/jupl/traceur-loader"><img width="48" height="48" src="https://google.github.com/traceur-compiler/logo/tc.svg"></a> | ![traceur-npm] | ![traceur-size] | Loads ES2015+ code and transpiles to ES5 using [Traceur](https://github.com/google/traceur-compiler) |
| <a href="https://github.com/TypeStrong/ts-loader"><img width="48" height="48" src="https://cdn.rawgit.com/Microsoft/TypeScript/master/doc/logo.svg"></a> | ![type-npm] | ![type-size] | Loads TypeScript like JavaScript |
| [`awesome-typescript-loader`](https://github.com/s-panferov/awesome-typescript-loader) | ![awesome-typescript-npm] | ![awesome-typescript-size] | Awesome TypeScript loader for webpack |
| <a href="https://github.com/webpack-contrib/coffee-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a> | ![coffee-npm] | ![coffee-size] | Loads CoffeeScript like JavaScript |
[script-npm]: https://img.shields.io/npm/v/script-loader.svg
[script-size]: https://packagephobia.now.sh/badge?p=script-loader
@ -210,14 +207,13 @@ or are automatically applied via regex from your webpack configuration.
#### Templating
|Name|Status|Install Size|Description|
|:--:|:----:|:----------:|:----------|
|<a href="https://github.com/webpack-contrib/html-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/html5.svg"></a>|![html-npm]|![html-size]|Exports HTML as string, requires references to static resources|
|<a href="https://github.com/pugjs/pug-loader"><img width="48" height="48" src="https://cdn.rawgit.com/pugjs/pug-logo/master/SVG/pug-final-logo-_-colour-128.svg"></a>|![pug-npm]|![pug-size]|Loads Pug templates and returns a function|
|<a href="https://github.com/peerigon/markdown-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/markdown.svg"></a>|![md-npm]|![md-size]|Compiles Markdown to HTML|
|<a href="https://github.com/posthtml/posthtml-loader"><img width="48" height="48" src="https://posthtml.github.io/posthtml/logo.svg"></a>|![posthtml-npm]|![posthtml-size]|Loads and transforms a HTML file using [PostHTML](https://github.com/posthtml/posthtml)|
|<a href="https://github.com/pcardune/handlebars-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/handlebars-1.svg"></a>|![hbs-npm]|![hbs-size]| Compiles Handlebars to HTML|
| Name | Status | Install Size | Description |
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-------------: | :--------------: | :-------------------------------------------------------------------------------------- |
| <a href="https://github.com/webpack-contrib/html-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/html5.svg"></a> | ![html-npm] | ![html-size] | Exports HTML as string, requires references to static resources |
| <a href="https://github.com/pugjs/pug-loader"><img width="48" height="48" src="https://cdn.rawgit.com/pugjs/pug-logo/master/SVG/pug-final-logo-_-colour-128.svg"></a> | ![pug-npm] | ![pug-size] | Loads Pug templates and returns a function |
| <a href="https://github.com/peerigon/markdown-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/markdown.svg"></a> | ![md-npm] | ![md-size] | Compiles Markdown to HTML |
| <a href="https://github.com/posthtml/posthtml-loader"><img width="48" height="48" src="https://posthtml.github.io/posthtml/logo.svg"></a> | ![posthtml-npm] | ![posthtml-size] | Loads and transforms a HTML file using [PostHTML](https://github.com/posthtml/posthtml) |
| <a href="https://github.com/pcardune/handlebars-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/handlebars-1.svg"></a> | ![hbs-npm] | ![hbs-size] | Compiles Handlebars to HTML |
[html-npm]: https://img.shields.io/npm/v/html-loader.svg
[html-size]: https://packagephobia.now.sh/badge?p=html-loader
@ -234,15 +230,14 @@ or are automatically applied via regex from your webpack configuration.
#### Styling
|Name|Status|Install Size|Description|
|:--:|:----:|:----------:|:----------|
|<a href="https://github.com/webpack-contrib/style-loader">`<style>`</a>|![style-npm]|![style-size]|Add exports of a module as style to DOM|
|<a href="https://github.com/webpack-contrib/css-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/css-3.svg"></a>|![css-npm]|![css-size]|Loads CSS file with resolved imports and returns CSS code|
|<a href="https://github.com/webpack-contrib/less-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/less-63.svg"></a>|![less-npm]|![less-size]|Loads and compiles a LESS file|
|<a href="https://github.com/webpack-contrib/sass-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/sass-1.svg"></a>|![sass-npm]|![sass-size]|Loads and compiles a Sass/SCSS file|
|<a href="https://github.com/shama/stylus-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/stylus.svg"></a>|![stylus-npm]|![stylus-size]|Loads and compiles a Stylus file|
|<a href="https://github.com/postcss/postcss-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/postcss.svg"></a>|![postcss-npm]|![postcss-size]|Loads and transforms a CSS/SSS file using [PostCSS](https://postcss.org)|
| Name | Status | Install Size | Description |
| :-------------------------------------------------------------------------------------------------------------------------------------------: | :------------: | :-------------: | :----------------------------------------------------------------------- |
| <a href="https://github.com/webpack-contrib/style-loader">`<style>`</a> | ![style-npm] | ![style-size] | Add exports of a module as style to DOM |
| <a href="https://github.com/webpack-contrib/css-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/css-3.svg"></a> | ![css-npm] | ![css-size] | Loads CSS file with resolved imports and returns CSS code |
| <a href="https://github.com/webpack-contrib/less-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/less-63.svg"></a> | ![less-npm] | ![less-size] | Loads and compiles a LESS file |
| <a href="https://github.com/webpack-contrib/sass-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/sass-1.svg"></a> | ![sass-npm] | ![sass-size] | Loads and compiles a Sass/SCSS file |
| <a href="https://github.com/shama/stylus-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/stylus.svg"></a> | ![stylus-npm] | ![stylus-size] | Loads and compiles a Stylus file |
| <a href="https://github.com/postcss/postcss-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/postcss.svg"></a> | ![postcss-npm] | ![postcss-size] | Loads and transforms a CSS/SSS file using [PostCSS](https://postcss.org) |
[style-npm]: https://img.shields.io/npm/v/style-loader.svg
[style-size]: https://packagephobia.now.sh/badge?p=style-loader
@ -259,11 +254,11 @@ or are automatically applied via regex from your webpack configuration.
#### Linting & Testing
|Name|Status|Install Size|Description|
|:--:|:----:|:----------:|:----------|
|<a href="https://github.com/webpack-contrib/mocha-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/mocha.svg"></a>|![mocha-npm]|![mocha-size]|Tests with mocha (Browser/NodeJS)|
|<a href="https://github.com/webpack-contrib/eslint-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/eslint.svg"></a>|![eslint-npm]|![eslint-size]|PreLoader for linting code using ESLint|
|<a href="https://github.com/webpack-contrib/jshint-loader"><img width="48" height="20.64" src="https://jshint.com/res/jshint-dark.png"></a>|![jshint-npm]|![jshint-size]|PreLoader for linting code using JSHint|
| Name | Status | Install Size | Description |
| :--------------------------------------------------------------------------------------------------------------------------------------------: | :-----------: | :------------: | :-------------------------------------- |
| <a href="https://github.com/webpack-contrib/mocha-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/mocha.svg"></a> | ![mocha-npm] | ![mocha-size] | Tests with mocha (Browser/NodeJS) |
| <a href="https://github.com/webpack-contrib/eslint-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/eslint.svg"></a> | ![eslint-npm] | ![eslint-size] | PreLoader for linting code using ESLint |
| <a href="https://github.com/webpack-contrib/jshint-loader"><img width="48" height="20.64" src="https://jshint.com/res/jshint-dark.png"></a> | ![jshint-npm] | ![jshint-size] | PreLoader for linting code using JSHint |
[mocha-npm]: https://img.shields.io/npm/v/mocha-loader.svg
[mocha-size]: https://packagephobia.now.sh/badge?p=mocha-loader
@ -276,14 +271,12 @@ or are automatically applied via regex from your webpack configuration.
#### Frameworks
|Name|Status|Install Size|Description|
|:--:|:----:|:----------:|:----------|
|<a href="https://github.com/vuejs/vue-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/vue-9.svg"></a>|![vue-npm]|![vue-size]|Loads and compiles Vue Components|
|<a href="https://github.com/webpack-contrib/polymer-webpack-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/polymer.svg"></a>|![polymer-npm]|![polymer-size]|Process HTML & CSS with preprocessor of choice and `require()` Web Components like first-class modules|
|<a href="https://github.com/TheLarkInn/angular2-template-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/angular-icon-1.svg"></a>|![angular-npm]|![angular-size]| Loads and compiles Angular 2 Components|
|<a href="https://github.com/riot/webpack-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/riot.svg"></a>|![riot-npm]|![riot-size]| Riot official webpack loader|
| Name | Status | Install Size | Description |
| :----------------------------------------------------------------------------------------------------------------------------------------------------------: | :------------: | :-------------: | :----------------------------------------------------------------------------------------------------- |
| <a href="https://github.com/vuejs/vue-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/vue-9.svg"></a> | ![vue-npm] | ![vue-size] | Loads and compiles Vue Components |
| <a href="https://github.com/webpack-contrib/polymer-webpack-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/polymer.svg"></a> | ![polymer-npm] | ![polymer-size] | Process HTML & CSS with preprocessor of choice and `require()` Web Components like first-class modules |
| <a href="https://github.com/TheLarkInn/angular2-template-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/angular-icon-1.svg"></a> | ![angular-npm] | ![angular-size] | Loads and compiles Angular 2 Components |
| <a href="https://github.com/riot/webpack-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/riot.svg"></a> | ![riot-npm] | ![riot-size] | Riot official webpack loader |
[vue-npm]: https://img.shields.io/npm/v/vue-loader.svg
[vue-size]: https://packagephobia.now.sh/badge?p=vue-loader
@ -324,15 +317,17 @@ friendly** by using hashes.
Contributions go far beyond pull requests and commits. Although we love giving you the opportunity to put your stamp on webpack, we also are thrilled to receive a variety of other contributions including:
* [Documentation](https://github.com/webpack/webpack.js.org) updates, enhancements, designs, or bugfixes
* Spelling or grammar fixes
* README.md corrections or redesigns
* Adding unit, or functional tests
* Triaging GitHub issues -- especially determining whether an issue still persists or is reproducible.
* [Searching #webpack on twitter](https://twitter.com/search?q=webpack) and helping someone else who needs help
* Teaching others how to contribute to one of the many webpack's repos!
* [Blogging, speaking about, or creating tutorials](https://github.com/webpack-contrib/awesome-webpack) about one of webpack's many features.
* Helping others in our webpack [gitter channel](https://gitter.im/webpack/webpack).
- [Documentation](https://github.com/webpack/webpack.js.org) updates, enhancements, designs, or bugfixes
- Spelling or grammar fixes
- README.md corrections or redesigns
- Adding unit, or functional tests
- Triaging GitHub issues -- especially determining whether an issue still persists or is reproducible.
- [Searching #webpack on twitter](https://twitter.com/search?q=webpack) and helping someone else who needs help
- Teaching others how to contribute to one of the many webpack's repos!
- [Blogging, speaking about, or creating tutorials](https://github.com/webpack-contrib/awesome-webpack) about one of webpack's many features.
- Helping others in our webpack [gitter channel](https://gitter.im/webpack/webpack).
To get started have a look at our [documentation on contributing](https://github.com/webpack/webpack/blob/master/CONTRIBUTING.md).
If you are worried or don't know where to start, you can **always** reach out to [Sean Larkin (@TheLarkInn) on Twitter](https://twitter.com/thelarkinn) or simply submit an issue and a maintainer can help give you guidance!
@ -416,13 +411,12 @@ Most of the core team members, webpack contributors and contributors in the ecos
This is how we use the donations:
* Allow the core team to work on webpack
* Thank contributors if they invested a large amount of time in contributing
* Support projects in the ecosystem that are of great value for users
* Support projects that are voted most (work in progress)
* Infrastructure cost
* Fees for money handling
- Allow the core team to work on webpack
- Thank contributors if they invested a large amount of time in contributing
- Support projects in the ecosystem that are of great value for users
- Support projects that are voted most (work in progress)
- Infrastructure cost
- Fees for money handling
<h2 align="center">Premium Partners</h2>
@ -745,40 +739,31 @@ src="https://static.monei.net/monei-logo.svg" height="30" alt="MONEI"></a>
<h2 align="center">Special Thanks to</h2>
<p align="center">(In chronological order)</p>
* @google for [Google Web Toolkit (GWT)](http://www.gwtproject.org/), which aims to compile Java to JavaScript. It features a similar [Code Splitting](http://www.gwtproject.org/doc/latest/DevGuideCodeSplitting.html) as webpack.
* @medikoo for [modules-webmake](https://github.com/medikoo/modules-webmake), which is a similar project. webpack was born because I wanted Code Splitting for modules-webmake. Interestingly the [Code Splitting issue is still open](https://github.com/medikoo/modules-webmake/issues/7) (thanks also to @Phoscur for the discussion).
* @substack for [browserify](http://browserify.org/), which is a similar project and source for many ideas.
* @jrburke for [require.js](https://requirejs.org/), which is a similar project and source for many ideas.
* @defunctzombie for the [browser-field spec](https://github.com/defunctzombie/package-browser-field-spec), which makes modules available for node.js, browserify and webpack.
* Every early webpack user, which contributed to webpack by writing issues or PRs. You influenced the direction...
* @shama, @jhnns and @sokra for maintaining this project
* Everyone who has written a loader for webpack. You are the ecosystem...
* Everyone I forgot to mention here, but also influenced webpack.
- [@google](https://github.com/google) for [Google Web Toolkit (GWT)](http://www.gwtproject.org/), which aims to compile Java to JavaScript. It features a similar [Code Splitting](http://www.gwtproject.org/doc/latest/DevGuideCodeSplitting.html) as webpack.
- [@medikoo](https://github.com/medikoo) for [modules-webmake](https://github.com/medikoo/modules-webmake), which is a similar project. webpack was born because I wanted Code Splitting for modules-webmake. Interestingly the [Code Splitting issue is still open](https://github.com/medikoo/modules-webmake/issues/7) (thanks also to @Phoscur for the discussion).
- [@substack](https://github.com/substack) for [browserify](http://browserify.org/), which is a similar project and source for many ideas.
- [@jrburke](https://github.com/jrburke) for [require.js](https://requirejs.org/), which is a similar project and source for many ideas.
- [@defunctzombie](https://github.com/defunctzombie) for the [browser-field spec](https://github.com/defunctzombie/package-browser-field-spec), which makes modules available for node.js, browserify and webpack.
- Every early webpack user, which contributed to webpack by writing issues or PRs. You influenced the direction...
- [@shama](https://github.com/shama), [@jhnns](https://github.com/jhnns) and [@sokra](https://github.com/sokra) for maintaining this project
- Everyone who has written a loader for webpack. You are the ecosystem...
- Everyone I forgot to mention here, but also influenced webpack.
[npm]: https://img.shields.io/npm/v/webpack.svg
[npm-url]: https://npmjs.com/package/webpack
[node]: https://img.shields.io/node/v/webpack.svg
[node-url]: https://nodejs.org
[deps]: https://img.shields.io/david/webpack/webpack.svg
[deps-url]: https://david-dm.org/webpack/webpack
[tests]: https://img.shields.io/travis/webpack/webpack/master.svg
[tests-url]: https://travis-ci.org/webpack/webpack
[prs]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg
[prs-url]: https://webpack.js.org/contribute/
[builds-url]: https://ci.appveyor.com/project/sokra/webpack/branch/master
[builds]: https://ci.appveyor.com/api/projects/status/github/webpack/webpack?svg=true
[builds2]: https://dev.azure.com/webpack/webpack/_apis/build/status/webpack.webpack
[builds2-url]: https://dev.azure.com/webpack/webpack/_build/latest?definitionId=3
[licenses-url]: https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fwebpack%2Fwebpack?ref=badge_shield
[licenses]: https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fwebpack%2Fwebpack.svg?type=shield
[cover]: https://img.shields.io/coveralls/webpack/webpack.svg
[cover-url]: https://coveralls.io/r/webpack/webpack/

View File

@ -60,17 +60,17 @@ yarn test:update-snapshots
### To run code formatter (prettier) run
```bash
yarn pretty
yarn pretty-lint-fix
```
### To run all linters use
This performs linting on:
* eslint (code-lint script)
* schema + dependencies (jest-lint script)
* types (type-lint script)
* format + generated files (special-lint script)
- eslint (code-lint script)
- schema + dependencies (jest-lint script)
- types (type-lint script)
- format + generated files (special-lint script)
```bash
yarn lint

View File

@ -7,7 +7,7 @@ const outputPath = path.join(__dirname, "js");
const benchmarkOptions = {
defer: true,
onCycle: function() {
onCycle: function () {
process.stderr.write(".");
},
minSamples: 10

View File

@ -166,6 +166,8 @@
"valign",
"returnfalse",
"return'development",
"datastructures",
"prewalking",
"overridables",
"overridable",

View File

@ -19,7 +19,7 @@ export type Bail = boolean;
/**
* Cache generated modules and chunks to improve performance for multiple incremental builds.
*/
export type Cache = CacheNormalized | true;
export type Cache = true | CacheNormalized;
/**
* Cache generated modules and chunks to improve performance for multiple incremental builds.
*/
@ -51,11 +51,7 @@ export type EntryStatic = EntryObject | EntryUnnamed;
/**
* Module(s) that are loaded upon startup.
*/
export type EntryItem = string | NonEmptyArrayOfUniqueStringValues;
/**
* A non-empty array of non-empty strings.
*/
export type NonEmptyArrayOfUniqueStringValues = [string, ...string[]];
export type EntryItem = [string, ...string[]] | string;
/**
* Specifies the name of each output file on disk. You must **not** specify an absolute path here! The `output.path` option determines the location on disk the files are written to, filename is used solely for naming the individual files.
*/
@ -72,11 +68,11 @@ export type AuxiliaryComment = string | LibraryCustomUmdCommentObject;
/**
* Specify which export should be exposed as library.
*/
export type LibraryExport = string | string[];
export type LibraryExport = string[] | string;
/**
* The name of the library (some types allow unnamed libraries too).
*/
export type LibraryName = string | string[] | LibraryCustomUmdObject;
export type LibraryName = string[] | string | LibraryCustomUmdObject;
/**
* Type of library.
*/
@ -108,43 +104,30 @@ export type EntryUnnamed = EntryItem;
/**
* Specify dependencies that shouldn't be resolved by webpack, but should become dependencies of the resulting bundle. The kind of the dependency depends on `output.libraryTarget`.
*/
export type Externals =
| ((
context: string,
request: string,
callback: (err?: Error, result?: string) => void
) => void)
| ExternalItem
| (
| ((
context: string,
request: string,
callback: (err?: Error, result?: string) => void
) => void)
| ExternalItem
)[];
export type Externals = ExternalItem[] | ExternalItem;
/**
* Specify dependency that shouldn't be resolved by webpack, but should become dependencies of the resulting bundle. The kind of the dependency depends on `output.libraryTarget`.
*/
export type ExternalItem =
| RegExp
| string
| {
/**
* The dependency used for the external.
*/
[k: string]:
| string[]
| boolean
| string
| {
[k: string]: any;
}
| ArrayOfStringValues
| boolean;
};
}
| RegExp;
/**
* Array of strings.
*/
export type ArrayOfStringValues = string[];
| ((
context: string,
request: string,
callback: (err?: Error, result?: string) => void
) => void);
/**
* Specifies the default type of externals ('amd*', 'umd*', 'system' and 'jsonp' depend on output.libraryTarget set to the same value).
*/
@ -168,7 +151,7 @@ export type ExternalsType =
/**
* Filtering values.
*/
export type FilterTypes = FilterItemTypes | FilterItemTypes[];
export type FilterTypes = FilterItemTypes[] | FilterItemTypes;
/**
* Filtering value, regexp or function.
*/
@ -187,8 +170,6 @@ export type RuleSetConditionOrConditions = RuleSetCondition | RuleSetConditions;
export type RuleSetCondition =
| RegExp
| string
| ((value: string) => boolean)
| RuleSetConditions
| {
/**
* Logical AND.
@ -202,7 +183,9 @@ export type RuleSetCondition =
* Logical OR.
*/
or?: RuleSetConditions;
};
}
| ((value: string) => boolean)
| RuleSetConditions;
/**
* A list of rule conditions.
*/
@ -219,8 +202,6 @@ export type RuleSetConditionOrConditionsAbsolute =
export type RuleSetConditionAbsolute =
| RegExp
| string
| ((value: string) => boolean)
| RuleSetConditionsAbsolute
| {
/**
* Logical AND.
@ -234,7 +215,9 @@ export type RuleSetConditionAbsolute =
* Logical OR.
*/
or?: RuleSetConditionsAbsolute;
};
}
| ((value: string) => boolean)
| RuleSetConditionsAbsolute;
/**
* A list of rule conditions matching an absolute path.
*/
@ -243,19 +226,25 @@ export type RuleSetConditionsAbsolute = RuleSetConditionAbsolute[];
* A loader request.
*/
export type RuleSetLoader = string;
/**
* Options passed to a loader.
*/
export type RuleSetLoaderOptions =
| string
| {
[k: string]: any;
};
/**
* A list of descriptions of loaders applied.
*/
export type RuleSetUse =
| RuleSetUseItem
| RuleSetUseItem[]
| ((data: object) => RuleSetUseItem[])
| RuleSetUseItem[];
| RuleSetUseItem;
/**
* A description of an applied loader.
*/
export type RuleSetUseItem =
| RuleSetLoader
| ((data: object) => RuleSetUseItem | RuleSetUseItem[])
| {
/**
* Unique loader options identifier.
@ -269,19 +258,9 @@ export type RuleSetUseItem =
* Loader options.
*/
options?: RuleSetLoaderOptions;
};
/**
* Options passed to a loader.
*/
export type RuleSetLoaderOptions =
| {
[k: string]: any;
}
| string;
/**
* List of string or string-array values.
*/
export type ArrayOfStringOrStringArrayValues = (string | string[])[];
| ((data: object) => RuleSetUseItem | RuleSetUseItem[])
| RuleSetLoader;
/**
* A list of rules.
*/
@ -305,8 +284,8 @@ export type WebpackPluginFunction = (
* Create an additional chunk which contains only the webpack runtime and chunk hash maps.
*/
export type OptimizationRuntimeChunk =
| boolean
| ("single" | "multiple")
| boolean
| {
/**
* The name or name factory for the runtime chunks.
@ -377,7 +356,7 @@ export type DevtoolNamespace = string;
/**
* The maximum EcmaScript version of the webpack generated code (doesn't include input source code from modules).
*/
export type EcmaVersion = number | 2009;
export type EcmaVersion = 2009 | number;
/**
* List of library types enabled for use by entry points.
*/
@ -511,8 +490,6 @@ export type ResolveLoader = ResolveOptions;
* Stats options object or preset name.
*/
export type Stats =
| StatsOptions
| boolean
| (
| "none"
| "errors-only"
@ -521,7 +498,9 @@ export type Stats =
| "detailed"
| "verbose"
| "errors-warnings"
);
)
| boolean
| StatsOptions;
/**
* Environment to build for.
*/
@ -703,7 +682,7 @@ export interface MemoryCacheOptions {
*/
immutablePaths?: string[];
/**
* List of paths that are managed by a package manager and can be trusted to not being modified otherwise.
* List of paths that are managed by a package manager and can be trusted to not be modified otherwise.
*/
managedPaths?: string[];
/**
@ -749,7 +728,7 @@ export interface FileCacheOptions {
*/
immutablePaths?: string[];
/**
* List of paths that are managed by a package manager and can be trusted to not being modified otherwise.
* List of paths that are managed by a package manager and can be trusted to not be modified otherwise.
*/
managedPaths?: string[];
/**
@ -791,7 +770,7 @@ export interface EntryDescription {
/**
* The entrypoints that the current entrypoint depend on. They must be loaded when this entrypoint is loaded.
*/
dependOn?: string | NonEmptyArrayOfUniqueStringValues;
dependOn?: [string, ...string[]] | string;
/**
* Specifies the name of each output file on disk. You must **not** specify an absolute path here! The `output.path` option determines the location on disk the files are written to, filename is used solely for naming the individual files.
*/
@ -866,7 +845,7 @@ export interface LibraryCustomUmdObject {
/**
* Name of the property exposed globally by a UMD library.
*/
root?: string | string[];
root?: string[] | string;
}
/**
* Enables/Disables experiments (experimental features with relax SemVer compatibility).
@ -912,7 +891,7 @@ export interface InfrastructureLogging {
/**
* Enable debug logging for specific loggers.
*/
debug?: FilterTypes | boolean;
debug?: boolean | FilterTypes;
/**
* Log level.
*/
@ -943,7 +922,7 @@ export interface Module {
/**
* Sets the default regular expression for full dynamic dependencies.
*/
exprContextRegExp?: boolean | RegExp;
exprContextRegExp?: RegExp | boolean;
/**
* Set the default request for full dynamic dependencies.
*/
@ -952,11 +931,10 @@ export interface Module {
* Don't parse files matching. It's matched against the full resolved request.
*/
noParse?:
| [RegExp, ...RegExp[]]
| [RegExp | string | Function, ...(RegExp | string | Function)[]]
| RegExp
| Function
| [string, ...string[]]
| string;
| string
| Function;
/**
* An array of rules applied for modules.
*/
@ -980,7 +958,7 @@ export interface Module {
/**
* Sets the regular expression when using the require function in a not statically analyse-able way.
*/
unknownContextRegExp?: boolean | RegExp;
unknownContextRegExp?: RegExp | boolean;
/**
* Sets the request when using the require function in a not statically analyse-able way.
*/
@ -1035,7 +1013,7 @@ export interface RuleSetRule {
/**
* Shortcut for use.loader.
*/
loader?: RuleSetLoader | RuleSetUse;
loader?: RuleSetLoader;
/**
* Only execute the first matching rule in this array.
*/
@ -1099,13 +1077,7 @@ export interface ResolveOptions {
/**
* New request.
*/
[k: string]: string | string[] | false;
}
| {
/**
* New request.
*/
alias: string | string[] | false;
alias: string[] | false | string;
/**
* Request to be redirected.
*/
@ -1114,11 +1086,17 @@ export interface ResolveOptions {
* Redirect only exact matching request.
*/
onlyModule?: boolean;
}[];
}[]
| {
/**
* New request.
*/
[k: string]: string[] | false | string;
};
/**
* Fields in the description file (package.json) which are used to redirect requests inside the module.
* Fields in the description file (usually package.json) which are used to redirect requests inside the module.
*/
aliasFields?: ArrayOfStringOrStringArrayValues;
aliasFields?: (string[] | string)[];
/**
* Enable caching of successfully resolved requests (cache entries are revalidated).
*/
@ -1132,9 +1110,9 @@ export interface ResolveOptions {
*/
cacheWithContext?: boolean;
/**
* Filenames used to find a description file.
* Filenames used to find a description file (like a package.json).
*/
descriptionFiles?: ArrayOfStringValues;
descriptionFiles?: string[];
/**
* Enforce using one of the extensions from the extensions option.
*/
@ -1142,7 +1120,7 @@ export interface ResolveOptions {
/**
* Extensions added to the request when trying to find the file.
*/
extensions?: ArrayOfStringValues;
extensions?: string[];
/**
* Filesystem for the resolver.
*/
@ -1152,15 +1130,15 @@ export interface ResolveOptions {
/**
* Field names from the description file (package.json) which are used to find the default entry point.
*/
mainFields?: ArrayOfStringOrStringArrayValues;
mainFields?: (string[] | string)[];
/**
* Filenames used to find the default entry point if there is no description file or main field.
*/
mainFiles?: ArrayOfStringValues;
mainFiles?: string[];
/**
* Folder names or directory paths where to find modules.
*/
modules?: ArrayOfStringValues;
modules?: string[];
/**
* Plugins for the resolver.
*/
@ -1337,9 +1315,9 @@ export interface OptimizationSplitChunksOptions {
*/
[k: string]:
| false
| Function
| string
| RegExp
| string
| Function
| OptimizationSplitChunksCacheGroup;
};
/**
@ -1419,7 +1397,7 @@ export interface OptimizationSplitChunksOptions {
/**
* Give chunks created a name (chunks with equal name are merged).
*/
name?: false | Function | string;
name?: false | string | Function;
}
/**
* Options object for describing behavior of a cache group selecting modules that should be cached together.
@ -1487,7 +1465,7 @@ export interface OptimizationSplitChunksCacheGroup {
/**
* Give chunks for this cache group a name (chunks with equal name are merged).
*/
name?: false | Function | string;
name?: false | string | Function;
/**
* Priority of this cache group.
*/
@ -1499,11 +1477,11 @@ export interface OptimizationSplitChunksCacheGroup {
/**
* Assign modules to a cache group by module name.
*/
test?: Function | string | RegExp;
test?: RegExp | string | Function;
/**
* Assign modules to a cache group by module type.
*/
type?: Function | string | RegExp;
type?: RegExp | string | Function;
}
/**
* Options affecting the output of the compilation. `output` options tell webpack how to write the compiled files to disk.
@ -1801,7 +1779,7 @@ export interface StatsOptions {
/**
* Please use excludeModules instead.
*/
exclude?: FilterTypes | boolean;
exclude?: boolean | FilterTypes;
/**
* Suppress assets that match the specified filters. Filters can be Strings, RegExps or Functions.
*/
@ -1809,7 +1787,7 @@ export interface StatsOptions {
/**
* Suppress modules that match the specified filters. Filters can be Strings, RegExps, Booleans or Functions.
*/
excludeModules?: FilterTypes | boolean;
excludeModules?: boolean | FilterTypes;
/**
* Add the hash of the compilation.
*/
@ -1821,11 +1799,11 @@ export interface StatsOptions {
/**
* Add logging output.
*/
logging?: boolean | ("none" | "error" | "warn" | "info" | "log" | "verbose");
logging?: ("none" | "error" | "warn" | "info" | "log" | "verbose") | boolean;
/**
* Include debug logging of specified loggers (i. e. for plugins or loaders). Filters can be Strings, RegExps or Functions.
*/
loggingDebug?: FilterTypes | boolean;
loggingDebug?: boolean | FilterTypes;
/**
* Add stack traces to logging output.
*/
@ -1926,11 +1904,11 @@ export interface WatchOptions {
/**
* Ignore some files from watching (glob pattern).
*/
ignored?: string | ArrayOfStringValues;
ignored?: string[] | string;
/**
* Enable polling mode for watching.
*/
poll?: boolean | number;
poll?: number | boolean;
/**
* Stop watching when stdin stream has ended.
*/
@ -1943,7 +1921,7 @@ export interface EntryDescriptionNormalized {
/**
* The entrypoints that the current entrypoint depend on. They must be loaded when this entrypoint is loaded.
*/
dependOn?: NonEmptyArrayOfUniqueStringValues;
dependOn?: [string, ...string[]];
/**
* Specifies the name of each output file on disk. You must **not** specify an absolute path here! The `output.path` option determines the location on disk the files are written to, filename is used solely for naming the individual files.
*/
@ -1951,7 +1929,7 @@ export interface EntryDescriptionNormalized {
/**
* Module(s) that are loaded upon startup. The last one is exported.
*/
import: NonEmptyArrayOfUniqueStringValues;
import: [string, ...string[]];
/**
* Options for library.
*/

View File

@ -5,9 +5,9 @@
*/
export type BannerPluginArgument =
| string
| BannerPluginOptions
| BannerFunction
| string;
| BannerFunction;
/**
* The banner as function, it will be wrapped in a comment.
*/
@ -29,7 +29,7 @@ export interface BannerPluginOptions {
/**
* Specifies the banner.
*/
banner: BannerFunction | string;
banner: string | BannerFunction;
/**
* If true, the banner will only be added to the entry chunks.
*/

View File

@ -17,7 +17,7 @@ export type DllReferencePluginOptions =
/**
* An object containing content and name or a string to the absolute path of the JSON manifest to be loaded upon compilation.
*/
manifest: DllReferencePluginOptionsManifest | string;
manifest: string | DllReferencePluginOptionsManifest;
/**
* The name where the dll is exposed (external name, defaults to manifest.name).
*/
@ -81,7 +81,8 @@ export type DllReferencePluginOptionsSourceType =
| "amd-require"
| "umd"
| "umd2"
| "jsonp";
| "jsonp"
| "system";
/**
* An object containing content, name and type.
@ -117,7 +118,7 @@ export interface DllReferencePluginOptionsContent {
/**
* Information about the provided exports of the module.
*/
exports?: true | string[];
exports?: string[] | true;
/**
* Module ID.
*/

View File

@ -29,7 +29,7 @@ export interface SourceMapDevToolPluginOptions {
/**
* Generator string or function to create identifiers of modules for the 'sources' array in the SourceMap used only if 'moduleFilenameTemplate' would result in a conflict.
*/
fallbackModuleFilenameTemplate?: Function | string;
fallbackModuleFilenameTemplate?: string | Function;
/**
* Path prefix to which the [file] placeholder is relative to.
*/
@ -49,7 +49,7 @@ export interface SourceMapDevToolPluginOptions {
/**
* Generator string or function to create identifiers of modules for the 'sources' array in the SourceMap.
*/
moduleFilenameTemplate?: Function | string;
moduleFilenameTemplate?: string | Function;
/**
* Namespace prefix to allow multiple webpack roots in the devtools.
*/

View File

@ -8,5 +8,5 @@ export interface WatchIgnorePluginOptions {
/**
* A list of RegExps or absolute paths to directories or files that should be ignored.
*/
paths: [string | RegExp, ...(string | RegExp)[]];
paths: [RegExp | string, ...(RegExp | string)[]];
}

View File

@ -1,4 +1,4 @@
This example shows automatically created async commons chunks.
This example shows the automatically created async commons chunks.
The example entry references two chunks:
@ -16,7 +16,7 @@ The example entry references two chunks:
These chunks share modules `a` and `b`. The optimization extract these into chunk Z:
Note: Actually the optimization compare size of chunk Z to some minimum value, but this is disabled from this example. In practice there is no configuration needed for this.
Note: The optimization compares the size of chunk Z to some minimum value, but this is disabled from this example. In practice, there is no configuration needed for this.
- entry chunk
- async require -> chunk X & Z

View File

@ -1,4 +1,4 @@
This example shows automatically created async commons chunks.
This example shows the automatically created async commons chunks.
The example entry references two chunks:
@ -16,7 +16,7 @@ The example entry references two chunks:
These chunks share modules `a` and `b`. The optimization extract these into chunk Z:
Note: Actually the optimization compare size of chunk Z to some minimum value, but this is disabled from this example. In practice there is no configuration needed for this.
Note: The optimization compares the size of chunk Z to some minimum value, but this is disabled from this example. In practice, there is no configuration needed for this.
- entry chunk
- async require -> chunk X & Z

View File

@ -1,6 +1,6 @@
// harmony module
// import from CommonJs module
// import from CommonJS module
import fs from "./fs";
import { readFile } from "./fs";
import * as fs2 from "./fs";

View File

@ -1,10 +1,10 @@
This example demonstrates how webpack tracks the using of ES6 imports and exports. Only used exports are emitted to the resulting bundle. The minimizing step then removes the declarations because they are unused.
This example demonstrates how webpack tracks the usage of ES6 imports and exports. Only used exports are emitted to the resulting bundle. The minimizing step then removes the declarations because they are unused.
Excluding unused exports from bundles is known as "[tree-shaking](http://www.2ality.com/2015/12/webpack-tree-shaking.html)".
In this example, only `add` and `multiply` in `./math.js` are used by the app. `list` is unused and is not included in the minimized bundle (Look for `Array.from` in the minimized bundle).
In addition to that, `library.js` simulates an entry point to a big library. `library.js` re-exports multiple identifiers from submodules. Often big parts of that is unused, like `abc.js`. Note how the usage information flows from `example.js` through `library.js` into `abc.js` and all declarations in `abc.js` are not included in the minimized bundle (Look for `console.log("a")` in the minimized bundle).
In addition to that, `library.js` simulates an entry point to a big library. `library.js` re-exports multiple identifiers from submodules. Often big parts of that are unused, like `abc.js`. Note how the usage information flows from `example.js` through `library.js` into `abc.js` and all declarations in `abc.js` are not included in the minimized bundle (Look for `console.log("a")` in the minimized bundle).
# example.js

View File

@ -1,10 +1,10 @@
This example demonstrates how webpack tracks the using of ES6 imports and exports. Only used exports are emitted to the resulting bundle. The minimizing step then removes the declarations because they are unused.
This example demonstrates how webpack tracks the usage of ES6 imports and exports. Only used exports are emitted to the resulting bundle. The minimizing step then removes the declarations because they are unused.
Excluding unused exports from bundles is known as "[tree-shaking](http://www.2ality.com/2015/12/webpack-tree-shaking.html)".
In this example, only `add` and `multiply` in `./math.js` are used by the app. `list` is unused and is not included in the minimized bundle (Look for `Array.from` in the minimized bundle).
In addition to that, `library.js` simulates an entry point to a big library. `library.js` re-exports multiple identifiers from submodules. Often big parts of that is unused, like `abc.js`. Note how the usage information flows from `example.js` through `library.js` into `abc.js` and all declarations in `abc.js` are not included in the minimized bundle (Look for `console.log("a")` in the minimized bundle).
In addition to that, `library.js` simulates an entry point to a big library. `library.js` re-exports multiple identifiers from submodules. Often big parts of that are unused, like `abc.js`. Note how the usage information flows from `example.js` through `library.js` into `abc.js` and all declarations in `abc.js` are not included in the minimized bundle (Look for `console.log("a")` in the minimized bundle).
# example.js

View File

@ -1,12 +1,12 @@
This example demonstrates the AggressiveSplittingPlugin for splitting the bundle into multiple smaller chunks to improve caching. This works best with a HTTP2 web server, otherwise there is an overhead for the increased number of requests.
This example demonstrates the AggressiveSplittingPlugin for splitting the bundle into multiple smaller chunks to improve caching. This works best with an HTTP2 web server, otherwise, there is an overhead for the increased number of requests.
AggressiveSplittingPlugin splits every chunk until it reaches the specified `maxSize`. In this example it tries to create chunks with <50kB raw code, which typically minimizes to ~10kB. It groups modules together by folder structure, because modules in the same folder are likely to have similar repetitive text, making them gzip efficiently together. They are also likely to change together.
AggressiveSplittingPlugin splits every chunk until it reaches the specified `maxSize`. In this example, it tries to create chunks with <50kB raw code, which typically minimizes to ~10kB. It groups modules by folder structure because modules in the same folder are likely to have similar repetitive text, making them gzip efficiently together. They are also likely to change together.
AggressiveSplittingPlugin records its splitting in the webpack records. When it is next run, it tries to use the last recorded splitting. Since changes to application code between one run and the next are usually in only a few modules (or just one), re-using the old splittings (and chunks, which are probably still in the client's cache), is highly advantageous.
Only chunks which are bigger than the specified `minSize` are stored into the records. This ensures that these chunks fill up as your application grows, instead of creating many records of small chunks for every change.
Only chunks that are bigger than the specified `minSize` are stored into the records. This ensures that these chunks fill up as your application grows, instead of creating many records of small chunks for every change.
If a module changes, its chunks are declared to be invalid, and are put back into the module pool. New chunks are created from all modules in the pool.
If a module changes, its chunks are declared to be invalid and are put back into the module pool. New chunks are created from all modules in the pool.
There is a tradeoff here:
@ -14,7 +14,7 @@ The caching improves with smaller `maxSize`, as chunks change less often and can
The compression improves with bigger `maxSize`, as gzip works better for bigger files. It's more likely to find duplicate strings, etc.
The backward compatibility (non HTTP2 client) improves with bigger `maxSize`, as the number of requests decreases.
The backward compatibility (non-HTTP2 client) improves with bigger `maxSize`, as the number of requests decreases.
```js
var path = require("path");

View File

@ -1,12 +1,12 @@
This example demonstrates the AggressiveSplittingPlugin for splitting the bundle into multiple smaller chunks to improve caching. This works best with a HTTP2 web server, otherwise there is an overhead for the increased number of requests.
This example demonstrates the AggressiveSplittingPlugin for splitting the bundle into multiple smaller chunks to improve caching. This works best with an HTTP2 web server, otherwise, there is an overhead for the increased number of requests.
AggressiveSplittingPlugin splits every chunk until it reaches the specified `maxSize`. In this example it tries to create chunks with <50kB raw code, which typically minimizes to ~10kB. It groups modules together by folder structure, because modules in the same folder are likely to have similar repetitive text, making them gzip efficiently together. They are also likely to change together.
AggressiveSplittingPlugin splits every chunk until it reaches the specified `maxSize`. In this example, it tries to create chunks with <50kB raw code, which typically minimizes to ~10kB. It groups modules by folder structure, because modules in the same folder are likely to have similar repetitive text, making them gzip efficiently together. They are also likely to change together.
AggressiveSplittingPlugin records its splitting in the webpack records. When it is next run, it tries to use the last recorded splitting. Since changes to application code between one run and the next are usually in only a few modules (or just one), re-using the old splittings (and chunks, which are probably still in the client's cache), is highly advantageous.
Only chunks which are bigger than the specified `minSize` are stored into the records. This ensures that these chunks fill up as your application grows, instead of creating many records of small chunks for every change.
Only chunks that are bigger than the specified `minSize` are stored into the records. This ensures that these chunks fill up as your application grows, instead of creating many records of small chunks for every change.
If a module changes, its chunks are declared to be invalid, and are put back into the module pool. New chunks are created from all modules in the pool.
If a module changes, its chunks are declared to be invalid and are put back into the module pool. New chunks are created from all modules in the pool.
There is a tradeoff here:
@ -14,7 +14,7 @@ The caching improves with smaller `maxSize`, as chunks change less often and can
The compression improves with bigger `maxSize`, as gzip works better for bigger files. It's more likely to find duplicate strings, etc.
The backward compatibility (non HTTP2 client) improves with bigger `maxSize`, as the number of requests decreases.
The backward compatibility (non-HTTP2 client) improves with bigger `maxSize`, as the number of requests decreases.
```js
_{{webpack.config.js}}_

View File

@ -2,12 +2,12 @@
This example illustrates webpack's algorithm for automatic deduplication using `optimization.splitChunks`.
This example application contains 7 pages, each importing 1-3 modules from the `node_modules` folder (vendor libs) and 0-3 modules from the `stuff` folder (application modules). In reality an application is probably more complex, but the same mechanisms apply.
This example application contains 7 pages, each importing 1-3 modules from the `node_modules` folder (vendor libs) and 0-3 modules from the `stuff` folder (application modules). In reality, an application is probably more complex, but the same mechanisms apply.
The following configuration is used:
- `optimization.splitChunks.chunks: "all"` - This opt-in into automatic splitting of initial chunks which is off by default
- `optimization.splitChunks.maxInitial/AsyncRequests: 20` - This opt-in into a HTTP2 optimized splitting mode by increasing the allowed amount of requests. Browser only supports 6 requests in parallel for HTTP1.1.
- `optimization.splitChunks.maxInitial/AsyncRequests: 20` - This opt-in into an HTTP2 optimized splitting mode by increasing the allowed amount of requests. The browser only supports 6 requests in parallel for HTTP1.1.
# Interpreting the result
@ -16,11 +16,11 @@ The following configuration is used:
- `vendors~pageA.js` vendors only used by a single page but larger than the threshold in size
- `pageA~pageD~pageF.js` application modules shared by these pages and larger than the threshold in size
The threshold is here 40 bytes, but by default (in a real application) 30kb.
Here, the threshold is 40 bytes but by default (in a real application) 30kb.
Some modules are intentionally duplicated, i. e. `./stuff/s4.js` is shared by `pageA` and `pageC`, but it's the only shared module so no separate output file is created because it would be smaller than the threshold. A separate request (which comes with an overhead and worsen gzipping) is not worth the extra bytes.
Note: decreasing `maxInitial/AsyncRequest` will increase duplication further to reduce the number of requests. Duplication doesn't affect initial page load, it only affects download size of navigations to other pages of the application.
Note: decreasing `maxInitial/AsyncRequest` will increase duplication further to reduce the number of requests. Duplication doesn't affect the initial page load, it only affects download size of navigations to other pages of the application.
## webpack.config.js

View File

@ -2,12 +2,12 @@
This example illustrates webpack's algorithm for automatic deduplication using `optimization.splitChunks`.
This example application contains 7 pages, each importing 1-3 modules from the `node_modules` folder (vendor libs) and 0-3 modules from the `stuff` folder (application modules). In reality an application is probably more complex, but the same mechanisms apply.
This example application contains 7 pages, each importing 1-3 modules from the `node_modules` folder (vendor libs) and 0-3 modules from the `stuff` folder (application modules). In reality, an application is probably more complex, but the same mechanisms apply.
The following configuration is used:
- `optimization.splitChunks.chunks: "all"` - This opt-in into automatic splitting of initial chunks which is off by default
- `optimization.splitChunks.maxInitial/AsyncRequests: 20` - This opt-in into a HTTP2 optimized splitting mode by increasing the allowed amount of requests. Browser only supports 6 requests in parallel for HTTP1.1.
- `optimization.splitChunks.maxInitial/AsyncRequests: 20` - This opt-in into an HTTP2 optimized splitting mode by increasing the allowed amount of requests. The browser only supports 6 requests in parallel for HTTP1.1.
# Interpreting the result
@ -16,11 +16,11 @@ The following configuration is used:
- `vendors~pageA.js` vendors only used by a single page but larger than the threshold in size
- `pageA~pageD~pageF.js` application modules shared by these pages and larger than the threshold in size
The threshold is here 40 bytes, but by default (in a real application) 30kb.
Here, the threshold is 40 bytes but by default (in a real application) 30kb.
Some modules are intentionally duplicated, i. e. `./stuff/s4.js` is shared by `pageA` and `pageC`, but it's the only shared module so no separate output file is created because it would be smaller than the threshold. A separate request (which comes with an overhead and worsen gzipping) is not worth the extra bytes.
Note: decreasing `maxInitial/AsyncRequest` will increase duplication further to reduce the number of requests. Duplication doesn't affect initial page load, it only affects download size of navigations to other pages of the application.
Note: decreasing `maxInitial/AsyncRequest` will increase duplication further to reduce the number of requests. Duplication doesn't affect the initial page load, it only affects download size of navigations to other pages of the application.
## webpack.config.js

View File

@ -1,11 +1,11 @@
This example shows how you can mix different module styles in webpack. Here CommonJs, AMD and Harmony Modules (ES6 Modules) are used. In addition to that there are different types of dynamic requires (`"../require.context/templates/"+amd1+".js"` and `Math.random() < 0.5 ? "./commonjs" : "./amd"`).
This example shows how you can mix different module styles in webpack. Here CommonJS, AMD and Harmony Modules (ES6 Modules) are used. In addition to that there are different types of dynamic requires (`"../require.context/templates/"+amd1+".js"` and `Math.random() < 0.5 ? "./commonjs" : "./amd"`).
You see that everything is working nicely together.
# example.js
```javascript
// CommonJs-style requires
// CommonJS-style requires
var commonjs1 = require("./commonjs");
var amd1 = require("./amd");
var harmony1 = require("./harmony");
@ -41,7 +41,7 @@ define(
# commonjs.js
```javascript
// CommonJs Module Format
// CommonJS Module Format
module.exports = 123;
// but you can use amd style requires
@ -68,7 +68,7 @@ require(
/*! runtime requirements: module, __webpack_require__, __webpack_require__.oe, __webpack_require__.* */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
// CommonJs Module Format
// CommonJS Module Format
module.exports = 123;
// but you can use amd style requires

View File

@ -1,4 +1,4 @@
This example shows how you can mix different module styles in webpack. Here CommonJs, AMD and Harmony Modules (ES6 Modules) are used. In addition to that there are different types of dynamic requires (`"../require.context/templates/"+amd1+".js"` and `Math.random() < 0.5 ? "./commonjs" : "./amd"`).
This example shows how you can mix different module styles in webpack. Here CommonJS, AMD and Harmony Modules (ES6 Modules) are used. In addition to that there are different types of dynamic requires (`"../require.context/templates/"+amd1+".js"` and `Math.random() < 0.5 ? "./commonjs" : "./amd"`).
You see that everything is working nicely together.

View File

@ -1,8 +1,8 @@
This example demonstrates how to build a complex library with webpack. The library consist of multiple parts that are usable on its own and together.
This example demonstrates how to build a complex library with webpack. The library consists of multiple parts that are usable on its own and together.
When using this library with script tags it exports itself to the namespace `MyLibrary` and each part to a property in this namespace (`MyLibrary.alpha` and `MyLibrary.beta`). When consuming the library with CommonsJs or AMD it just export each part.
When using this library with script tags it exports itself to the namespace `MyLibrary` and each part to a property in this namespace (`MyLibrary.alpha` and `MyLibrary.beta`). When consuming the library with CommonsJS or AMD it just exports each part.
We are using multiple entry points (`entry` option) to build every part of the library as separate output file. The `output.filename` option contains `[name]` to give each output file a different name.
We are using multiple entry points (`entry` option) to build every part of the library as a separate output file. The `output.filename` option contains `[name]` to give each output file a different name.
We are using the `libraryTarget` option to generate a UMD ([Universal Module Definition](https://github.com/umdjs/umd)) module that is consumable in CommonsJs, AMD and with script tags. The `library` option defines the namespace. We are using `[name]` in the `library` option to give every entry a different namespace.

View File

@ -1,10 +1,10 @@
This example demonstrates how to build a complex library with webpack. The library consist of multiple parts that are usable on its own and together.
This example demonstrates how to build a complex library with webpack. The library consists of multiple parts that are usable on its own and together.
When using this library with script tags it exports itself to the namespace `MyLibrary` and each part to a property in this namespace (`MyLibrary.alpha` and `MyLibrary.beta`). When consuming the library with CommonsJs or AMD it just export each part.
When using this library with script tags it exports itself to the namespace `MyLibrary` and each part to a property in this namespace (`MyLibrary.alpha` and `MyLibrary.beta`). When consuming the library with CommonsJS or AMD it just exports each part.
We are using multiple entry points (`entry` option) to build every part of the library as separate output file. The `output.filename` option contains `[name]` to give each output file a different name.
We are using multiple entry points (`entry` option) to build every part of the library as a separate output file. The `output.filename` option contains `[name]` to give each output file a different name.
We are using the `libraryTarget` option to generate a UMD ([Universal Module Definition](https://github.com/umdjs/umd)) module that is consumable in CommonsJs, AMD and with script tags. The `library` option defines the namespace. We are using `[name]` in the `library` option to give every entry a different namespace.
We are using the `libraryTarget` option to generate a UMD ([Universal Module Definition](https://github.com/umdjs/umd)) module that is consumable in CommonsJS, AMD and with script tags. The `library` option defines the namespace. We are using `[name]` in the `library` option to give every entry a different namespace.
You can see that webpack automatically wraps your module so that it is consumable in every environment. All you need is this simple config.

View File

@ -1,6 +1,6 @@
This example shows how to use multiple entry points with a commons chunk.
In this example you have two (HTML) pages `pageA` and `pageB`. You want to create individual bundles for each page. In addition to this you want to create a shared bundle that contains all modules used in both pages (assuming there are many/big modules in common). The pages also use Code Splitting to load a less used part of the features on demand.
In this example, you have two (HTML) pages `pageA` and `pageB`. You want to create individual bundles for each page. In addition to this, you want to create a shared bundle that contains all modules used in both pages (assuming there are many/big modules in common). The pages also use Code Splitting to load a less used part of the features on demand.
You can see how to define multiple entry points via the `entry` option.
@ -21,7 +21,7 @@ You can see the output files:
You can also see the info that is printed to console. It shows among others:
- the generated files
- the chunks with file, name and id
- the chunks with file, name, and id
- see lines starting with `chunk`
- the modules that are in the chunks
- the reasons why the modules are included

View File

@ -1,6 +1,6 @@
This example shows how to use multiple entry points with a commons chunk.
In this example you have two (HTML) pages `pageA` and `pageB`. You want to create individual bundles for each page. In addition to this you want to create a shared bundle that contains all modules used in both pages (assuming there are many/big modules in common). The pages also use Code Splitting to load a less used part of the features on demand.
In this example, you have two (HTML) pages `pageA` and `pageB`. You want to create individual bundles for each page. In addition to this, you want to create a shared bundle that contains all the modules used in both pages (assuming there are many/big modules in common). The pages also use Code Splitting to load a less used part of the features on demand.
You can see how to define multiple entry points via the `entry` option.
@ -21,7 +21,7 @@ You can see the output files:
You can also see the info that is printed to console. It shows among others:
- the generated files
- the chunks with file, name and id
- the chunks with file, name, and id
- see lines starting with `chunk`
- the modules that are in the chunks
- the reasons why the modules are included

View File

@ -12,7 +12,7 @@ if (module.hot) {
var check = function check() {
module.hot
.check(true)
.then(function(updatedModules) {
.then(function (updatedModules) {
if (!updatedModules) {
log("warning", "[HMR] Cannot find update. Need to do a full reload!");
log(
@ -33,7 +33,7 @@ if (module.hot) {
log("info", "[HMR] App is up to date.");
}
})
.catch(function(err) {
.catch(function (err) {
var status = module.hot.status();
if (["abort", "fail"].indexOf(status) >= 0) {
log(
@ -48,7 +48,7 @@ if (module.hot) {
});
};
var hotEmitter = require("./emitter");
hotEmitter.on("webpackHotUpdate", function(currentHash) {
hotEmitter.on("webpackHotUpdate", function (currentHash) {
lastHash = currentHash;
if (!upToDate() && module.hot.status() === "idle") {
log("info", "[HMR] Checking for updates on the server...");

View File

@ -2,8 +2,8 @@
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
module.exports = function(updatedModules, renewedModules) {
var unacceptedModules = updatedModules.filter(function(moduleId) {
module.exports = function (updatedModules, renewedModules) {
var unacceptedModules = updatedModules.filter(function (moduleId) {
return renewedModules && renewedModules.indexOf(moduleId) < 0;
});
var log = require("./log");
@ -13,7 +13,7 @@ module.exports = function(updatedModules, renewedModules) {
"warning",
"[HMR] The following modules couldn't be hot updated: (They would need a full reload!)"
);
unacceptedModules.forEach(function(moduleId) {
unacceptedModules.forEach(function (moduleId) {
log("warning", "[HMR] - " + moduleId);
});
}
@ -22,7 +22,7 @@ module.exports = function(updatedModules, renewedModules) {
log("info", "[HMR] Nothing hot updated.");
} else {
log("info", "[HMR] Updated modules:");
renewedModules.forEach(function(moduleId) {
renewedModules.forEach(function (moduleId) {
if (typeof moduleId === "string" && moduleId.indexOf("!") !== -1) {
var parts = moduleId.split("!");
log.groupCollapsed("info", "[HMR] - " + parts.pop());
@ -32,7 +32,7 @@ module.exports = function(updatedModules, renewedModules) {
log("info", "[HMR] - " + moduleId);
}
});
var numberIds = renewedModules.every(function(moduleId) {
var numberIds = renewedModules.every(function (moduleId) {
return typeof moduleId === "number";
});
if (numberIds)

View File

@ -11,14 +11,14 @@ function shouldLog(level) {
}
function logGroup(logFn) {
return function(level, msg) {
return function (level, msg) {
if (shouldLog(level)) {
logFn(msg);
}
};
}
module.exports = function(level, msg) {
module.exports = function (level, msg) {
if (shouldLog(level)) {
if (level === "info") {
console.log(msg);
@ -42,11 +42,11 @@ module.exports.groupCollapsed = logGroup(groupCollapsed);
module.exports.groupEnd = logGroup(groupEnd);
module.exports.setLogLevel = function(level) {
module.exports.setLogLevel = function (level) {
logLevel = level;
};
module.exports.formatError = function(err) {
module.exports.formatError = function (err) {
var message = err.message;
var stack = err.stack;
if (!stack) {

View File

@ -12,7 +12,7 @@ if (module.hot) {
var check = function check() {
module.hot
.check()
.then(function(updatedModules) {
.then(function (updatedModules) {
if (!updatedModules) {
log("warning", "[HMR] Cannot find update. Need to do a full reload!");
log(
@ -27,21 +27,21 @@ if (module.hot) {
ignoreUnaccepted: true,
ignoreDeclined: true,
ignoreErrored: true,
onUnaccepted: function(data) {
onUnaccepted: function (data) {
log(
"warning",
"Ignored an update to unaccepted module " +
data.chain.join(" -> ")
);
},
onDeclined: function(data) {
onDeclined: function (data) {
log(
"warning",
"Ignored an update to declined module " +
data.chain.join(" -> ")
);
},
onErrored: function(data) {
onErrored: function (data) {
log("error", data.error);
log(
"warning",
@ -53,7 +53,7 @@ if (module.hot) {
);
}
})
.then(function(renewedModules) {
.then(function (renewedModules) {
if (!upToDate()) {
check();
}
@ -65,7 +65,7 @@ if (module.hot) {
}
});
})
.catch(function(err) {
.catch(function (err) {
var status = module.hot.status();
if (["abort", "fail"].indexOf(status) >= 0) {
log(
@ -79,7 +79,7 @@ if (module.hot) {
});
};
var hotEmitter = require("./emitter");
hotEmitter.on("webpackHotUpdate", function(currentHash) {
hotEmitter.on("webpackHotUpdate", function (currentHash) {
lastHash = currentHash;
if (!upToDate()) {
var status = module.hot.status();

View File

@ -11,7 +11,7 @@ if (module.hot) {
if (module.hot.status() === "idle") {
module.hot
.check(true)
.then(function(updatedModules) {
.then(function (updatedModules) {
if (!updatedModules) {
if (fromUpdate) log("info", "[HMR] Update applied.");
return;
@ -19,7 +19,7 @@ if (module.hot) {
require("./log-apply-result")(updatedModules, updatedModules);
checkForUpdate(true);
})
.catch(function(err) {
.catch(function (err) {
var status = module.hot.status();
if (["abort", "fail"].indexOf(status) >= 0) {
log("warning", "[HMR] Cannot apply update.");

View File

@ -8,7 +8,7 @@ if (module.hot) {
var checkForUpdate = function checkForUpdate(fromUpdate) {
module.hot
.check()
.then(function(updatedModules) {
.then(function (updatedModules) {
if (!updatedModules) {
if (fromUpdate) log("info", "[HMR] Update applied.");
else log("warning", "[HMR] Cannot find update.");
@ -18,7 +18,7 @@ if (module.hot) {
return module.hot
.apply({
ignoreUnaccepted: true,
onUnaccepted: function(data) {
onUnaccepted: function (data) {
log(
"warning",
"Ignored an update to unaccepted module " +
@ -26,14 +26,14 @@ if (module.hot) {
);
}
})
.then(function(renewedModules) {
.then(function (renewedModules) {
require("./log-apply-result")(updatedModules, renewedModules);
checkForUpdate(true);
return null;
});
})
.catch(function(err) {
.catch(function (err) {
var status = module.hot.status();
if (["abort", "fail"].indexOf(status) >= 0) {
log("warning", "[HMR] Cannot apply update.");
@ -45,7 +45,7 @@ if (module.hot) {
});
};
process.on(__resourceQuery.substr(1) || "SIGUSR2", function() {
process.on(__resourceQuery.substr(1) || "SIGUSR2", function () {
if (module.hot.status() !== "idle") {
log(
"warning",

View File

@ -78,6 +78,12 @@ const REPLACEMENTS = {
req: [RuntimeGlobals.uncaughtErrorHandler],
type: undefined, // type is not known, could be function or undefined
assign: true // is never a pattern
},
__system_context__: {
expr: RuntimeGlobals.systemContext,
req: [RuntimeGlobals.systemContext],
type: "object",
assign: false
}
};
/* eslint-enable camelcase */

View File

@ -126,7 +126,7 @@ Object.defineProperty(ChunkTemplate.prototype, "outputOptions", {
* @this {ChunkTemplate}
* @returns {TODO} output options
*/
function() {
function () {
return this._outputOptions;
},
"ChunkTemplate.outputOptions is deprecated (use Compilation.outputOptions instead)",

View File

@ -103,8 +103,8 @@ class ContextModule extends Module {
// Info from Factory
this.resolveDependencies = resolveDependencies;
/** @type {ContextModuleOptions} */
this.options = ({
/** @type {Omit<ContextModuleOptions, "resolveOptions">} */
this.options = {
resource: resource,
resourceQuery: resourceQuery,
mode: options.mode,
@ -116,7 +116,7 @@ class ContextModule extends Module {
chunkName: options.chunkName,
groupOptions: options.groupOptions,
namespaceObject: options.namespaceObject
});
};
if (options.resolveOptions !== undefined) {
this.resolveOptions = options.resolveOptions;
}

View File

@ -79,8 +79,7 @@ class EvalSourceMapDevToolPlugin {
} else if (m instanceof ConcatenatedModule) {
const concatModule = /** @type {ConcatenatedModule} */ (m);
if (concatModule.rootModule instanceof NormalModule) {
const module =
/** @type {NormalModule} */ (concatModule.rootModule);
const module = /** @type {NormalModule} */ (concatModule.rootModule);
if (!matchModule(module.resource)) {
return source;
}

View File

@ -298,7 +298,7 @@ Object.defineProperty(MainTemplate.prototype, "outputOptions", {
* @this {MainTemplate}
* @returns {TODO} output options
*/
function() {
function () {
return this._outputOptions;
},
"MainTemplate.outputOptions is deprecated (use Compilation.outputOptions instead)",

View File

@ -703,11 +703,7 @@ class Module extends DependenciesBlock {
const sources = this.codeGeneration(sourceContext).sources;
return sourceContext.type
? sources.get(sourceContext.type)
: sources.get(
this.getSourceTypes()
.values()
.next().value
);
: sources.get(this.getSourceTypes().values().next().value);
}
/**
@ -868,7 +864,7 @@ Object.defineProperty(Module.prototype, "errors", {
* @this {Module}
* @returns {WebpackError[]} array
*/
function() {
function () {
if (this._errors === undefined) {
this._errors = [];
}
@ -886,7 +882,7 @@ Object.defineProperty(Module.prototype, "warnings", {
* @this {Module}
* @returns {WebpackError[]} array
*/
function() {
function () {
if (this._warnings === undefined) {
this._warnings = [];
}

View File

@ -20,10 +20,7 @@ class ModuleDependencyError extends WebpackError {
super(err.message);
this.name = "ModuleDependencyError";
this.details = err.stack
.split("\n")
.slice(1)
.join("\n");
this.details = err.stack.split("\n").slice(1).join("\n");
this.module = module;
this.loc = loc;
this.error = err;

View File

@ -19,10 +19,7 @@ module.exports = class ModuleDependencyWarning extends WebpackError {
super(err.message);
this.name = "ModuleDependencyWarning";
this.details = err.stack
.split("\n")
.slice(1)
.join("\n");
this.details = err.stack.split("\n").slice(1).join("\n");
this.module = module;
this.loc = loc;
this.error = err;

View File

@ -88,10 +88,7 @@ ModuleFilenameHelpers.createFilename = (
shortIdentifier = module.readableIdentifier(requestShortener);
identifier = requestShortener.shorten(module.identifier());
moduleId = chunkGraph.getModuleId(module);
absoluteResourcePath = module
.identifier()
.split("!")
.pop();
absoluteResourcePath = module.identifier().split("!").pop();
hash = getHash(identifier);
}
const resource = shortIdentifier.split("!").pop();

View File

@ -140,7 +140,7 @@ Object.defineProperty(ModuleTemplate.prototype, "runtimeTemplate", {
* @this {ModuleTemplate}
* @returns {TODO} output options
*/
function() {
function () {
return this._runtimeTemplate;
},
"ModuleTemplate.runtimeTemplate is deprecated (use Compilation.runtimeTemplate instead)",

View File

@ -42,8 +42,8 @@ const createDefaultHandler = (profile, logger) => {
const alreadyReported = lastStateItem.alreadyReported;
const diff = now - lastStateItem.time;
const stateMsg = alreadyReported
? `${diff}ms (-${alreadyReported}ms) ${lastStateItem.value}`
: `${diff}ms ${lastStateItem.value}`;
? `${diff} ms (-${alreadyReported} ms) ${lastStateItem.value}`
: `${diff} ms ${lastStateItem.value}`;
const d = diff - alreadyReported;
if (d > 10000) {
logger.error(stateMsg);

View File

@ -240,3 +240,8 @@ exports.system = "__webpack_require__.System";
* using of it decreases the compiled bundle size
*/
exports.hasOwnProperty = "__webpack_require__.o";
/**
* the System.register context object
*/
exports.systemContext = "__webpack_require__.y";

View File

@ -19,6 +19,7 @@ const GlobalRuntimeModule = require("./runtime/GlobalRuntimeModule");
const HasOwnPropertyRuntimeModule = require("./runtime/HasOwnPropertyRuntimeModule");
const MakeNamespaceObjectRuntimeModule = require("./runtime/MakeNamespaceObjectRuntimeModule");
const PublicPathRuntimeModule = require("./runtime/PublicPathRuntimeModule");
const SystemContextRuntimeModule = require("./runtime/SystemContextRuntimeModule");
/** @typedef {import("./Chunk")} Chunk */
/** @typedef {import("./Compiler")} Compiler */
@ -158,6 +159,17 @@ class RuntimePlugin {
compilation.addRuntimeModule(chunk, new GlobalRuntimeModule());
return true;
});
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.systemContext)
.tap("RuntimePlugin", chunk => {
if (compilation.outputOptions.library.type === "system") {
compilation.addRuntimeModule(
chunk,
new SystemContextRuntimeModule()
);
}
return true;
});
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.getChunkScriptFilename)
.tap("RuntimePlugin", (chunk, set) => {

View File

@ -136,7 +136,7 @@ const extractBlockModulesMap = compilation => {
* @param {Compilation} compilation the compilation
* @param {Entrypoint[]} inputEntrypoints input groups
* @param {Map<ChunkGroup, ChunkGroupInfo>} chunkGroupInfoMap mapping from chunk group to available modules
* @param {Map<ChunkGroup, ChunkGroupDep[]>} chunkDependencies dependencies for chunk groups
* @param {Map<ChunkGroup, ChunkGroupDep[]>} chunkGroupDependencies dependencies for chunk groups
* @param {Set<DependenciesBlock>} blocksWithNestedBlocks flag for blocks that have nested blocks
* @param {Set<ChunkGroup>} allCreatedChunkGroups filled with all chunk groups that are created here
*/
@ -145,7 +145,7 @@ const visitModules = (
compilation,
inputEntrypoints,
chunkGroupInfoMap,
chunkDependencies,
chunkGroupDependencies,
blocksWithNestedBlocks,
allCreatedChunkGroups
) => {
@ -277,7 +277,7 @@ const visitModules = (
* @returns {void}
*/
const iteratorBlock = b => {
// 1. We create a chunk for this Block
// 1. We create a chunk group with single chunk in it for this Block
// but only once (blockChunkGroups map)
let cgi = blockChunkGroups.get(b);
/** @type {ChunkGroup} */
@ -327,15 +327,16 @@ const visitModules = (
c = cgi.chunkGroup;
}
// 2. We store the Block+Chunk mapping as dependency for the chunk
let deps = chunkDependencies.get(chunkGroup);
if (!deps) chunkDependencies.set(chunkGroup, (deps = []));
// 2. We store the Block + Chunk Group mapping as dependency
// for the chunk group which is set in processQueue
let deps = chunkGroupDependencies.get(chunkGroup);
if (!deps) chunkGroupDependencies.set(chunkGroup, (deps = []));
deps.push({
block: b,
chunkGroup: c
});
// 3. We create/update the chunk group info
// 3. We enqueue the chunk group info creation/updating
let connectList = queueConnect.get(chunkGroupInfo);
if (connectList === undefined) {
connectList = new Set();
@ -788,13 +789,13 @@ const visitModules = (
*
* @param {Compilation} compilation the compilation
* @param {Set<DependenciesBlock>} blocksWithNestedBlocks flag for blocks that have nested blocks
* @param {Map<ChunkGroup, ChunkGroupDep[]>} chunkDependencies dependencies for chunk groups
* @param {Map<ChunkGroup, ChunkGroupDep[]>} chunkGroupDependencies dependencies for chunk groups
* @param {Map<ChunkGroup, ChunkGroupInfo>} chunkGroupInfoMap mapping from chunk group to available modules
*/
const connectChunkGroups = (
compilation,
blocksWithNestedBlocks,
chunkDependencies,
chunkGroupDependencies,
chunkGroupInfoMap
) => {
const { chunkGraph } = compilation;
@ -836,7 +837,7 @@ const connectChunkGroups = (
};
// For all deps, check if chunk groups need to be connected
for (const [chunkGroup, deps] of chunkDependencies) {
for (const [chunkGroup, deps] of chunkGroupDependencies) {
if (deps.length === 0) continue;
// 1. Get info from chunk group info map
@ -896,7 +897,7 @@ const buildChunkGraph = (compilation, inputEntrypoints) => {
// SHARED STATE
/** @type {Map<ChunkGroup, ChunkGroupDep[]>} */
const chunkDependencies = new Map();
const chunkGroupDependencies = new Map();
/** @type {Set<ChunkGroup>} */
const allCreatedChunkGroups = new Set();
@ -915,7 +916,7 @@ const buildChunkGraph = (compilation, inputEntrypoints) => {
compilation,
inputEntrypoints,
chunkGroupInfoMap,
chunkDependencies,
chunkGroupDependencies,
blocksWithNestedBlocks,
allCreatedChunkGroups
);
@ -927,7 +928,7 @@ const buildChunkGraph = (compilation, inputEntrypoints) => {
connectChunkGroups(
compilation,
blocksWithNestedBlocks,
chunkDependencies,
chunkGroupDependencies,
chunkGroupInfoMap
);
logger.timeEnd("connectChunkGroups");

612
lib/cli.js Normal file
View File

@ -0,0 +1,612 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const path = require("path");
const webpackSchema = require("../schemas/WebpackOptions.json");
// TODO add originPath to PathItem for better errors
/**
* @typedef {Object} PathItem
* @property {any} schema the part of the schema
* @property {string} path the path in the config
*/
/**
* @typedef {Object} Problem
* @property {string} type
* @property {string} path
* @property {string} argument
* @property {any=} value
* @property {number=} index
* @property {string=} expected
*/
/**
* @typedef {Object} LocalProblem
* @property {string} type
* @property {string} path
* @property {string=} expected
*/
/**
* @typedef {Object} ArgumentConfig
* @property {string} description
* @property {string} path
* @property {boolean} multiple
* @property {"enum"|"string"|"path"|"number"|"boolean"|"RegExp"|"reset"} type
* @property {any[]=} values
*/
/**
* @typedef {Object} Argument
* @property {string} description
* @property {"string"|"number"|"boolean"} simpleType
* @property {boolean} multiple
* @property {ArgumentConfig[]} configs
*/
/**
* @param {any=} schema a json schema to create arguments for (by default webpack schema is used)
* @returns {Record<string, Argument>} object of arguments
*/
const getArguments = (schema = webpackSchema) => {
/** @type {Record<string, Argument>} */
const flags = {};
const pathToArgumentName = input => {
return input
.replace(/\./g, "-")
.replace(/\[\]/g, "")
.replace(
/(\p{Uppercase_Letter}+|\p{Lowercase_Letter}|\d)(\p{Uppercase_Letter})/gu,
"$1-$2"
)
.replace(/-?[^\p{Uppercase_Letter}\p{Lowercase_Letter}\d]+/gu, "-")
.toLowerCase();
};
const getSchemaPart = path => {
const newPath = path.split("/");
let schemaPart = schema;
for (let i = 1; i < newPath.length; i++) {
const inner = schemaPart[newPath[i]];
if (!inner) {
break;
}
schemaPart = inner;
}
return schemaPart;
};
/**
*
* @param {PathItem[]} path path in the schema
* @returns {string | undefined} description
*/
const getDescription = path => {
for (const { schema } of path) {
if (schema.cli && schema.cli.helper) continue;
if (schema.description) return schema.description;
}
};
/**
*
* @param {any} schemaPart schema
* @returns {Pick<ArgumentConfig, "type"|"values">} partial argument config
*/
const schemaToArgumentConfig = schemaPart => {
if (schemaPart.enum) {
return {
type: "enum",
values: schemaPart.enum
};
}
switch (schemaPart.type) {
case "number":
return {
type: "number"
};
case "string":
return {
type: schemaPart.absolutePath ? "path" : "string"
};
case "boolean":
return {
type: "boolean"
};
}
if (schemaPart.instanceof === "RegExp") {
return {
type: "RegExp"
};
}
return undefined;
};
/**
* @param {PathItem[]} path path in the schema
* @returns {void}
*/
const addResetFlag = path => {
const schemaPath = path[0].path;
const name = pathToArgumentName(`${schemaPath}.reset`);
const description = getDescription(path);
flags[name] = {
configs: [
{
type: "reset",
multiple: false,
description: `Clear all items provided in configuration. ${description}`,
path: schemaPath
}
],
description: undefined,
simpleType: undefined,
multiple: undefined
};
};
/**
* @param {PathItem[]} path full path in schema
* @param {boolean} multiple inside of an array
* @returns {number} number of arguments added
*/
const addFlag = (path, multiple) => {
const argConfigBase = schemaToArgumentConfig(path[0].schema);
if (!argConfigBase) return 0;
const name = pathToArgumentName(path[0].path);
/** @type {ArgumentConfig} */
const argConfig = {
...argConfigBase,
multiple,
description: getDescription(path),
path: path[0].path
};
if (!flags[name]) {
flags[name] = {
configs: [],
description: undefined,
simpleType: undefined,
multiple: undefined
};
}
if (
flags[name].configs.some(
item => JSON.stringify(item) === JSON.stringify(argConfig)
)
) {
return 0;
}
if (
flags[name].configs.some(
item => item.type === argConfig.type && item.multiple !== multiple
)
) {
if (multiple) {
throw new Error(
`Conflicting schema for ${path[0].path} with ${argConfig.type} type (array type must be before single item type)`
);
}
return 0;
}
flags[name].configs.push(argConfig);
return 1;
};
// TODO support `not` and `if/then/else`
// TODO support `const`, but we don't use it on our schema
/**
*
* @param {object} schemaPart the current schema
* @param {string} schemaPath the current path in the schema
* @param {{schema: object, path: string}[]} path all previous visited schemaParts
* @param {string | null} inArray if inside of an array, the path to the array
* @returns {number} added arguments
*/
const traverse = (schemaPart, schemaPath = "", path = [], inArray = null) => {
while (schemaPart.$ref) {
schemaPart = getSchemaPart(schemaPart.$ref);
}
const repetitions = path.filter(({ schema }) => schema === schemaPart);
if (
repetitions.length >= 2 ||
repetitions.some(({ path }) => path === schemaPath)
) {
return 0;
}
if (schemaPart.cli && schemaPart.cli.exclude) return 0;
const fullPath = [{ schema: schemaPart, path: schemaPath }, ...path];
let addedArguments = 0;
addedArguments += addFlag(fullPath, !!inArray);
if (schemaPart.type === "object") {
if (schemaPart.properties) {
for (const property of Object.keys(schemaPart.properties)) {
addedArguments += traverse(
schemaPart.properties[property],
schemaPath ? `${schemaPath}.${property}` : property,
fullPath,
inArray
);
}
}
return addedArguments;
}
if (schemaPart.type === "array") {
if (inArray) {
return 0;
}
if (Array.isArray(schemaPart.items)) {
let i = 0;
for (const item of schemaPart.items) {
addedArguments += traverse(
item,
`${schemaPath}.${i}`,
fullPath,
schemaPath
);
}
return addedArguments;
}
addedArguments += traverse(
schemaPart.items,
`${schemaPath}[]`,
fullPath,
schemaPath
);
if (addedArguments > 0) {
addResetFlag(fullPath);
addedArguments++;
}
return addedArguments;
}
const maybeOf = schemaPart.oneOf || schemaPart.anyOf || schemaPart.allOf;
if (maybeOf) {
const items = maybeOf;
for (let i = 0; i < items.length; i++) {
addedArguments += traverse(items[i], schemaPath, fullPath, inArray);
}
return addedArguments;
}
return addedArguments;
};
traverse(schema);
// Summarize flags
for (const name of Object.keys(flags)) {
const argument = flags[name];
argument.description = argument.configs.reduce((desc, { description }) => {
if (!desc) return description;
if (!description) return desc;
if (desc.includes(description)) return desc;
return `${desc} ${description}`;
}, /** @type {string | undefined} */ (undefined));
argument.simpleType = argument.configs.reduce((t, argConfig) => {
/** @type {"string" | "number" | "boolean"} */
let type = "string";
switch (argConfig.type) {
case "number":
type = "number";
break;
case "reset":
case "boolean":
type = "boolean";
break;
case "enum":
if (argConfig.values.every(v => typeof v === "boolean"))
type = "boolean";
if (argConfig.values.every(v => typeof v === "number"))
type = "number";
break;
}
if (t === undefined) return type;
return t === type ? t : "string";
}, /** @type {"string" | "number" | "boolean" | undefined} */ (undefined));
argument.multiple = argument.configs.some(c => c.multiple);
}
return flags;
};
const cliAddedItems = new WeakMap();
/**
* @param {any} config configuration
* @param {string} schemaPath path in the config
* @param {number | undefined} index index of value when multiple values are provided, otherwise undefined
* @returns {{ problem?: LocalProblem, object?: any, property?: string | number, value?: any }} problem or object with property and value
*/
const getObjectAndProperty = (config, schemaPath, index = 0) => {
if (!schemaPath) return { value: config };
const parts = schemaPath.split(".");
let property = parts.pop();
let current = config;
let i = 0;
for (const part of parts) {
const isArray = part.endsWith("[]");
const name = isArray ? part.slice(0, -2) : part;
let value = current[name];
if (isArray) {
if (value === undefined) {
value = {};
current[name] = [...Array.from({ length: index }), value];
cliAddedItems.set(current[name], index + 1);
} else if (!Array.isArray(value)) {
return {
problem: {
type: "unexpected-non-array-in-path",
path: parts.slice(0, i).join(".")
}
};
} else {
let addedItems = cliAddedItems.get(value) || 0;
while (addedItems <= index) {
value.push(undefined);
addedItems++;
}
cliAddedItems.set(value, addedItems);
const x = value.length - addedItems + index;
if (value[x] === undefined) {
value[x] = {};
} else if (value[x] === null || typeof value[x] !== "object") {
return {
problem: {
type: "unexpected-non-object-in-path",
path: parts.slice(0, i).join(".")
}
};
}
value = value[x];
}
} else {
if (value === undefined) {
value = current[name] = {};
} else if (value === null || typeof value !== "object") {
return {
problem: {
type: "unexpected-non-object-in-path",
path: parts.slice(0, i).join(".")
}
};
}
}
current = value;
i++;
}
let value = current[property];
if (property.endsWith("[]")) {
const name = property.slice(0, -2);
const value = current[name];
if (value === undefined) {
current[name] = [...Array.from({ length: index }), undefined];
cliAddedItems.set(current[name], index + 1);
return { object: current[name], property: index, value: undefined };
} else if (!Array.isArray(value)) {
current[name] = [value, ...Array.from({ length: index }), undefined];
cliAddedItems.set(current[name], index + 1);
return { object: current[name], property: index + 1, value: undefined };
} else {
let addedItems = cliAddedItems.get(value) || 0;
while (addedItems <= index) {
value.push(undefined);
addedItems++;
}
cliAddedItems.set(value, addedItems);
const x = value.length - addedItems + index;
if (value[x] === undefined) {
value[x] = {};
} else if (value[x] === null || typeof value[x] !== "object") {
return {
problem: {
type: "unexpected-non-object-in-path",
path: schemaPath
}
};
}
return {
object: value,
property: x,
value: value[x]
};
}
}
return { object: current, property, value };
};
/**
* @param {any} config configuration
* @param {string} schemaPath path in the config
* @param {any} value parsed value
* @param {number | undefined} index index of value when multiple values are provided, otherwise undefined
* @returns {LocalProblem | null} problem or null for success
*/
const setValue = (config, schemaPath, value, index) => {
const { problem, object, property } = getObjectAndProperty(
config,
schemaPath,
index
);
if (problem) return problem;
object[property] = value;
return null;
};
/**
* @param {ArgumentConfig} argConfig processing instructions
* @param {any} config configuration
* @param {any} value the value
* @param {number | undefined} index the index if multiple values provided
* @returns {LocalProblem | null} a problem if any
*/
const processArgumentConfig = (argConfig, config, value, index) => {
if (index !== undefined && !argConfig.multiple) {
return {
type: "multiple-values-unexpected",
path: argConfig.path
};
}
const parsed = parseValueForArgumentConfig(argConfig, value);
if (parsed === undefined) {
return {
type: "invalid-value",
path: argConfig.path,
expected: getExpectedValue(argConfig)
};
}
const problem = setValue(config, argConfig.path, parsed, index);
if (problem) return problem;
return null;
};
/**
* @param {ArgumentConfig} argConfig processing instructions
* @returns {string | undefined} expected message
*/
const getExpectedValue = argConfig => {
switch (argConfig.type) {
default:
return argConfig.type;
case "boolean":
return "true | false";
case "RegExp":
return "regular expression (example: /ab?c*/)";
case "enum":
return argConfig.values.map(v => `${v}`).join(" | ");
case "reset":
return "true (will reset the previous value to an empty array)";
}
};
/**
* @param {ArgumentConfig} argConfig processing instructions
* @param {any} value the value
* @returns {any | undefined} parsed value
*/
const parseValueForArgumentConfig = (argConfig, value) => {
switch (argConfig.type) {
case "string":
if (typeof value === "string") {
return value;
}
break;
case "path":
if (typeof value === "string") {
return path.resolve(value);
}
break;
case "number":
if (typeof value === "number") return value;
if (typeof value === "string" && /^[+-]?\d*(\.\d*)[eE]\d+$/) {
const n = +value;
if (!isNaN(n)) return value;
}
break;
case "boolean":
if (typeof value === "boolean") return value;
if (value === "true") return true;
if (value === "false") return false;
break;
case "RegExp":
if (value instanceof RegExp) return value;
if (typeof value === "string") {
// cspell:word yugi
const match = /^\/(.*)\/([yugi]*)$/.exec(value);
if (match && !/[^\\]\//.test(match[1]))
return new RegExp(match[1], match[2]);
}
break;
case "enum":
if (argConfig.values.includes(value)) return value;
for (const item of argConfig.values) {
if (`${item}` === value) return item;
}
break;
case "reset":
if (value === true) return [];
break;
}
};
/**
* @param {Record<string, Argument>} args object of arguments
* @param {any} config configuration
* @param {Record<string, string | number | boolean | RegExp>} values object with values
* @returns {Problem[] | null} problems or null for success
*/
const processArguments = (args, config, values) => {
/** @type {Problem[]} */
const problems = [];
for (const key of Object.keys(values)) {
const arg = args[key];
if (!arg) {
problems.push({
type: "unknown-argument",
path: "",
argument: key
});
continue;
}
const processValue = (value, i) => {
const currentProblems = [];
for (const argConfig of arg.configs) {
const problem = processArgumentConfig(argConfig, config, value, i);
if (!problem) {
return;
}
currentProblems.push({
...problem,
argument: key,
value: value,
index: i
});
}
problems.push(...currentProblems);
};
let value = values[key];
if (Array.isArray(value)) {
for (let i = 0; i < value.length; i++) {
processValue(value[i], i);
}
} else {
processValue(value, undefined);
}
}
if (problems.length === 0) return null;
return problems;
};
exports.getArguments = getArguments;
exports.processArguments = processArguments;

View File

@ -117,9 +117,7 @@ const getNormalizedWebpackOptions = config => {
entry: nestedConfig(config.entry, entry => {
if (typeof entry === "function") {
return () =>
Promise.resolve()
.then(entry)
.then(getNormalizedEntryStatic);
Promise.resolve().then(entry).then(getNormalizedEntryStatic);
}
return getNormalizedEntryStatic(entry);
}),

View File

@ -97,8 +97,7 @@ class OverridableModule extends Module {
*/
updateCacheModule(module) {
super.updateCacheModule(module);
this.originalModule =
/** @type {OverridableModule} */ (module).originalModule;
this.originalModule = /** @type {OverridableModule} */ (module).originalModule;
}
/**

View File

@ -18,8 +18,8 @@ class OverridableOriginalModuleFactory extends ModuleFactory {
* @returns {void}
*/
create(data, callback) {
const dep =
/** @type {OverridableOriginalDependency} */ (data.dependencies[0]);
const dep = /** @type {OverridableOriginalDependency} */ (data
.dependencies[0]);
callback(null, {
module: dep.originalModule
});

View File

@ -19,8 +19,8 @@ class RemoteOverrideModuleFactory extends ModuleFactory {
* @returns {void}
*/
create(data, callback) {
const dep =
/** @type {RemoteToOverrideDependency} */ (data.dependencies[0]);
const dep = /** @type {RemoteToOverrideDependency} */ (data
.dependencies[0]);
callback(null, {
module: new RemoteOverrideModule(dep.request, dep.overrides)
});

View File

@ -19,22 +19,6 @@ class AMDRequireItemDependency extends ModuleDependency {
get type() {
return "amd require";
}
serialize(context) {
const { write } = context;
write(this.range);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.range = read();
super.deserialize(context);
}
}
makeSerializable(

View File

@ -20,22 +20,6 @@ class ContextElementDependency extends ModuleDependency {
get type() {
return "context element";
}
serialize(context) {
const { write } = context;
write(this.userRequest);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.userRequest = read();
super.deserialize(context);
}
}
makeSerializable(

View File

@ -103,7 +103,7 @@ HarmonyExportExpressionDependency.Template = class HarmonyExportDependencyTempla
dep.range[0] - 1,
content + "(" + dep.prefix
);
source.replace(dep.range[1], dep.rangeStatement[1] - 1, ");");
source.replace(dep.range[1], dep.rangeStatement[1] - 0.5, ");");
return;
}

View File

@ -22,22 +22,6 @@ class ImportEagerDependency extends ModuleDependency {
get type() {
return "import() eager";
}
serialize(context) {
const { write } = context;
write(this.range);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.range = read();
super.deserialize(context);
}
}
makeSerializable(

View File

@ -23,18 +23,6 @@ class ImportWeakDependency extends ModuleDependency {
get type() {
return "import() weak";
}
serialize(context) {
const { write } = context;
write(this.range);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.range = read();
super.deserialize(context);
}
}
makeSerializable(

View File

@ -19,18 +19,6 @@ class ModuleHotAcceptDependency extends ModuleDependency {
get type() {
return "module.hot.accept";
}
serialize(context) {
const { write } = context;
write(this.range);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.range = read();
super.deserialize(context);
}
}
makeSerializable(

View File

@ -20,18 +20,6 @@ class ModuleHotDeclineDependency extends ModuleDependency {
get type() {
return "module.hot.decline";
}
serialize(context) {
const { write } = context;
write(this.range);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.range = read();
super.deserialize(context);
}
}
makeSerializable(

View File

@ -51,7 +51,6 @@ class ProvidedDependency extends ModuleDependency {
const { write } = context;
write(this.identifier);
write(this.path);
write(this.range);
super.serialize(context);
}
@ -59,7 +58,6 @@ class ProvidedDependency extends ModuleDependency {
const { read } = context;
this.identifier = read();
this.path = read();
this.range = read();
super.deserialize(context);
}
}

View File

@ -18,7 +18,7 @@ const NullDependency = require("./NullDependency");
class PureExpressionDependency extends NullDependency {
/**
* @param {TODO} range the source range
* @param {[number, number]} range the source range
*/
constructor(range) {
super();
@ -75,8 +75,11 @@ PureExpressionDependency.Template = class PureExpressionDependencyTemplate exten
}
}
source.insert(dep.range[0], "/* unused pure expression */ undefined && (");
source.insert(dep.range[1], ")");
source.insert(
dep.range[0],
"(/* unused pure expression or super */ null && ("
);
source.insert(dep.range[1], "))");
}
};

View File

@ -35,22 +35,6 @@ class RequireIncludeDependency extends ModuleDependency {
get type() {
return "require.include";
}
serialize(context) {
const { write } = context;
write(this.range);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.range = read();
super.deserialize(context);
}
}
makeSerializable(

View File

@ -32,22 +32,6 @@ class RequireResolveDependency extends ModuleDependency {
// This doesn't use any export
return Dependency.NO_EXPORTS_REFERENCED;
}
serialize(context) {
const { write } = context;
write(this.range);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.range = read();
super.deserialize(context);
}
}
makeSerializable(

View File

@ -14,7 +14,7 @@ var $hmrDownloadManifest$ = undefined;
var $hmrDownloadUpdateHandlers$ = undefined;
var __webpack_require__ = undefined;
module.exports = function() {
module.exports = function () {
var currentHash = $getFullHash$();
var currentModuleData = {};
var installedModules = $moduleCache$;
@ -36,11 +36,11 @@ module.exports = function() {
$hmrModuleData$ = currentModuleData;
$getFullHash$ = function() {
$getFullHash$ = function () {
return currentHash;
};
$interceptModuleExecution$.push(function(options) {
$interceptModuleExecution$.push(function (options) {
var module = options.module;
var require = createRequire(options.require, options.id);
module.hot = createModuleHotObject(options.id, module);
@ -55,7 +55,7 @@ module.exports = function() {
function createRequire(require, moduleId) {
var me = installedModules[moduleId];
if (!me) return require;
var fn = function(request) {
var fn = function (request) {
if (me.hot.active) {
if (installedModules[request]) {
var parents = installedModules[request].parents;
@ -80,14 +80,14 @@ module.exports = function() {
}
return require(request);
};
var createPropertyDescriptor = function(name) {
var createPropertyDescriptor = function (name) {
return {
configurable: true,
enumerable: true,
get: function() {
get: function () {
return require[name];
},
set: function(value) {
set: function (value) {
require[name] = value;
}
};
@ -97,7 +97,7 @@ module.exports = function() {
Object.defineProperty(fn, name, createPropertyDescriptor(name));
}
}
fn.e = function(chunkId) {
fn.e = function (chunkId) {
return trackBlockingPromise(require.e(chunkId));
};
return fn;
@ -112,7 +112,7 @@ module.exports = function() {
_selfDeclined: false,
_disposeHandlers: [],
_main: currentChildModule !== moduleId,
_requireSelf: function() {
_requireSelf: function () {
currentParents = me.parents.slice();
currentChildModule = moduleId;
__webpack_require__(moduleId);
@ -120,28 +120,28 @@ module.exports = function() {
// Module API
active: true,
accept: function(dep, callback) {
accept: function (dep, callback) {
if (dep === undefined) hot._selfAccepted = true;
else if (typeof dep === "function") hot._selfAccepted = dep;
else if (typeof dep === "object" && dep !== null)
for (var i = 0; i < dep.length; i++)
hot._acceptedDependencies[dep[i]] = callback || function() {};
else hot._acceptedDependencies[dep] = callback || function() {};
hot._acceptedDependencies[dep[i]] = callback || function () {};
else hot._acceptedDependencies[dep] = callback || function () {};
},
decline: function(dep) {
decline: function (dep) {
if (dep === undefined) hot._selfDeclined = true;
else if (typeof dep === "object" && dep !== null)
for (var i = 0; i < dep.length; i++)
hot._declinedDependencies[dep[i]] = true;
else hot._declinedDependencies[dep] = true;
},
dispose: function(callback) {
dispose: function (callback) {
hot._disposeHandlers.push(callback);
},
addDisposeHandler: function(callback) {
addDisposeHandler: function (callback) {
hot._disposeHandlers.push(callback);
},
removeDisposeHandler: function(callback) {
removeDisposeHandler: function (callback) {
var idx = hot._disposeHandlers.indexOf(callback);
if (idx >= 0) hot._disposeHandlers.splice(idx, 1);
},
@ -149,14 +149,14 @@ module.exports = function() {
// Management API
check: hotCheck,
apply: hotApply,
status: function(l) {
status: function (l) {
if (!l) return currentStatus;
registeredStatusHandlers.push(l);
},
addStatusHandler: function(l) {
addStatusHandler: function (l) {
registeredStatusHandlers.push(l);
},
removeStatusHandler: function(l) {
removeStatusHandler: function (l) {
var idx = registeredStatusHandlers.indexOf(l);
if (idx >= 0) registeredStatusHandlers.splice(idx, 1);
},
@ -179,7 +179,7 @@ module.exports = function() {
case "ready":
setStatus("prepare");
blockingPromises.push(promise);
waitForBlockingPromises(function() {
waitForBlockingPromises(function () {
setStatus("ready");
});
return promise;
@ -195,7 +195,7 @@ module.exports = function() {
if (blockingPromises.length === 0) return fn();
var blocker = blockingPromises;
blockingPromises = [];
return Promise.all(blocker).then(function() {
return Promise.all(blocker).then(function () {
return waitForBlockingPromises(fn);
});
}
@ -205,7 +205,7 @@ module.exports = function() {
throw new Error("check() is only allowed in idle status");
}
setStatus("check");
return $hmrDownloadManifest$().then(function(update) {
return $hmrDownloadManifest$().then(function (update) {
if (!update) {
setStatus("idle");
return null;
@ -219,7 +219,7 @@ module.exports = function() {
currentUpdateApplyHandlers = [];
return Promise.all(
Object.keys($hmrDownloadUpdateHandlers$).reduce(function(
Object.keys($hmrDownloadUpdateHandlers$).reduce(function (
promises,
key
) {
@ -234,8 +234,8 @@ module.exports = function() {
return promises;
},
[])
).then(function() {
return waitForBlockingPromises(function() {
).then(function () {
return waitForBlockingPromises(function () {
if (applyOnUpdate) {
return internalApply(applyOnUpdate);
} else {
@ -250,7 +250,7 @@ module.exports = function() {
function hotApply(options) {
if (currentStatus !== "ready") {
return Promise.resolve().then(function() {
return Promise.resolve().then(function () {
throw new Error("apply() is only allowed in ready status");
});
}
@ -260,19 +260,19 @@ module.exports = function() {
function internalApply(options) {
options = options || {};
var results = currentUpdateApplyHandlers.map(function(handler) {
var results = currentUpdateApplyHandlers.map(function (handler) {
return handler(options);
});
var errors = results
.map(function(r) {
.map(function (r) {
return r.error;
})
.filter(Boolean);
if (errors.length > 0) {
setStatus("abort");
return Promise.resolve().then(function() {
return Promise.resolve().then(function () {
throw errors[0];
});
}
@ -280,7 +280,7 @@ module.exports = function() {
// Now in "dispose" phase
setStatus("dispose");
results.forEach(function(result) {
results.forEach(function (result) {
if (result.dispose) result.dispose();
});
@ -290,12 +290,12 @@ module.exports = function() {
currentHash = currentUpdateNewHash;
var error;
var reportError = function(err) {
var reportError = function (err) {
if (!error) error = err;
};
var outdatedModules = [];
results.forEach(function(result) {
results.forEach(function (result) {
if (result.apply) {
var modules = result.apply(reportError);
if (modules) {
@ -309,7 +309,7 @@ module.exports = function() {
// handle errors in accept handlers and self accepted module load
if (error) {
setStatus("fail");
return Promise.resolve().then(function() {
return Promise.resolve().then(function () {
throw error;
});
}

View File

@ -13,12 +13,12 @@ var $moduleFactories$ = undefined;
var $hmrModuleData$ = undefined;
var __webpack_require__ = undefined;
module.exports = function() {
module.exports = function () {
function getAffectedModuleEffects(updateModuleId) {
var outdatedModules = [updateModuleId];
var outdatedDependencies = {};
var queue = outdatedModules.map(function(id) {
var queue = outdatedModules.map(function (id) {
return {
chain: [id],
id: id
@ -211,7 +211,7 @@ module.exports = function() {
var moduleOutdatedDependencies;
return {
dispose: function() {
dispose: function () {
// $dispose$
var idx;
@ -271,7 +271,7 @@ module.exports = function() {
}
}
},
apply: function(reportError) {
apply: function (reportError) {
// insert new code
for (var updateModuleId in appliedUpdate) {
if (

View File

@ -31,6 +31,7 @@ const exportPlugins = (obj, mappings) => {
};
exportPlugins(module.exports, {
cli: () => require("./cli"),
AutomaticPrefetchPlugin: () => require("./AutomaticPrefetchPlugin"),
BannerPlugin: () => require("./BannerPlugin"),
Cache: () => require("./Cache"),

View File

@ -152,8 +152,7 @@ class JavascriptGenerator extends Generator {
* @returns {void}
*/
sourceDependency(module, dependency, initFragments, source, generateContext) {
const constructor =
/** @type {new (...args: any[]) => Dependency} */ (dependency.constructor);
const constructor = /** @type {new (...args: any[]) => Dependency} */ (dependency.constructor);
const template = generateContext.dependencyTemplates.get(constructor);
if (!template) {
throw new Error(

View File

@ -18,6 +18,8 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
/** @typedef {import("estree").BinaryExpression} BinaryExpressionNode */
/** @typedef {import("estree").BlockStatement} BlockStatementNode */
/** @typedef {import("estree").CallExpression} CallExpressionNode */
/** @typedef {import("estree").ClassDeclaration} ClassDeclarationNode */
/** @typedef {import("estree").ClassExpression} ClassExpressionNode */
/** @typedef {import("estree").Comment} CommentNode */
/** @typedef {import("estree").ConditionalExpression} ConditionalExpressionNode */
/** @typedef {import("estree").Declaration} DeclarationNode */
@ -28,6 +30,7 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
/** @typedef {import("estree").Literal} LiteralNode */
/** @typedef {import("estree").LogicalExpression} LogicalExpressionNode */
/** @typedef {import("estree").MemberExpression} MemberExpressionNode */
/** @typedef {import("estree").MethodDefinition} MethodDefinitionNode */
/** @typedef {import("estree").ModuleDeclaration} ModuleDeclarationNode */
/** @typedef {import("estree").Node} AnyNode */
/** @typedef {import("estree").Program} ProgramNode */
@ -156,6 +159,10 @@ class JavascriptParser extends Parser {
statement: new SyncBailHook(["statement"]),
/** @type {SyncBailHook<[IfStatementNode], boolean | void>} */
statementIf: new SyncBailHook(["statement"]),
/** @type {SyncBailHook<[ExpressionNode, ClassExpressionNode | ClassDeclarationNode], boolean | void>} */
classExtendsExpression: new SyncBailHook(["expression", "statement"]),
/** @type {SyncBailHook<[MethodDefinitionNode, ClassExpressionNode | ClassDeclarationNode], boolean | void>} */
classBodyElement: new SyncBailHook(["element", "statement"]),
/** @type {HookMap<SyncBailHook<[LabeledStatementNode], boolean | void>>} */
label: new HookMap(() => new SyncBailHook(["statement"])),
/** @type {SyncBailHook<[StatementNode, ImportSource], boolean | void>} */
@ -1137,17 +1144,28 @@ class JavascriptParser extends Parser {
}
}
/**
* @param {ClassExpressionNode | ClassDeclarationNode} classy a class node
* @returns {void}
*/
walkClass(classy) {
if (classy.superClass) this.walkExpression(classy.superClass);
if (classy.superClass) {
if (!this.hooks.classExtendsExpression.call(classy.superClass, classy)) {
this.walkExpression(classy.superClass);
}
}
if (classy.body && classy.body.type === "ClassBody") {
const wasTopLevel = this.scope.topLevelScope;
this.scope.topLevelScope = false;
for (const methodDefinition of classy.body.body) {
if (methodDefinition.type === "MethodDefinition") {
this.walkMethodDefinition(methodDefinition);
for (const classElement of classy.body.body) {
if (!this.hooks.classBodyElement.call(classElement, classy)) {
if (classElement.type === "MethodDefinition") {
this.scope.topLevelScope = false;
this.walkMethodDefinition(classElement);
this.scope.topLevelScope = wasTopLevel;
}
// TODO add support for ClassProperty here once acorn supports it
}
}
this.scope.topLevelScope = wasTopLevel;
}
}

View File

@ -181,7 +181,7 @@ class SystemLibraryPlugin extends AbstractLibraryPlugin {
return new ConcatSource(
Template.asString([
`System.register(${name}${systemDependencies}, function(${dynamicExport}) {`,
`System.register(${name}${systemDependencies}, function(${dynamicExport}, __system_context__) {`,
Template.indent([
externalVarDeclarations,
Template.asString(externalVarInitialization),

View File

@ -158,7 +158,7 @@ module.exports = ({ level = "info", debug = false, console }) => {
case LogType.time: {
if (!debug && loglevel > LogLevel.log) return;
const ms = args[1] * 1000 + args[2] / 1000000;
const msg = `[${name}] ${args[0]}: ${ms}ms`;
const msg = `[${name}] ${args[0]}: ${ms} ms`;
if (typeof console.logTime === "function") {
console.logTime(msg);
} else {

View File

@ -907,9 +907,8 @@ class ConcatenatedModule extends Module {
})
.map(connection => ({
connection,
sourceOrder:
/** @type {HarmonyImportDependency} */ (connection.dependency)
.sourceOrder
sourceOrder: /** @type {HarmonyImportDependency} */ (connection.dependency)
.sourceOrder
}));
references.sort(
concatComparators(bySourceOrder, keepOriginalOrder(references))
@ -1866,7 +1865,7 @@ class HarmonyExportExpressionDependencyConcatenatedTemplate extends DependencyTe
dep.range[0] - 1,
content + "(" + dep.prefix
);
source.replace(dep.range[1], dep.rangeStatement[1] - 1, ");");
source.replace(dep.range[1], dep.rangeStatement[1] - 0.5, ");");
return;
}

View File

@ -11,6 +11,10 @@ const {
const PureExpressionDependency = require("../dependencies/PureExpressionDependency");
const InnerGraph = require("./InnerGraph");
/** @typedef {import("estree").ClassDeclaration} ClassDeclarationNode */
/** @typedef {import("estree").ClassExpression} ClassExpressionNode */
/** @typedef {import("estree").Node} Node */
/** @typedef {import("estree").VariableDeclarator} VariableDeclaratorNode */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../dependencies/HarmonyImportSpecifierDependency")} HarmonyImportSpecifierDependency */
@ -34,6 +38,7 @@ const isPure = (expr, parser, commentsStartPos) => {
parser.getTagData(expr.name, harmonySpecifierTag)
);
case "ClassDeclaration":
case "ClassExpression":
if (expr.body.type !== "ClassBody") return false;
if (expr.superClass && !isPure(expr.superClass, parser, expr.range[0])) {
@ -50,6 +55,7 @@ const isPure = (expr, parser, commentsStartPos) => {
return true;
});
case "FunctionDeclaration":
case "FunctionExpression":
case "ArrowFunctionExpression":
case "Literal":
@ -107,12 +113,30 @@ class InnerGraphPlugin {
PureExpressionDependency,
new PureExpressionDependency.Template()
);
/**
* @param {JavascriptParser} parser the parser
* @param {Object} parserOptions options
* @returns {void}
*/
const handler = (parser, parserOptions) => {
const onUsageSuper = sup => {
InnerGraph.onUsage(parser.state, usedByExports => {
switch (usedByExports) {
case undefined:
case true:
return;
default: {
const dep = new PureExpressionDependency(sup.range);
dep.loc = sup.loc;
dep.usedByExports = usedByExports;
parser.state.module.addDependency(dep);
break;
}
}
});
};
parser.hooks.program.tap("InnerGraphPlugin", () => {
InnerGraph.enable(parser.state);
});
@ -124,8 +148,31 @@ class InnerGraphPlugin {
InnerGraph.inferDependencyUsage(parser.state);
logger.timeAggregate("infer dependency usage");
});
/** @type {WeakMap<{}, TopLevelSymbol>} */
// During prewalking the following datastructures are filled with
// nodes that have a TopLevelSymbol assigned and
// variables are tagged with the assigned TopLevelSymbol
// We differ 3 types of nodes:
// 1. full statements (export default, function declaration)
// 2. classes (class declaration, class expression)
// 3. variable declarators (const x = ...)
/** @type {WeakMap<Node, TopLevelSymbol>} */
const statementWithTopLevelSymbol = new WeakMap();
/** @type {WeakMap<Node, Node>} */
const statementPurePart = new WeakMap();
/** @type {WeakMap<ClassExpressionNode | ClassDeclarationNode, TopLevelSymbol>} */
const classWithTopLevelSymbol = new WeakMap();
/** @type {WeakMap<VariableDeclaratorNode, TopLevelSymbol>} */
const declWithTopLevelSymbol = new WeakMap();
/** @type {WeakSet<VariableDeclaratorNode>} */
const pureDeclarators = new WeakSet();
// The following hooks are used during prewalking:
parser.hooks.preStatement.tap("InnerGraphPlugin", statement => {
if (!InnerGraph.isEnabled(parser.state)) return;
@ -138,6 +185,7 @@ class InnerGraphPlugin {
}
}
});
parser.hooks.blockPreStatement.tap("InnerGraphPlugin", statement => {
if (!InnerGraph.isEnabled(parser.state)) return;
@ -145,27 +193,32 @@ class InnerGraphPlugin {
if (statement.type === "ClassDeclaration") {
const name = statement.id ? statement.id.name : "*default*";
const fn = InnerGraph.tagTopLevelSymbol(parser, name);
statementWithTopLevelSymbol.set(statement, fn);
classWithTopLevelSymbol.set(statement, fn);
return true;
}
if (statement.type === "ExportDefaultDeclaration") {
const name = "*default*";
const fn = InnerGraph.tagTopLevelSymbol(parser, name);
const decl = statement.declaration;
if (
decl.type === "FunctionExpression" ||
decl.type === "ArrowFunctionExpression" ||
decl.type === "ClassExpression" ||
decl.type === "Identifier"
decl.type === "ClassDeclaration"
) {
const name = "*default*";
const fn = InnerGraph.tagTopLevelSymbol(parser, name);
classWithTopLevelSymbol.set(decl, fn);
} else if (isPure(decl, parser, decl.range[1])) {
statementWithTopLevelSymbol.set(statement, fn);
if (
!decl.type.endsWith("FunctionExpression") &&
!decl.type.endsWith("Declaration") &&
decl.type !== "Literal"
) {
statementPurePart.set(statement, decl);
}
}
}
}
});
/** @type {WeakMap<{}, TopLevelSymbol>} */
const declWithTopLevelSymbol = new WeakMap();
const pureDeclarators = new WeakSet();
parser.hooks.preDeclarator.tap(
"InnerGraphPlugin",
(decl, statement) => {
@ -175,67 +228,157 @@ class InnerGraphPlugin {
decl.init &&
decl.id.type === "Identifier"
) {
if (
decl.init.type === "FunctionExpression" ||
decl.init.type === "ArrowFunctionExpression" ||
decl.init.type === "ClassExpression"
) {
const name = decl.id.name;
const name = decl.id.name;
if (decl.init.type === "ClassExpression") {
const fn = InnerGraph.tagTopLevelSymbol(parser, name);
classWithTopLevelSymbol.set(decl.init, fn);
} else if (isPure(decl.init, parser, decl.id.range[1])) {
const fn = InnerGraph.tagTopLevelSymbol(parser, name);
declWithTopLevelSymbol.set(decl, fn);
return true;
}
if (isPure(decl.init, parser, decl.id.range[1])) {
const name = decl.id.name;
const fn = InnerGraph.tagTopLevelSymbol(parser, name);
declWithTopLevelSymbol.set(decl, fn);
pureDeclarators.add(decl);
if (
!decl.init.type.endsWith("FunctionExpression") &&
decl.init.type !== "Literal"
) {
pureDeclarators.add(decl);
}
return true;
}
}
}
);
// During real walking we set the TopLevelSymbol state to the assigned
// TopLevelSymbol by using the fill datastructures.
// In addition to tracking TopLevelSymbols, we sometimes need to
// add a PureExpressionDependency. This is needed to skip execution
// of pure expressions, even when they are not dropped due to
// minimizing. Otherwise symbols used there might not exist anymore
// as they are removed as unused by this optimization
// When we find a reference to a TopLevelSymbol, we register a
// TopLevelSymbol dependency from TopLevelSymbol in state to the
// referenced TopLevelSymbol. This way we get a graph of all
// TopLevelSymbols.
// The following hooks are called during walking:
parser.hooks.statement.tap("InnerGraphPlugin", statement => {
if (!InnerGraph.isEnabled(parser.state)) return;
if (parser.scope.topLevelScope === true) {
InnerGraph.setTopLevelSymbol(parser.state, undefined);
const fn = statementWithTopLevelSymbol.get(statement);
if (fn) {
InnerGraph.setTopLevelSymbol(parser.state, fn);
const purePart = statementPurePart.get(statement);
if (purePart) {
InnerGraph.onUsage(parser.state, usedByExports => {
switch (usedByExports) {
case undefined:
case true:
return;
default: {
const dep = new PureExpressionDependency(
purePart.range
);
dep.loc = statement.loc;
dep.usedByExports = usedByExports;
parser.state.module.addDependency(dep);
break;
}
}
});
}
}
}
});
parser.hooks.classExtendsExpression.tap(
"InnerGraphPlugin",
(expr, statement) => {
if (!InnerGraph.isEnabled(parser.state)) return;
if (parser.scope.topLevelScope === true) {
const fn = classWithTopLevelSymbol.get(statement);
if (
fn &&
isPure(
expr,
parser,
statement.id ? statement.id.range[1] : statement.range[0]
)
) {
InnerGraph.setTopLevelSymbol(parser.state, fn);
onUsageSuper(expr);
}
}
}
);
parser.hooks.classBodyElement.tap(
"InnerGraphPlugin",
(element, statement) => {
if (!InnerGraph.isEnabled(parser.state)) return;
if (parser.scope.topLevelScope === true) {
const fn = classWithTopLevelSymbol.get(statement);
if (fn) {
if (element.type === "MethodDefinition") {
InnerGraph.setTopLevelSymbol(parser.state, fn);
} else if (
element.type === "ClassProperty" &&
!element.static
) {
// TODO add test case once acorn supports it
// Currently this is not parsable
InnerGraph.setTopLevelSymbol(parser.state, fn);
} else {
InnerGraph.setTopLevelSymbol(parser.state, undefined);
}
}
}
}
);
parser.hooks.declarator.tap("InnerGraphPlugin", (decl, statement) => {
if (!InnerGraph.isEnabled(parser.state)) return;
const fn = declWithTopLevelSymbol.get(decl);
if (fn) {
InnerGraph.setTopLevelSymbol(parser.state, fn);
if (pureDeclarators.has(decl)) {
InnerGraph.onUsage(parser.state, usedByExports => {
switch (usedByExports) {
case undefined:
case true:
return;
default: {
const dep = new PureExpressionDependency(decl.init.range);
dep.loc = decl.loc;
dep.usedByExports = usedByExports;
parser.state.module.addDependency(dep);
break;
}
if (decl.init.type === "ClassExpression") {
if (decl.init.superClass) {
onUsageSuper(decl.init.superClass);
}
});
} else {
InnerGraph.onUsage(parser.state, usedByExports => {
switch (usedByExports) {
case undefined:
case true:
return;
default: {
const dep = new PureExpressionDependency(
decl.init.range
);
dep.loc = decl.loc;
dep.usedByExports = usedByExports;
parser.state.module.addDependency(dep);
break;
}
}
});
}
}
parser.walkExpression(decl.init);
InnerGraph.setTopLevelSymbol(parser.state, undefined);
return true;
}
});
parser.hooks.expression
.for(topLevelSymbolTag)
.tap("InnerGraphPlugin", () => {
const topLevelSymbol =
/** @type {TopLevelSymbol} */ (parser.currentTagData);
const topLevelSymbol = /** @type {TopLevelSymbol} */ (parser.currentTagData);
const currentTopLevelSymbol = InnerGraph.getTopLevelSymbol(
parser.state
);

View File

@ -185,15 +185,16 @@ class ModuleConcatenationPlugin {
);
const importingModuleTypes = new Map(
Array.from(importingModules).map(
m => /** @type {[Module, Set<string>]} */ ([
m,
new Set(
nonHarmonyConnections
.filter(c => c.originModule === m)
.map(c => c.dependency.type)
.sort()
)
])
m =>
/** @type {[Module, Set<string>]} */ ([
m,
new Set(
nonHarmonyConnections
.filter(c => c.originModule === m)
.map(c => c.dependency.type)
.sort()
)
])
)
);
const names = Array.from(importingModules)

View File

@ -1213,8 +1213,9 @@ module.exports = class SplitChunksPlugin {
minSizeValue > maxSizeValue
) {
const keys = chunkConfig && chunkConfig.keys;
const warningKey = `${keys &&
keys.join()} ${minSizeValue} ${maxSizeValue}`;
const warningKey = `${
keys && keys.join()
} ${minSizeValue} ${maxSizeValue}`;
if (!incorrectMinMaxSizeSet.has(warningKey)) {
incorrectMinMaxSizeSet.add(warningKey);
compilation.warnings.push(

View File

@ -0,0 +1,25 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
*/
"use strict";
const RuntimeGlobals = require("../RuntimeGlobals");
const RuntimeModule = require("../RuntimeModule");
/** @typedef {import("../Compilation")} Compilation */
class SystemContextRuntimeModule extends RuntimeModule {
constructor() {
super("__system_context__");
}
/**
* @returns {string} runtime code
*/
generate() {
return `${RuntimeGlobals.systemContext} = __system_context__;`;
}
}
module.exports = SystemContextRuntimeModule;

View File

@ -435,8 +435,9 @@ const SIMPLE_EXTRACTORS = {
}
let message = undefined;
if (entry.type === LogType.time) {
message = `${entry.args[0]}: ${entry.args[1] * 1000 +
entry.args[2] / 1000000}ms`;
message = `${entry.args[0]}: ${
entry.args[1] * 1000 + entry.args[2] / 1000000
} ms`;
} else if (entry.args && entry.args.length > 0) {
message = util.format(entry.args[0], ...entry.args.slice(1));
}
@ -500,22 +501,22 @@ const SIMPLE_EXTRACTORS = {
compilationAuxiliaryFileToChunks.get(asset.name) || [];
object.chunkNames = uniqueOrderedArray(
chunks,
c => ((c.name ? [c.name] : [])),
c => (c.name ? [c.name] : []),
compareIds
);
object.chunkIdHints = uniqueOrderedArray(
chunks,
c => (Array.from(c.idNameHints)),
c => Array.from(c.idNameHints),
compareIds
);
object.auxiliaryChunkNames = uniqueOrderedArray(
auxiliaryChunks,
c => ((c.name ? [c.name] : [])),
c => (c.name ? [c.name] : []),
compareIds
);
object.auxiliaryChunkIdHints = uniqueOrderedArray(
auxiliaryChunks,
c => (Array.from(c.idNameHints)),
c => Array.from(c.idNameHints),
compareIds
);
object.emitted = compilation.emittedAssets.has(asset.name);
@ -986,25 +987,25 @@ const FILTER = {
}
}
},
"compilation.modules": ({
"compilation.modules": {
excludeModules: EXCLUDE_MODULES_FILTER("module"),
"!orphanModules": (module, { compilation: { chunkGraph } }) => {
if (chunkGraph.getNumberOfModuleChunks(module) === 0) return false;
},
...BASE_MODULES_FILTER
}),
"module.modules": ({
},
"module.modules": {
excludeModules: EXCLUDE_MODULES_FILTER("nested"),
...BASE_MODULES_FILTER
}),
"chunk.modules": ({
},
"chunk.modules": {
excludeModules: EXCLUDE_MODULES_FILTER("chunk"),
...BASE_MODULES_FILTER
}),
"chunk.rootModules": ({
},
"chunk.rootModules": {
excludeModules: EXCLUDE_MODULES_FILTER("root-of-chunk"),
...BASE_MODULES_FILTER
})
}
};
/** @type {Record<string, (module: Module, context: UsualContext, options: UsualOptions, idx: number, i: number) => boolean | undefined>} */

View File

@ -152,12 +152,12 @@ const DEFAULTS = {
warnings: NORMAL_ON,
publicPath: OFF_FOR_TO_STRING,
logging: ({ all }, { forToString }) =>
(forToString && all !== false ? "info" : false),
forToString && all !== false ? "info" : false,
loggingDebug: () => [],
loggingTrace: OFF_FOR_TO_STRING,
excludeModules: () => [],
excludeAssets: () => [],
maxModules: (o, { forToString }) => ((forToString ? 15 : Infinity)),
maxModules: (o, { forToString }) => (forToString ? 15 : Infinity),
modulesSort: () => "depth",
chunkModulesSort: () => "name",
chunkRootModulesSort: () => "name",

View File

@ -27,7 +27,7 @@
* @property {(id: string, direction?: "parent"|"child"|"sibling") => string} formatChunkId
* @property {(size: number) => string} formatSize
* @property {(flag: string) => string} formatFlag
* @property {(time: number) => string} formatTime
* @property {(time: number, boldQuantity?: boolean) => string} formatTime
* @property {number} maxModuleId
* @property {string} chunkGroupKind
*/
@ -43,11 +43,7 @@ const printSizes = (sizes, { formatSize }) => {
}
};
const mapLines = (str, fn) =>
str
.split("\n")
.map(fn)
.join("\n");
const mapLines = (str, fn) => str.split("\n").map(fn).join("\n");
/**
* @param {number} n a number
@ -67,7 +63,8 @@ const SIMPLE_PRINTERS = {
type === "compilation.version"
? `Version: webpack ${bold(version)}`
: undefined,
"compilation.time": (time, { bold }) => `Time: ${bold(time)}ms`,
"compilation.time": (time, { formatTime }) =>
`Time: ${formatTime(time, true)}`,
"compilation.builtAt": (builtAt, { bold }) => {
const d = new Date(builtAt);
const x = twoDigit;
@ -84,10 +81,10 @@ const SIMPLE_PRINTERS = {
"compilation.entrypoints": (entrypoints, context, printer) =>
Array.isArray(entrypoints)
? undefined
: printer.print(context.type, Object.values(entrypoints), ({
: printer.print(context.type, Object.values(entrypoints), {
...context,
chunkGroupKind: "Entrypoint"
})),
}),
"compilation.namedChunkGroups": (namedChunkGroups, context, printer) => {
if (!Array.isArray(namedChunkGroups)) {
const {
@ -100,10 +97,10 @@ const SIMPLE_PRINTERS = {
!Object.prototype.hasOwnProperty.call(entrypoints, group.name)
);
}
return printer.print(context.type, chunkGroups, ({
return printer.print(context.type, chunkGroups, {
...context,
chunkGroupKind: "Chunk Group"
}));
});
}
},
"compilation.assetsByChunkName": () => "",
@ -152,7 +149,7 @@ const SIMPLE_PRINTERS = {
"asset.size": (
size,
{ asset: { isOverSizeLimit }, yellow, green, formatSize }
) => ((isOverSizeLimit ? yellow(formatSize(size)) : formatSize(size))),
) => (isOverSizeLimit ? yellow(formatSize(size)) : formatSize(size)),
"asset.emitted": (emitted, { green, formatFlag }) =>
emitted ? green(formatFlag("emitted")) : undefined,
"asset.comparedForEmit": (comparedForEmit, { yellow, formatFlag }) =>
@ -167,7 +164,7 @@ const SIMPLE_PRINTERS = {
"asset.info.hotModuleReplacement": (
hotModuleReplacement,
{ green, formatFlag }
) => ((hotModuleReplacement ? green(formatFlag("hmr")) : undefined)),
) => (hotModuleReplacement ? green(formatFlag("hmr")) : undefined),
assetChunk: (id, { formatChunkId }) => formatChunkId(id),
@ -350,8 +347,7 @@ const SIMPLE_PRINTERS = {
rendered ? green(formatFlag("rendered")) : undefined,
"chunk.recorded": (recorded, { formatFlag, green }) =>
recorded ? green(formatFlag("recorded")) : undefined,
"chunk.reason": (reason, { yellow }) =>
(reason ? yellow(reason) : undefined),
"chunk.reason": (reason, { yellow }) => (reason ? yellow(reason) : undefined),
"chunk.rootModules": (modules, context) => {
let maxModuleId = 0;
for (const module of modules) {
@ -462,7 +458,7 @@ const SIMPLE_PRINTERS = {
loggingGroup: loggingGroup =>
loggingGroup.entries.length === 0 ? "" : undefined,
"loggingGroup.debug": (flag, { red }) => ((flag ? red("DEBUG") : undefined)),
"loggingGroup.debug": (flag, { red }) => (flag ? red("DEBUG") : undefined),
"loggingGroup.name": (name, { bold }) => bold(`LOG from ${name}`),
"loggingGroup.separator!": () => "\n",
"loggingGroup.filteredEntries": filteredEntries =>
@ -830,7 +826,7 @@ const SIMPLE_ELEMENT_JOINERS = {
if (maxModuleId >= 10) prefix += " ";
}
return (
(prefix +
prefix +
joinExplicitNewLine(
items.filter(item => {
switch (item.element) {
@ -846,13 +842,13 @@ const SIMPLE_ELEMENT_JOINERS = {
return true;
}),
indenter
))
)
);
},
chunk: items => {
let hasEntry = false;
return (
("chunk " +
"chunk " +
joinExplicitNewLine(
items.filter(item => {
switch (item.element) {
@ -866,7 +862,7 @@ const SIMPLE_ELEMENT_JOINERS = {
return true;
}),
" "
))
)
);
},
"chunk.childrenByOrder[]": items => `(${joinOneLine(items)})`,
@ -886,8 +882,8 @@ const SIMPLE_ELEMENT_JOINERS = {
break;
case "resolvedModule":
return (
(moduleReason.module !== moduleReason.resolvedModule &&
item.content)
moduleReason.module !== moduleReason.resolvedModule &&
item.content
);
}
return true;
@ -931,7 +927,12 @@ const AVAILABLE_FORMATS = {
(oversize ? yellow : green)(filename),
formatFlag: flag => `[${flag}]`,
formatSize: require("../SizeFormatHelpers").formatSize,
formatTime: (time, { timeReference, bold, green, yellow, red }) => {
formatTime: (
time,
{ timeReference, bold, green, yellow, red },
boldQuantity
) => {
const unit = " ms";
if (timeReference && time !== timeReference) {
const times = [
timeReference / 2,
@ -939,13 +940,13 @@ const AVAILABLE_FORMATS = {
timeReference / 8,
timeReference / 16
];
if (time < times[3]) return `${time}ms`;
else if (time < times[2]) return bold(`${time}ms`);
else if (time < times[1]) return green(`${time}ms`);
else if (time < times[0]) return yellow(`${time}ms`);
else return red(`${time}ms`);
if (time < times[3]) return `${time}${unit}`;
else if (time < times[2]) return bold(`${time}${unit}`);
else if (time < times[1]) return green(`${time}${unit}`);
else if (time < times[0]) return yellow(`${time}${unit}`);
else return red(`${time}${unit}`);
} else {
return `${time}ms`;
return `${boldQuantity ? bold(time) : time}${unit}`;
}
}
};

View File

@ -74,7 +74,7 @@ exports.arrayToSetDeprecation = (set, name) => {
* @this {Set}
* @returns {number} count
*/
set[method] = function() {
set[method] = function () {
d();
const array = Array.from(this);
return Array.prototype[method].apply(array, arguments);
@ -97,7 +97,7 @@ exports.arrayToSetDeprecation = (set, name) => {
* @this {Set}
* @returns {number} count
*/
set.push = function() {
set.push = function () {
dPush();
for (const item of Array.from(arguments)) {
this.add(item);
@ -117,7 +117,7 @@ exports.arrayToSetDeprecation = (set, name) => {
* @this {Set} a Set
* @returns {any} the value at this location
*/
const fn = function() {
const fn = function () {
dIndexer();
let i = 0;
for (const item of this) {

View File

@ -64,8 +64,7 @@ const validateSchema = (schema, options) => {
}
if (error.keyword === "additionalProperties") {
const params =
/** @type {import("ajv").AdditionalPropertiesParams} */ (error.params);
const params = /** @type {import("ajv").AdditionalPropertiesParams} */ (error.params);
if (
Object.prototype.hasOwnProperty.call(
DID_YOU_MEAN,

View File

@ -455,9 +455,9 @@ rules:
actions:
label:
remove:
- "PR: next"
- "PR: webpack-4"
- "PR: non-master"
- "PR: next"
- "PR: webpack-4"
- "PR: non-master"
- filters:
pull_request:
base_ref: "^next$"
@ -465,8 +465,8 @@ rules:
label:
add: "PR: next"
remove:
- "PR: webpack-4"
- "PR: non-master"
- "PR: webpack-4"
- "PR: non-master"
- filters:
pull_request:
base_ref: "^webpack-4$"
@ -474,8 +474,8 @@ rules:
label:
add: "PR: webpack-4"
remove:
- "PR: next"
- "PR: non-master"
- "PR: next"
- "PR: non-master"
- filters:
pull_request:
base_ref: "^(?!master$)(?!webpack-4$)(?!next$)"
@ -483,8 +483,8 @@ rules:
label:
add: "PR: non-master"
remove:
- "PR: next"
- "PR: webpack-4"
- "PR: next"
- "PR: webpack-4"
# add non-master label to pull request to other branch
- filters:

View File

@ -68,7 +68,7 @@
"mini-css-extract-plugin": "^0.8.0",
"mini-svg-data-uri": "^1.1.3",
"open-cli": "^5.0.0",
"prettier": "^1.14.3",
"prettier": "2",
"pretty-format": "^25.1.0",
"pug": "^2.0.4",
"pug-loader": "^2.4.0",
@ -130,14 +130,17 @@
"type-report": "rimraf coverage && yarn cover:types && yarn cover:report && open-cli coverage/lcov-report/index.html",
"pretest": "yarn lint",
"prelint": "yarn setup",
"lint": "yarn code-lint && yarn jest-lint && yarn type-lint && yarn special-lint && yarn spellcheck",
"lint": "yarn code-lint && yarn jest-lint && yarn type-lint && yarn special-lint && yarn pretty-lint && yarn spellcheck",
"code-lint": "eslint . --ext '.js' --cache",
"type-lint": "tsc --pretty",
"spellcheck": "cspell \"{.github,benchmark,bin,examples,hot,lib,schemas,setup,tooling}/**/*.{md,yml,yaml,js,json}\" \"*.md\"",
"special-lint": "node tooling/inherit-types && node tooling/format-schemas && node tooling/format-file-header && node tooling/compile-to-definitions",
"special-lint-fix": "node tooling/inherit-types --write --override && node tooling/format-schemas --write && node tooling/format-file-header --write && node tooling/compile-to-definitions --write",
"fix": "yarn code-lint --fix && yarn special-lint-fix",
"pretty": "prettier --loglevel warn --write \"*.{ts,js,json,yml,yaml}\" \"{setup,lib,bin,hot,benchmark,tooling,schemas}/**/*.{js,json}\" \"test/*.js\" \"test/helpers/*.js\" \"test/{configCases,watchCases,statsCases,hotCases}/**/webpack.config.js\" \"examples/**/webpack.config.js\"",
"fix": "yarn code-lint --fix && yarn special-lint-fix && yarn pretty-lint-fix",
"pretty-lint-base": "prettier \"*.{ts,json,yml,yaml,md}\" \"{setup,lib,bin,hot,benchmark,tooling,schemas}/**/*.json\" \"examples/*.md\"",
"pretty-lint-base-all": "yarn pretty-lint-base \"*.js\" \"{setup,lib,bin,hot,benchmark,tooling,schemas}/**/*.js\" \"test/*.js\" \"test/helpers/*.js\" \"test/{configCases,watchCases,statsCases,hotCases,benchmarkCases}/**/webpack.config.js\" \"examples/**/webpack.config.js\"",
"pretty-lint-fix": "yarn pretty-lint-base-all --loglevel warn --write",
"pretty-lint": "yarn pretty-lint-base --check",
"jest-lint": "node --max-old-space-size=4096 node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/test/*.lint.js\" --no-verbose",
"benchmark": "node --max-old-space-size=4096 --trace-deprecation node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/test/*.benchmark.js\" --runInBand",
"cover": "yarn cover:all && yarn cover:report",
@ -157,6 +160,9 @@
"*.js|{lib,setup,bin,hot,tooling,schemas}/**/*.js|test/*.js|{test,examples}/**/webpack.config.js}": [
"eslint --cache"
],
"*.{ts,json,yml,yaml,md}|examples/*.md": [
"prettier --check"
],
"*.md|{.github,benchmark,bin,examples,hot,lib,schemas,setup,tooling}/**/*.{md,yml,yaml,js,json}": [
"cspell"
]

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,7 @@
"properties": {
"dataUrl": {
"description": "The options for data url generator.",
"oneOf": [
"anyOf": [
{
"$ref": "#/definitions/DataUrlOptions"
},

View File

@ -23,7 +23,7 @@
"properties": {
"dataUrlCondition": {
"description": "The condition for inlining the asset as DataUrl.",
"oneOf": [
"anyOf": [
{
"$ref": "#/definitions/DataUrlOptions"
},

View File

@ -7,7 +7,7 @@
},
"Rule": {
"description": "Filtering rule as regex or string.",
"oneOf": [
"anyOf": [
{
"instanceof": "RegExp",
"tsType": "RegExp"
@ -20,12 +20,12 @@
},
"Rules": {
"description": "Filtering rules.",
"oneOf": [
"anyOf": [
{
"type": "array",
"items": {
"description": "A rule condition.",
"anyOf": [
"oneOf": [
{
"$ref": "#/definitions/Rule"
}
@ -39,7 +39,12 @@
}
},
"title": "BannerPluginArgument",
"oneOf": [
"anyOf": [
{
"description": "The banner as string, it will be wrapped in a comment.",
"type": "string",
"minLength": 1
},
{
"title": "BannerPluginOptions",
"type": "object",
@ -49,10 +54,10 @@
"description": "Specifies the banner.",
"anyOf": [
{
"$ref": "#/definitions/BannerFunction"
"type": "string"
},
{
"type": "string"
"$ref": "#/definitions/BannerFunction"
}
]
},
@ -62,7 +67,7 @@
},
"exclude": {
"description": "Exclude all modules matching any of these conditions.",
"anyOf": [
"oneOf": [
{
"$ref": "#/definitions/Rules"
}
@ -70,7 +75,7 @@
},
"include": {
"description": "Include all modules matching any of these conditions.",
"anyOf": [
"oneOf": [
{
"$ref": "#/definitions/Rules"
}
@ -82,7 +87,7 @@
},
"test": {
"description": "Include all modules that pass test assertion.",
"anyOf": [
"oneOf": [
{
"$ref": "#/definitions/Rules"
}
@ -93,11 +98,6 @@
},
{
"$ref": "#/definitions/BannerFunction"
},
{
"description": "The banner as string, it will be wrapped in a comment.",
"type": "string",
"minLength": 1
}
]
}

View File

@ -15,10 +15,6 @@
"exports": {
"description": "Information about the provided exports of the module.",
"anyOf": [
{
"description": "Exports unknown/dynamic.",
"enum": [true]
},
{
"description": "List of provided exports of the module.",
"type": "array",
@ -27,6 +23,10 @@
"type": "string",
"minLength": 1
}
},
{
"description": "Exports unknown/dynamic.",
"enum": [true]
}
]
},
@ -54,7 +54,7 @@
"properties": {
"content": {
"description": "The mappings from request to module info.",
"anyOf": [
"oneOf": [
{
"$ref": "#/definitions/DllReferencePluginOptionsContent"
}
@ -67,7 +67,7 @@
},
"type": {
"description": "The type how the dll is exposed (external type).",
"anyOf": [
"oneOf": [
{
"$ref": "#/definitions/DllReferencePluginOptionsSourceType"
}
@ -91,7 +91,8 @@
"amd-require",
"umd",
"umd2",
"jsonp"
"jsonp",
"system"
]
}
},
@ -116,13 +117,13 @@
},
"manifest": {
"description": "An object containing content and name or a string to the absolute path of the JSON manifest to be loaded upon compilation.",
"oneOf": [
{
"$ref": "#/definitions/DllReferencePluginOptionsManifest"
},
"anyOf": [
{
"type": "string",
"absolutePath": true
},
{
"$ref": "#/definitions/DllReferencePluginOptionsManifest"
}
]
},
@ -138,7 +139,7 @@
},
"sourceType": {
"description": "How the dll is exposed (libraryTarget, defaults to manifest.type).",
"anyOf": [
"oneOf": [
{
"$ref": "#/definitions/DllReferencePluginOptionsSourceType"
}
@ -157,7 +158,7 @@
"properties": {
"content": {
"description": "The mappings from request to module info.",
"anyOf": [
"oneOf": [
{
"$ref": "#/definitions/DllReferencePluginOptionsContent"
}
@ -188,7 +189,7 @@
},
"sourceType": {
"description": "How the dll is exposed (libraryTarget).",
"anyOf": [
"oneOf": [
{
"$ref": "#/definitions/DllReferencePluginOptionsSourceType"
}

View File

@ -1,6 +1,6 @@
{
"title": "IgnorePluginOptions",
"oneOf": [
"anyOf": [
{
"type": "object",
"additionalProperties": false,

View File

@ -28,7 +28,7 @@
},
"handler": {
"description": "Function that executes for every progress step.",
"anyOf": [
"oneOf": [
{
"$ref": "#/definitions/HandlerFunction"
}
@ -54,7 +54,7 @@
}
},
"title": "ProgressPluginArgument",
"oneOf": [
"anyOf": [
{
"$ref": "#/definitions/ProgressPluginOptions"
},

View File

@ -2,7 +2,7 @@
"definitions": {
"rule": {
"description": "Include source maps for modules based on their extension (defaults to .js and .css).",
"oneOf": [
"anyOf": [
{
"instanceof": "RegExp",
"tsType": "RegExp"
@ -15,12 +15,12 @@
},
"rules": {
"description": "Include source maps for modules based on their extension (defaults to .js and .css).",
"oneOf": [
"anyOf": [
{
"type": "array",
"items": {
"description": "A rule condition.",
"anyOf": [
"oneOf": [
{
"$ref": "#/definitions/rule"
}
@ -39,7 +39,7 @@
"properties": {
"append": {
"description": "Appends the given value to the original asset. Usually the #sourceMappingURL comment. [url] is replaced with a URL to the source map file. false disables the appending.",
"oneOf": [
"anyOf": [
{
"description": "Append no SourceMap comment to the bundle, but still generate SourceMaps.",
"enum": [false, null]
@ -56,7 +56,7 @@
},
"exclude": {
"description": "Exclude modules that match the given value from source map generation.",
"anyOf": [
"oneOf": [
{
"$ref": "#/definitions/rules"
}
@ -64,15 +64,15 @@
},
"fallbackModuleFilenameTemplate": {
"description": "Generator string or function to create identifiers of modules for the 'sources' array in the SourceMap used only if 'moduleFilenameTemplate' would result in a conflict.",
"oneOf": [
"anyOf": [
{
"type": "string",
"minLength": 1
},
{
"description": "Custom function generating the identifier.",
"instanceof": "Function",
"tsType": "Function"
},
{
"type": "string",
"minLength": 1
}
]
},
@ -82,7 +82,7 @@
},
"filename": {
"description": "Defines the output filename of the SourceMap (will be inlined if no value is provided).",
"oneOf": [
"anyOf": [
{
"description": "Disable separate SourceMap file and inline SourceMap as DataUrl.",
"enum": [false, null]
@ -96,7 +96,7 @@
},
"include": {
"description": "Include source maps for module paths that match the given value.",
"anyOf": [
"oneOf": [
{
"$ref": "#/definitions/rules"
}
@ -108,15 +108,15 @@
},
"moduleFilenameTemplate": {
"description": "Generator string or function to create identifiers of modules for the 'sources' array in the SourceMap.",
"oneOf": [
"anyOf": [
{
"type": "string",
"minLength": 1
},
{
"description": "Custom function generating the identifier.",
"instanceof": "Function",
"tsType": "Function"
},
{
"type": "string",
"minLength": 1
}
]
},

View File

@ -8,13 +8,13 @@
"type": "array",
"items": {
"description": "RegExp or absolute path to directories or files that should be ignored.",
"oneOf": [
{
"type": "string"
},
"anyOf": [
{
"instanceof": "RegExp",
"tsType": "RegExp"
},
{
"type": "string"
}
]
},

View File

@ -96,11 +96,7 @@ function execGetOutput(command, args, description) {
if (exitCode) {
reject(`${description} failed with exit code ${exitCode}`);
} else {
resolve(
Buffer.concat(buffers)
.toString("utf-8")
.trim()
);
resolve(Buffer.concat(buffers).toString("utf-8").trim());
}
});
const buffers = [];

View File

@ -6,9 +6,9 @@ const asyncLib = require("neo-async");
const Benchmark = require("benchmark");
const { remove } = require("./helpers/remove");
describe("BenchmarkTestCases", function() {
describe("BenchmarkTestCases", function () {
const casesPath = path.join(__dirname, "benchmarkCases");
const tests = fs.readdirSync(casesPath).filter(function(folder) {
const tests = fs.readdirSync(casesPath).filter(function (folder) {
return (
folder.indexOf("_") < 0 &&
fs.existsSync(path.resolve(casesPath, folder, "webpack.config.js"))
@ -25,7 +25,7 @@ describe("BenchmarkTestCases", function() {
fs.mkdirSync(baselinesPath);
} catch (e) {} // eslint-disable-line no-empty
beforeAll(function(done) {
beforeAll(function (done) {
const git = require("simple-git");
const rootPath = path.join(__dirname, "..");
getBaselineRevs(rootPath, (err, baselineRevisions) => {
@ -231,7 +231,7 @@ describe("BenchmarkTestCases", function() {
const warmupCompiler = webpack(config, (err, stats) => {
warmupCompiler.purgeInputFileSystem();
const bench = new Benchmark(
function(deferred) {
function (deferred) {
const compiler = webpack(config, (err, stats) => {
compiler.purgeInputFileSystem();
if (err) {
@ -249,18 +249,18 @@ describe("BenchmarkTestCases", function() {
maxTime: 30,
defer: true,
initCount: 1,
onComplete: function() {
onComplete: function () {
const stats = bench.stats;
const n = stats.sample.length;
const nSqrt = Math.sqrt(n);
const z = tDistribution(n - 1);
stats.minConfidence = stats.mean - (z * stats.deviation) / nSqrt;
stats.maxConfidence = stats.mean + (z * stats.deviation) / nSqrt;
stats.text = `${Math.round(stats.mean * 1000)}ms ± ${Math.round(
stats.text = `${Math.round(stats.mean * 1000)} ms ± ${Math.round(
stats.deviation * 1000
)}ms [${Math.round(stats.minConfidence * 1000)}ms; ${Math.round(
)} ms [${Math.round(stats.minConfidence * 1000)} ms; ${Math.round(
stats.maxConfidence * 1000
)}ms]`;
)} ms]`;
callback(null, bench.stats);
},
onError: callback
@ -276,10 +276,10 @@ describe("BenchmarkTestCases", function() {
tests.forEach(testName => {
const testDirectory = path.join(casesPath, testName);
let headStats = null;
describe(`${testName} create benchmarks`, function() {
describe(`${testName} create benchmarks`, function () {
baselines.forEach(baseline => {
let baselineStats = null;
it(`should benchmark ${baseline.name} (${baseline.rev})`, function(done) {
it(`should benchmark ${baseline.name} (${baseline.rev})`, function (done) {
const outputDirectory = path.join(
__dirname,
"js",
@ -330,7 +330,7 @@ describe("BenchmarkTestCases", function() {
}, 180000);
if (baseline.name !== "HEAD") {
it(`HEAD should not be slower than ${baseline.name} (${baseline.rev})`, function() {
it(`HEAD should not be slower than ${baseline.name} (${baseline.rev})`, function () {
if (baselineStats.maxConfidence < headStats.minConfidence) {
throw new Error(
`HEAD (${headStats.text}) is slower than ${baseline.name} (${baselineStats.text}) (90% confidence)`

378
test/Cli.test.js Normal file
View File

@ -0,0 +1,378 @@
const { getArguments, processArguments } = require("../").cli;
describe("Cli", () => {
it("should generate the correct cli flags", () => {
expect(getArguments()).toMatchSnapshot();
});
const test = (name, values, config, fn) => {
it(`should correctly process arguments for ${name}`, () => {
const args = getArguments();
const problems = processArguments(args, config, values);
fn(expect(problems || config));
});
};
test("none", {}, {}, e => e.toMatchInlineSnapshot(`Object {}`));
test("root boolean", { bail: true }, {}, e =>
e.toMatchInlineSnapshot(`
Object {
"bail": true,
}
`)
);
test("root single item of multiple", { entry: "./a.js" }, {}, e =>
e.toMatchInlineSnapshot(`
Object {
"entry": Array [
"./a.js",
],
}
`)
);
test(
"root single item of multiple with existing item",
{ entry: "./a.js" },
{ entry: "./old.js" },
e =>
e.toMatchInlineSnapshot(`
Object {
"entry": Array [
"./old.js",
"./a.js",
],
}
`)
);
test(
"root single item of multiple with existing items",
{ entry: "./a.js" },
{ entry: ["./old1.js", "./old2.js"] },
e =>
e.toMatchInlineSnapshot(`
Object {
"entry": Array [
"./old1.js",
"./old2.js",
"./a.js",
],
}
`)
);
test("root multiple items", { entry: ["./a.js", "./b.js"] }, {}, e =>
e.toMatchInlineSnapshot(`
Object {
"entry": Array [
"./a.js",
"./b.js",
],
}
`)
);
test(
"root multiple items with existing item",
{ entry: ["./a.js", "./b.js"] },
{ entry: "./old.js" },
e =>
e.toMatchInlineSnapshot(`
Object {
"entry": Array [
"./old.js",
"./a.js",
"./b.js",
],
}
`)
);
test(
"root multiple items with existing items",
{ entry: ["./a.js", "./b.js"] },
{ entry: ["./old1.js", "./old2.js"] },
e =>
e.toMatchInlineSnapshot(`
Object {
"entry": Array [
"./old1.js",
"./old2.js",
"./a.js",
"./b.js",
],
}
`)
);
test("nested boolean", { "experiments-top-level-await": true }, {}, e =>
e.toMatchInlineSnapshot(`
Object {
"experiments": Object {
"topLevelAwait": true,
},
}
`)
);
test(
"nested regexp",
{ "stats-warnings-filter": ["/module/", "path"] },
{},
e =>
e.toMatchInlineSnapshot(`
Object {
"stats": Object {
"warningsFilter": Array [
/module/,
"path",
],
},
}
`)
);
test(
"nested multiple",
{
"module-rules-test": ["/\\.css$/", "/\\.js$/"],
"module-rules-use": ["css-loader", "babel-loader"]
},
{},
e =>
e.toMatchInlineSnapshot(`
Object {
"module": Object {
"rules": Array [
Object {
"test": /\\\\\\.css\\$/,
"use": "css-loader",
},
Object {
"test": /\\\\\\.js\\$/,
"use": "babel-loader",
},
],
},
}
`)
);
test(
"reset array",
{
"stats-warnings-filter-reset": true,
"stats-warnings-filter": "path",
"module-rules-reset": true,
"module-rules-test": ["/\\.css$/", "/\\.js$/"],
"module-rules-use": ["css-loader", "babel-loader"]
},
{
stats: { warningsFilter: [/a/, /b/] },
module: {
rules: [
{
test: /\.js$/,
use: "typescript-loader"
}
]
}
},
e =>
e.toMatchInlineSnapshot(`
Object {
"module": Object {
"rules": Array [
Object {
"test": /\\\\\\.css\\$/,
"use": "css-loader",
},
Object {
"test": /\\\\\\.js\\$/,
"use": "babel-loader",
},
],
},
"stats": Object {
"warningsFilter": Array [
"path",
],
},
}
`)
);
test(
"numbers",
{
"watch-options-aggregate-timeout": 100,
"output-ecma-version": "2015"
},
{},
e =>
e.toMatchInlineSnapshot(`
Object {
"output": Object {
"ecmaVersion": "2015",
},
"watchOptions": Object {
"aggregateTimeout": 100,
},
}
`)
);
test(
"booleans and enums",
{
"optimization-used-exports": true,
"output-compare-before-emit": false,
"output-iife": "true",
"output-library-name": ["hello", "world"],
"output-library-umd-named-define": "false",
"stats-logging": "verbose",
amd: "false"
},
{},
e =>
e.toMatchInlineSnapshot(`
Object {
"amd": false,
"optimization": Object {
"usedExports": true,
},
"output": Object {
"compareBeforeEmit": false,
"iife": true,
"library": Object {
"name": Array [
"hello",
"world",
],
"umdNamedDefine": false,
},
},
"stats": Object {
"logging": "verbose",
},
}
`)
);
test(
"errors",
{
"output-library-name": "non-object",
"resolve-loader-unsafe-cache": [true, false],
"output-ecma-version": "2015x",
"cache-type": "filsystem",
"entry-reset": false,
"module-unknown-context-reg-exp": "ab?c*",
"module-wrapped-context-reg-exp": 123,
"my-argument": true
},
{
output: {
library: "hello"
}
},
e =>
e.toMatchInlineSnapshot(`
Array [
Object {
"argument": "output-library-name",
"index": undefined,
"path": "output",
"type": "unexpected-non-object-in-path",
"value": "non-object",
},
Object {
"argument": "resolve-loader-unsafe-cache",
"index": 0,
"path": "resolveLoader.unsafeCache",
"type": "multiple-values-unexpected",
"value": true,
},
Object {
"argument": "resolve-loader-unsafe-cache",
"index": 1,
"path": "resolveLoader.unsafeCache",
"type": "multiple-values-unexpected",
"value": false,
},
Object {
"argument": "output-ecma-version",
"expected": "2009",
"index": undefined,
"path": "output.ecmaVersion",
"type": "invalid-value",
"value": "2015x",
},
Object {
"argument": "output-ecma-version",
"expected": "number",
"index": undefined,
"path": "output.ecmaVersion",
"type": "invalid-value",
"value": "2015x",
},
Object {
"argument": "cache-type",
"expected": "memory",
"index": undefined,
"path": "cache.type",
"type": "invalid-value",
"value": "filsystem",
},
Object {
"argument": "cache-type",
"expected": "filesystem",
"index": undefined,
"path": "cache.type",
"type": "invalid-value",
"value": "filsystem",
},
Object {
"argument": "entry-reset",
"expected": "true (will reset the previous value to an empty array)",
"index": undefined,
"path": "entry",
"type": "invalid-value",
"value": false,
},
Object {
"argument": "module-unknown-context-reg-exp",
"expected": "regular expression (example: /ab?c*/)",
"index": undefined,
"path": "module.unknownContextRegExp",
"type": "invalid-value",
"value": "ab?c*",
},
Object {
"argument": "module-unknown-context-reg-exp",
"expected": "true | false",
"index": undefined,
"path": "module.unknownContextRegExp",
"type": "invalid-value",
"value": "ab?c*",
},
Object {
"argument": "module-wrapped-context-reg-exp",
"expected": "regular expression (example: /ab?c*/)",
"index": undefined,
"path": "module.wrappedContextRegExp",
"type": "invalid-value",
"value": 123,
},
Object {
"argument": "my-argument",
"path": "",
"type": "unknown-argument",
},
]
`)
);
});

View File

@ -366,7 +366,7 @@ describe("Compiler", () => {
done();
});
});
it("should not be run twice at a time (run)", function(done) {
it("should not be run twice at a time (run)", function (done) {
const compiler = webpack({
context: __dirname,
mode: "production",
@ -384,7 +384,7 @@ describe("Compiler", () => {
if (err) return done();
});
});
it("should not be run twice at a time (watch)", function(done) {
it("should not be run twice at a time (watch)", function (done) {
const compiler = webpack({
context: __dirname,
mode: "production",
@ -402,7 +402,7 @@ describe("Compiler", () => {
if (err) return done();
});
});
it("should not be run twice at a time (run - watch)", function(done) {
it("should not be run twice at a time (run - watch)", function (done) {
const compiler = webpack({
context: __dirname,
mode: "production",
@ -420,7 +420,7 @@ describe("Compiler", () => {
if (err) return done();
});
});
it("should not be run twice at a time (watch - run)", function(done) {
it("should not be run twice at a time (watch - run)", function (done) {
const compiler = webpack({
context: __dirname,
mode: "production",
@ -438,7 +438,7 @@ describe("Compiler", () => {
if (err) return done();
});
});
it("should not be run twice at a time (instance cb)", function(done) {
it("should not be run twice at a time (instance cb)", function (done) {
const compiler = webpack(
{
context: __dirname,
@ -456,7 +456,7 @@ describe("Compiler", () => {
if (err) return done();
});
});
it("should run again correctly after first compilation", function(done) {
it("should run again correctly after first compilation", function (done) {
const compiler = webpack({
context: __dirname,
mode: "production",
@ -476,7 +476,7 @@ describe("Compiler", () => {
});
});
});
it("should watch again correctly after first compilation", function(done) {
it("should watch again correctly after first compilation", function (done) {
const compiler = webpack({
context: __dirname,
mode: "production",
@ -496,7 +496,7 @@ describe("Compiler", () => {
});
});
});
it("should run again correctly after first closed watch", function(done) {
it("should run again correctly after first closed watch", function (done) {
const compiler = webpack({
context: __dirname,
mode: "production",
@ -517,7 +517,7 @@ describe("Compiler", () => {
});
});
});
it("should watch again correctly after first closed watch", function(done) {
it("should watch again correctly after first closed watch", function (done) {
const compiler = webpack({
context: __dirname,
mode: "production",
@ -538,7 +538,7 @@ describe("Compiler", () => {
});
});
});
it("should run again correctly inside afterDone hook", function(done) {
it("should run again correctly inside afterDone hook", function (done) {
const compiler = webpack({
context: __dirname,
mode: "production",
@ -562,7 +562,7 @@ describe("Compiler", () => {
if (err) return done(err);
});
});
it("should call afterDone hook after other callbacks (run)", function(done) {
it("should call afterDone hook after other callbacks (run)", function (done) {
const compiler = webpack({
context: __dirname,
mode: "production",
@ -586,7 +586,7 @@ describe("Compiler", () => {
runCb();
});
});
it("should call afterDone hook after other callbacks (instance cb)", function(done) {
it("should call afterDone hook after other callbacks (instance cb)", function (done) {
const instanceCb = jest.fn();
const compiler = webpack(
{
@ -612,7 +612,7 @@ describe("Compiler", () => {
done();
});
});
it("should call afterDone hook after other callbacks (watch)", function(done) {
it("should call afterDone hook after other callbacks (watch)", function (done) {
const compiler = webpack({
context: __dirname,
mode: "production",
@ -639,7 +639,7 @@ describe("Compiler", () => {
});
watch.invalidate(invalidateCb);
});
it("should call afterDone hook after other callbacks (watch close)", function(done) {
it("should call afterDone hook after other callbacks (watch close)", function (done) {
const compiler = webpack({
context: __dirname,
mode: "production",
@ -666,7 +666,7 @@ describe("Compiler", () => {
});
watch.invalidate(invalidateCb);
});
it("should flag watchMode as true in watch", function(done) {
it("should flag watchMode as true in watch", function (done) {
const compiler = webpack({
context: __dirname,
mode: "production",
@ -688,7 +688,7 @@ describe("Compiler", () => {
});
});
});
it("should use cache on second run call", function(done) {
it("should use cache on second run call", function (done) {
const compiler = webpack({
context: __dirname,
mode: "development",
@ -771,7 +771,7 @@ describe("Compiler", () => {
});
compiler.outputFileSystem = createFsFromVolume(new Volume());
compiler.run((err, stats) => {
expect(capture.toString().replace(/[\d.]+ms/, "Xms"))
expect(capture.toString().replace(/[\d.]+ ms/, "X ms"))
.toMatchInlineSnapshot(`
"<-> [MyPlugin] Group
<e> [MyPlugin] Error
@ -780,7 +780,7 @@ describe("Compiler", () => {
[MyPlugin] Log
<-> [MyPlugin] Collaped group
[MyPlugin] Log inside collapsed group
<t> [MyPlugin] Time: Xms
<t> [MyPlugin] Time: X ms
"
`);
done();
@ -802,7 +802,7 @@ describe("Compiler", () => {
});
compiler.outputFileSystem = createFsFromVolume(new Volume());
compiler.run((err, stats) => {
expect(capture.toString().replace(/[\d.]+ms/, "Xms"))
expect(capture.toString().replace(/[\d.]+ ms/, "X ms"))
.toMatchInlineSnapshot(`
"<-> [MyPlugin] Group
<e> [MyPlugin] Error
@ -812,7 +812,7 @@ describe("Compiler", () => {
[MyPlugin] Debug
<-> [MyPlugin] Collaped group
[MyPlugin] Log inside collapsed group
<t> [MyPlugin] Time: Xms
<t> [MyPlugin] Time: X ms
"
`);
done();

View File

@ -43,7 +43,7 @@ describe("ConfigTestCases", () => {
categories.forEach(category => {
describe(category.name, () => {
category.tests.forEach(testName => {
describe(testName, function() {
describe(testName, function () {
const testDirectory = path.join(casesPath, category.name, testName);
const outputDirectory = path.join(
__dirname,
@ -84,7 +84,7 @@ describe("ConfigTestCases", () => {
options.output.filename = "bundle" + idx + ".js";
});
let testConfig = {
findBundle: function(i, options) {
findBundle: function (i, options) {
const ext = path.extname(options.output.filename);
if (
fs.existsSync(

View File

@ -18,7 +18,7 @@ describe("Examples", () => {
}
it(
"should compile " + relativePath,
function(done) {
function (done) {
let options = {};
let webpackConfigPath = path.join(examplePath, "webpack.config.js");
webpackConfigPath =

View File

@ -9,7 +9,7 @@ describe("JavascriptParser", () => {
/* eslint-disable no-inner-declarations */
const testCases = {
"call ident": [
function() {
function () {
abc("test");
},
{
@ -17,7 +17,7 @@ describe("JavascriptParser", () => {
}
],
"call member": [
function() {
function () {
cde.abc("membertest");
},
{
@ -25,7 +25,7 @@ describe("JavascriptParser", () => {
}
],
"call member using bracket notation": [
function() {
function () {
cde["abc"]("membertest");
},
{
@ -33,7 +33,7 @@ describe("JavascriptParser", () => {
}
],
"call inner member": [
function() {
function () {
cde.ddd.abc("inner");
},
{
@ -41,7 +41,7 @@ describe("JavascriptParser", () => {
}
],
"call inner member using bracket notation": [
function() {
function () {
cde.ddd["abc"]("inner");
},
{
@ -49,7 +49,7 @@ describe("JavascriptParser", () => {
}
],
expression: [
function() {
function () {
fgh;
},
{
@ -57,7 +57,7 @@ describe("JavascriptParser", () => {
}
],
"expression sub": [
function() {
function () {
fgh.sub;
},
{
@ -65,7 +65,7 @@ describe("JavascriptParser", () => {
}
],
"member expression": [
function() {
function () {
test[memberExpr];
test[+memberExpr];
},
@ -74,8 +74,8 @@ describe("JavascriptParser", () => {
}
],
"in function definition": [
function() {
(function(abc, cde, fgh) {
function () {
(function (abc, cde, fgh) {
abc("test");
cde.abc("test");
cde.ddd.abc("test");
@ -86,7 +86,7 @@ describe("JavascriptParser", () => {
{}
],
"const definition": [
function() {
function () {
let abc, cde, fgh;
abc("test");
cde.abc("test");
@ -97,7 +97,7 @@ describe("JavascriptParser", () => {
{}
],
"var definition": [
function() {
function () {
var abc, cde, fgh;
abc("test");
cde.abc("test");
@ -108,7 +108,7 @@ describe("JavascriptParser", () => {
{}
],
"function definition": [
function() {
function () {
function abc() {}
function cde() {}
@ -123,7 +123,7 @@ describe("JavascriptParser", () => {
{}
],
"class definition": [
function() {
function () {
class memberExpr {
cde() {
abc("cde");
@ -140,7 +140,7 @@ describe("JavascriptParser", () => {
}
],
"in try": [
function() {
function () {
try {
fgh.sub;
fgh;
@ -160,7 +160,7 @@ describe("JavascriptParser", () => {
}
],
"renaming with const": [
function() {
function () {
const xyz = abc;
xyz("test");
},
@ -169,7 +169,7 @@ describe("JavascriptParser", () => {
}
],
"renaming with var": [
function() {
function () {
var xyz = abc;
xyz("test");
},
@ -178,7 +178,7 @@ describe("JavascriptParser", () => {
}
],
"renaming with assignment": [
function() {
function () {
const xyz = abc;
xyz("test");
},
@ -187,8 +187,8 @@ describe("JavascriptParser", () => {
}
],
"renaming with IIFE": [
function() {
!(function(xyz) {
function () {
!(function (xyz) {
xyz("test");
})(abc);
},
@ -197,8 +197,8 @@ describe("JavascriptParser", () => {
}
],
"renaming arguments with IIFE (called)": [
function() {
!function(xyz) {
function () {
!function (xyz) {
xyz("test");
}.call(fgh, abc);
},
@ -208,8 +208,8 @@ describe("JavascriptParser", () => {
}
],
"renaming this's properties with IIFE (called)": [
function() {
!function() {
function () {
!function () {
this.sub;
}.call(ijk);
},
@ -218,9 +218,9 @@ describe("JavascriptParser", () => {
}
],
"renaming this's properties with nested IIFE (called)": [
function() {
!function() {
!function() {
function () {
!function () {
!function () {
this.sub;
}.call(this);
}.call(ijk);
@ -230,7 +230,7 @@ describe("JavascriptParser", () => {
}
],
"new Foo(...)": [
function() {
function () {
new xyz("membertest");
},
{
@ -238,7 +238,7 @@ describe("JavascriptParser", () => {
}
],
"spread calls/literals": [
function() {
function () {
var xyz = [...abc("xyz"), cde];
Math.max(...fgh);
},

View File

@ -19,7 +19,7 @@ const createMultiCompiler = () => {
return compiler;
};
describe("MultiCompiler", function() {
describe("MultiCompiler", function () {
jest.setTimeout(20000);
it("should trigger 'run' for each child compiler", done => {
@ -53,7 +53,7 @@ describe("MultiCompiler", function() {
});
});
it("should not be run twice at a time (run)", function(done) {
it("should not be run twice at a time (run)", function (done) {
const compiler = createMultiCompiler();
compiler.run((err, stats) => {
if (err) return done(err);
@ -62,7 +62,7 @@ describe("MultiCompiler", function() {
if (err) return done();
});
});
it("should not be run twice at a time (watch)", function(done) {
it("should not be run twice at a time (watch)", function (done) {
const compiler = createMultiCompiler();
const watcher = compiler.watch({}, (err, stats) => {
if (err) return done(err);
@ -71,7 +71,7 @@ describe("MultiCompiler", function() {
if (err) return watcher.close(done);
});
});
it("should not be run twice at a time (run - watch)", function(done) {
it("should not be run twice at a time (run - watch)", function (done) {
const compiler = createMultiCompiler();
compiler.run((err, stats) => {
if (err) return done(err);
@ -80,7 +80,7 @@ describe("MultiCompiler", function() {
if (err) return done();
});
});
it("should not be run twice at a time (watch - run)", function(done) {
it("should not be run twice at a time (watch - run)", function (done) {
const compiler = createMultiCompiler();
let watcher;
watcher = compiler.watch({}, (err, stats) => {
@ -90,7 +90,7 @@ describe("MultiCompiler", function() {
if (err) return watcher.close(done);
});
});
it("should not be run twice at a time (instance cb)", function(done) {
it("should not be run twice at a time (instance cb)", function (done) {
const compiler = webpack(
{
context: __dirname,
@ -108,7 +108,7 @@ describe("MultiCompiler", function() {
if (err) return done();
});
});
it("should run again correctly after first compilation", function(done) {
it("should run again correctly after first compilation", function (done) {
const compiler = createMultiCompiler();
compiler.run((err, stats) => {
if (err) return done(err);
@ -119,7 +119,7 @@ describe("MultiCompiler", function() {
});
});
});
it("should watch again correctly after first compilation", function(done) {
it("should watch again correctly after first compilation", function (done) {
const compiler = createMultiCompiler();
compiler.run((err, stats) => {
if (err) return done(err);
@ -131,7 +131,7 @@ describe("MultiCompiler", function() {
});
});
});
it("should run again correctly after first closed watch", function(done) {
it("should run again correctly after first closed watch", function (done) {
const compiler = createMultiCompiler();
const watching = compiler.watch({}, (err, stats) => {
if (err) return done(err);
@ -143,7 +143,7 @@ describe("MultiCompiler", function() {
});
});
});
it("should watch again correctly after first closed watch", function(done) {
it("should watch again correctly after first closed watch", function (done) {
const compiler = createMultiCompiler();
const watching = compiler.watch({}, (err, stats) => {
if (err) return done(err);

View File

@ -5,7 +5,7 @@ const fs = require("graceful-fs");
const webpack = require("../");
const rimraf = require("rimraf");
describe("Profiling Plugin", function() {
describe("Profiling Plugin", function () {
jest.setTimeout(15000);
it("should handle output path with folder creation", done => {

View File

@ -7,7 +7,7 @@ const captureStdio = require("./helpers/captureStdio");
let webpack;
describe("ProgressPlugin", function() {
describe("ProgressPlugin", function () {
let stderr;
beforeEach(() => {
@ -78,6 +78,19 @@ describe("ProgressPlugin", function() {
expect(logs).toEqual(expect.stringMatching(/\d+ active/));
});
});
it("should get the custom handler text from the log", () => {
const compiler = createSimpleCompilerWithCustomHandler();
return RunCompilerAsync(compiler).then(() => {
const logs = stderr.toString();
expect(logs).toEqual(
expect.stringMatching(/\d+\/\d+ [custom test logger]/)
);
expect(logs).toEqual(expect.stringMatching(/\d+ active/));
expect(logs).toEqual(expect.stringMatching(/\d+\/\d+ modules/));
});
});
});
const createMultiCompiler = () => {
@ -114,6 +127,23 @@ const createSimpleCompiler = progressOptions => {
return compiler;
};
const createSimpleCompilerWithCustomHandler = options => {
const compiler = webpack({
context: path.join(__dirname, "fixtures"),
entry: "./a.js"
});
compiler.outputFileSystem = createFsFromVolume(new Volume());
const logger = compiler.getInfrastructureLogger("custom test logger");
new webpack.ProgressPlugin({
activeModules: true,
...options,
handler: (...args) => logger.status(args)
}).apply(compiler);
return compiler;
};
const getLogs = logsStr => logsStr.split(/\r/).filter(v => !(v === " "));
const RunCompilerAsync = compiler =>

Some files were not shown because too many files have changed in this diff Show More