Merge branch 'feature/type-compiler-compilation-save' of https://github.com/webpack/webpack into feature/type-compiler-compilation-save
Conflicts: .github/ISSUE_TEMPLATE/Bug_report.md
This commit is contained in:
commit
e737a4348a
|
@ -2,11 +2,11 @@ root = true
|
|||
|
||||
[*]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
max_line_length = 233
|
||||
max_line_length = 80
|
||||
|
||||
[.prettierrc]
|
||||
indent_style = space
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
<!-- Please don't delete this template or we'll close your issue -->
|
||||
<!-- Please don't delete this template because we'll close your issue -->
|
||||
<!-- Before creating an issue please make sure you are using the latest version of webpack. -->
|
||||
|
||||
# Bug report
|
||||
|
@ -20,18 +19,18 @@ about: Create a report to help us improve
|
|||
**If the current behavior is a bug, please provide the steps to reproduce.**
|
||||
|
||||
|
||||
<!-- A great way to do this is to provide your configuration via a GitHub repo. -->
|
||||
<!-- Best provide a minimal reproduceable repo with instructions -->
|
||||
<!-- Repos with too many files or long configs are not suitable -->
|
||||
<!-- Please only add small snippets of code directly into the issue -->
|
||||
<!-- A great way to do this is to provide your configuration via a GitHub repository -->
|
||||
<!-- The most helpful is a minimal reproduction with instructions on how to reproduce -->
|
||||
<!-- Repositories with too many files or large `webpack.config.js` files are not suitable -->
|
||||
<!-- Please only add small code snippets directly into this issue -->
|
||||
<!-- https://gist.github.com is a good place for longer code snippets -->
|
||||
<!-- If your issue is caused by a plugin or loader file the issue on the plugin/loader repo instead. -->
|
||||
<!-- If your issue is caused by a plugin or loader, please create an issue on the loader/plugin repository instead -->
|
||||
|
||||
**What is the expected behavior?**
|
||||
|
||||
|
||||
<!-- "It should work" is not a good explaination -->
|
||||
<!-- Explain how exactly you expecting it to behave -->
|
||||
<!-- "It should work" is not a helpful explanation -->
|
||||
<!-- Explain exactly how it should behave -->
|
||||
|
||||
**Other relevant information:**
|
||||
webpack version:
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
<!-- Thanks for submitting a pull request! Please provide enough information so that others can review your pull request. -->
|
||||
<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->
|
||||
<!-- Try to link to an open issue for more information. -->
|
||||
|
||||
|
||||
<!-- In addition to that please answer these questions: -->
|
||||
|
||||
**What kind of change does this PR introduce?**
|
||||
|
||||
|
@ -8,17 +13,11 @@
|
|||
|
||||
<!-- Note that we won't merge your changes if you don't add tests -->
|
||||
|
||||
**If relevant, link to documentation update:**
|
||||
|
||||
<!-- Link PR from webpack/webpack.js.org here, or N/A -->
|
||||
|
||||
**Summary**
|
||||
|
||||
<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->
|
||||
<!-- Try to link to an open issue for more information. -->
|
||||
|
||||
**Does this PR introduce a breaking change?**
|
||||
|
||||
<!-- If this PR introduces a breaking change, please describe the impact and a migration path for existing applications. -->
|
||||
|
||||
**Other information**
|
||||
**What needs to be documented once your changes are merged?**
|
||||
|
||||
<!-- List all the information that needs to be added to the documentation after merge -->
|
||||
<!-- When your changes are merged you will be asked to contribute this to the documentation -->
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
# Ignore all paths.
|
||||
**/*.*
|
||||
|
||||
# Enable prettier for the following paths.
|
||||
!setup/**/*.js
|
||||
!lib/**/*.js
|
||||
!bin/*.js
|
||||
!hot/*.js
|
||||
!buildin/*.js
|
||||
!benchmark/**/*.js
|
||||
!test/*.js
|
||||
!test/**/webpack.config.js
|
||||
!examples/**/webpack.config.js
|
||||
!schemas/**/*.js
|
||||
!declarations.d.ts
|
40
.travis.yml
40
.travis.yml
|
@ -9,42 +9,56 @@ branches:
|
|||
|
||||
cache:
|
||||
yarn: true
|
||||
directories:
|
||||
- ".jest-cache"
|
||||
- ".eslintcache"
|
||||
|
||||
stages:
|
||||
- basic
|
||||
- advanced
|
||||
- versions
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
node_js: "10"
|
||||
env: NO_WATCH_TESTS=1 JOB_PART=lint
|
||||
env: NO_WATCH_TESTS=1 JEST="--maxWorkers=2 --cacheDirectory .jest-cache" JOB_PART=basic
|
||||
stage: basic
|
||||
- os: linux
|
||||
node_js: "10"
|
||||
env: NO_WATCH_TESTS=1 JEST=--maxWorkers=2 JOB_PART=integration
|
||||
env: NO_WATCH_TESTS=1 JEST="--maxWorkers=2 --cacheDirectory .jest-cache" JOB_PART=lint-unit
|
||||
stage: advanced
|
||||
- os: linux
|
||||
node_js: "10"
|
||||
env: NO_WATCH_TESTS=1 JEST="--maxWorkers=2 --cacheDirectory .jest-cache" JOB_PART=integration
|
||||
stage: advanced
|
||||
- os: osx
|
||||
node_js: "10"
|
||||
env: NO_WATCH_TESTS=1 JEST="--maxWorkers=2 --cacheDirectory .jest-cache" JOB_PART=integration
|
||||
stage: versions
|
||||
- os: linux
|
||||
node_js: "8"
|
||||
env: NO_WATCH_TESTS=1 JEST=--maxWorkers=2 JOB_PART=integration
|
||||
- os: linux
|
||||
node_js: "10"
|
||||
env: NO_WATCH_TESTS=1 JOB_PART=unit
|
||||
env: NO_WATCH_TESTS=1 JEST="--maxWorkers=2 --cacheDirectory .jest-cache" JOB_PART=integration
|
||||
stage: versions
|
||||
- os: linux
|
||||
node_js: "6"
|
||||
env: NO_WATCH_TESTS=1 JEST=--maxWorkers=2 JOB_PART=integration
|
||||
- os: osx
|
||||
node_js: "10"
|
||||
env: NO_WATCH_TESTS=1 JEST=--maxWorkers=2 JOB_PART=integration
|
||||
env: NO_WATCH_TESTS=1 JEST="--maxWorkers=2 --cacheDirectory .jest-cache" JOB_PART=integration
|
||||
stage: versions
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- os: osx
|
||||
fast_finish: true
|
||||
|
||||
install:
|
||||
- yarn --frozen-lockfile
|
||||
- yarn link --frozen-lockfile || true
|
||||
- yarn link webpack --frozen-lockfile
|
||||
|
||||
script: npm run travis:$JOB_PART
|
||||
script: yarn travis:$JOB_PART
|
||||
|
||||
after_success:
|
||||
- cat ./coverage/lcov.info | node_modules/.bin/coveralls --verbose
|
||||
- bash <(curl -s https://codecov.io/bash) -F $JOB_PART -X gcov
|
||||
- rm -rf ./coverage
|
||||
- rm -f .jest-cache/haste-map* .jest-cache/perf-cache*
|
||||
|
||||
notifications:
|
||||
slack:
|
||||
|
|
147
README.md
147
README.md
|
@ -18,6 +18,9 @@
|
|||
<a href="https://npmcharts.com/compare/webpack?minimal=true">
|
||||
<img src="https://img.shields.io/npm/dm/webpack.svg">
|
||||
</a>
|
||||
<a href="https://packagephobia.now.sh/result?p=webpack">
|
||||
<img src="https://packagephobia.now.sh/badge?p=webpack" alt="install size">
|
||||
</a>
|
||||
<a href="https://opencollective.com/webpack#backer">
|
||||
<img src="https://opencollective.com/webpack/backers/badge.svg">
|
||||
</a>
|
||||
|
@ -84,25 +87,30 @@ interface](https://webpack.js.org/plugins/). Most of the features
|
|||
within webpack itself use this plugin interface. This makes webpack very
|
||||
**flexible**.
|
||||
|
||||
|Name|Status|Description|
|
||||
|:--:|:----:|:----------|
|
||||
|[extract-text-webpack-plugin][extract]|![extract-npm]|Extracts Text (CSS) from your bundles into a separate file (app.bundle.css)|
|
||||
|[compression-webpack-plugin][compression]|![compression-npm]|Prepares compressed versions of assets to serve them with Content-Encoding|
|
||||
|[i18n-webpack-plugin][i18n]|![i18n-npm]|Adds i18n support to your bundles|
|
||||
|[html-webpack-plugin][html-plugin]|![html-plugin-npm]| Simplifies creation of HTML files (`index.html`) to serve your bundles|
|
||||
|Name|Status|Install Size|Description|
|
||||
|:--:|:----:|:----------:|:----------|
|
||||
|[extract-text-webpack-plugin][extract]|![extract-npm]|![extract-size]|Extracts Text (CSS) from your bundles into a separate file (app.bundle.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|
|
||||
|
||||
|
||||
[common-npm]: https://img.shields.io/npm/v/webpack.svg
|
||||
[extract]: https://github.com/webpack/extract-text-webpack-plugin
|
||||
[extract-npm]: https://img.shields.io/npm/v/extract-text-webpack-plugin.svg
|
||||
[extract-size]: https://packagephobia.now.sh/badge?p=extract-text-webpack-plugin
|
||||
[component]: https://github.com/webpack/component-webpack-plugin
|
||||
[component-npm]: https://img.shields.io/npm/v/component-webpack-plugin.svg
|
||||
[component-size]: https://packagephobia.now.sh/badge?p=component-webpack-plugin
|
||||
[compression]: https://github.com/webpack/compression-webpack-plugin
|
||||
[compression-npm]: https://img.shields.io/npm/v/compression-webpack-plugin.svg
|
||||
[compression-size]: https://packagephobia.now.sh/badge?p=compression-webpack-plugin
|
||||
[i18n]: https://github.com/webpack/i18n-webpack-plugin
|
||||
[i18n-npm]: https://img.shields.io/npm/v/i18n-webpack-plugin.svg
|
||||
[i18n-size]: https://packagephobia.now.sh/badge?p=i18n-webpack-plugin
|
||||
[html-plugin]: https://github.com/ampedandwired/html-webpack-plugin
|
||||
[html-plugin-npm]: https://img.shields.io/npm/v/html-webpack-plugin.svg
|
||||
[html-plugin-size]: https://packagephobia.now.sh/badge?p=html-webpack-plugin
|
||||
|
||||
### [Loaders](https://webpack.js.org/loaders/)
|
||||
|
||||
|
@ -115,121 +123,154 @@ or are automatically applied via regex from your webpack configuration.
|
|||
|
||||
#### Files
|
||||
|
||||
|Name|Status|Description|
|
||||
|:--:|:----:|:----------|
|
||||
|[raw-loader][raw]|![raw-npm]|Loads raw content of a file (utf-8)|
|
||||
|[val-loader][val]|![val-npm]|Executes code as module and considers exports as JS code|
|
||||
|[url-loader][url]|![url-npm]|Works like the file loader, but can return a Data Url if the file is smaller than a limit|
|
||||
|[file-loader][file]|![file-npm]|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/raw-loader
|
||||
[raw-npm]: https://img.shields.io/npm/v/raw-loader.svg
|
||||
[raw-size]: https://packagephobia.now.sh/badge?p=raw-loader
|
||||
[val]: https://github.com/webpack/val-loader
|
||||
[val-npm]: https://img.shields.io/npm/v/val-loader.svg
|
||||
[val-size]: https://packagephobia.now.sh/badge?p=val-loader
|
||||
[url]: https://github.com/webpack/url-loader
|
||||
[url-npm]: https://img.shields.io/npm/v/url-loader.svg
|
||||
[url-size]: https://packagephobia.now.sh/badge?p=url-loader
|
||||
[file]: https://github.com/webpack/file-loader
|
||||
[file-npm]: https://img.shields.io/npm/v/file-loader.svg
|
||||
[file-size]: https://packagephobia.now.sh/badge?p=file-loader
|
||||
|
||||
#### JSON
|
||||
|
||||
|Name|Status|Description|
|
||||
|:--:|:----:|:----------|
|
||||
|<a href="https://github.com/webpack/json-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/json.svg"></a>|![json-npm]|Loads a JSON file (included by default)|
|
||||
|<a href="https://github.com/webpack/json5-loader"><img width="48" height="10.656" src="https://cdn.rawgit.com/json5/json5-logo/master/json5-logo.svg"></a>|![json5-npm]|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]|Loads and transpiles a CSON file|
|
||||
|Name|Status|Install Size|Description|
|
||||
|:--:|:----:|:----------:|:----------|
|
||||
|<a href="https://github.com/webpack/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/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
|
||||
[json5-npm]: https://img.shields.io/npm/v/json5-loader.svg
|
||||
[json5-size]: https://packagephobia.now.sh/badge?p=json5-loader
|
||||
[cson-npm]: https://img.shields.io/npm/v/cson-loader.svg
|
||||
[cson-size]: https://packagephobia.now.sh/badge?p=cson-loader
|
||||
|
||||
#### Transpiling
|
||||
|
||||
|Name|Status|Description|
|
||||
|:--:|:----:|:----------|
|
||||
|<a href="https://github.com/webpack/script-loader">`<script>`</a>|![script-npm]|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]|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]|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]|Loads TypeScript like JavaScript|
|
||||
|[`awesome-typescript-loader`](https://github.com/s-panferov/awesome-typescript-loader)|![awesome-typescript-npm]|Awesome TypeScript loader for webpack|
|
||||
|<a href="https://github.com/webpack/coffee-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a>|![coffee-npm]|Loads CoffeeScript like JavaScript|
|
||||
|Name|Status|Install Size|Description|
|
||||
|:--:|:----:|:----------:|:----------|
|
||||
|<a href="https://github.com/webpack/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/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
|
||||
[babel-npm]: https://img.shields.io/npm/v/babel-loader.svg
|
||||
[babel-size]: https://packagephobia.now.sh/badge?p=babel-loader
|
||||
[traceur-npm]: https://img.shields.io/npm/v/traceur-loader.svg
|
||||
[traceur-size]: https://packagephobia.now.sh/badge?p=traceur-loader
|
||||
[coffee-npm]: https://img.shields.io/npm/v/coffee-loader.svg
|
||||
[coffee-size]: https://packagephobia.now.sh/badge?p=coffee-loader
|
||||
[type-npm]: https://img.shields.io/npm/v/ts-loader.svg
|
||||
[type-size]: https://packagephobia.now.sh/badge?p=ts-loader
|
||||
[awesome-typescript-npm]: https://img.shields.io/npm/v/awesome-typescript-loader.svg
|
||||
[awesome-typescript-size]: https://packagephobia.now.sh/badge?p=awesome-typescript-loader
|
||||
|
||||
#### Templating
|
||||
|
||||
|Name|Status|Description|
|
||||
|:--:|:----:|:----------|
|
||||
|<a href="https://github.com/webpack/html-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/html5.svg"></a>|![html-npm]|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]|Loads Pug templates and returns a function|
|
||||
|<a href="https://github.com/webpack/jade-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/jade-3.svg"></a>|![jade-npm]|Loads Jade 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]|Compiles Markdown to HTML|
|
||||
|<a href="https://github.com/posthtml/posthtml-loader"><img width="48" height="48" src="http://posthtml.github.io/posthtml/logo.svg"></a>|![posthtml-npm]|Loads and transforms a HTML file using [PostHTML](https://github.com/posthtml/posthtml)|
|
||||
|<a href="https://github.com/altano/handlebars-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/handlebars-1.svg"></a>|![hbs-npm]| Compiles Handlebars to HTML|
|
||||
|Name|Status|Install Size|Description|
|
||||
|:--:|:----:|:----------:|:----------|
|
||||
|<a href="https://github.com/webpack/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/webpack/jade-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/jade-3.svg"></a>|![jade-npm]|![jade-size]|Loads Jade 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="http://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/altano/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
|
||||
[pug-npm]: https://img.shields.io/npm/v/pug-loader.svg
|
||||
[pug-size]: https://packagephobia.now.sh/badge?p=pug-loader
|
||||
[jade-npm]: https://img.shields.io/npm/v/jade-loader.svg
|
||||
[jade-size]: https://packagephobia.now.sh/badge?p=jade-loader
|
||||
[md-npm]: https://img.shields.io/npm/v/markdown-loader.svg
|
||||
[md-size]: https://packagephobia.now.sh/badge?p=markdown-loader
|
||||
[posthtml-npm]: https://img.shields.io/npm/v/posthtml-loader.svg
|
||||
[posthtml-size]: https://packagephobia.now.sh/badge?p=posthtml-loader
|
||||
[hbs-npm]: https://img.shields.io/npm/v/handlebars-loader.svg
|
||||
[hbs-size]: https://packagephobia.now.sh/badge?p=handlebars-loader
|
||||
|
||||
#### Styling
|
||||
|
||||
|Name|Status|Description|
|
||||
|:--:|:----:|:----------|
|
||||
|<a href="https://github.com/webpack/style-loader">`<style>`</a>|![style-npm]|Add exports of a module as style to DOM|
|
||||
|<a href="https://github.com/webpack/css-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/css-3.svg"></a>|![css-npm]|Loads CSS file with resolved imports and returns CSS code|
|
||||
|<a href="https://github.com/webpack/less-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/less-63.svg"></a>|![less-npm]|Loads and compiles a LESS file|
|
||||
|<a href="https://github.com/jtangelder/sass-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/sass-1.svg"></a>|![sass-npm]|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]|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]|Loads and transforms a CSS/SSS file using [PostCSS](http://postcss.org)|
|
||||
|Name|Status|Install Size|Description|
|
||||
|:--:|:----:|:----------:|:----------|
|
||||
|<a href="https://github.com/webpack/style-loader">`<style>`</a>|![style-npm]|![style-size]|Add exports of a module as style to DOM|
|
||||
|<a href="https://github.com/webpack/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/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/jtangelder/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](http://postcss.org)|
|
||||
|
||||
|
||||
[style-npm]: https://img.shields.io/npm/v/style-loader.svg
|
||||
[style-size]: https://packagephobia.now.sh/badge?p=style-loader
|
||||
[css-npm]: https://img.shields.io/npm/v/css-loader.svg
|
||||
[css-size]: https://packagephobia.now.sh/badge?p=css-loader
|
||||
[less-npm]: https://img.shields.io/npm/v/less-loader.svg
|
||||
[less-size]: https://packagephobia.now.sh/badge?p=less-loader
|
||||
[sass-npm]: https://img.shields.io/npm/v/sass-loader.svg
|
||||
[sass-size]: https://packagephobia.now.sh/badge?p=sass-loader
|
||||
[stylus-npm]: https://img.shields.io/npm/v/stylus-loader.svg
|
||||
[stylus-size]: https://packagephobia.now.sh/badge?p=stylus-loader
|
||||
[postcss-npm]: https://img.shields.io/npm/v/postcss-loader.svg
|
||||
[postcss-size]: https://packagephobia.now.sh/badge?p=postcss-loader
|
||||
|
||||
#### Linting & Testing
|
||||
|
||||
|Name|Status|Description|
|
||||
|:--:|:----:|:----------|
|
||||
|<a href="https://github.com/webpack/mocha-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/mocha.svg"></a>|![mocha-npm]|Tests with mocha (Browser/NodeJS)|
|
||||
|<a href="https://github.com/MoOx/eslint-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/eslint.svg"></a>|![eslint-npm]|PreLoader for linting code using ESLint|
|
||||
|<a href="https://github.com/webpack-contrib/jshint-loader"><img width="48" height="20.64" src="http://jshint.com/res/jshint-dark.png"></a>|![jshint-npm]|PreLoader for linting code using JSHint|
|
||||
|Name|Status|Install Size|Description|
|
||||
|:--:|:----:|:----------:|:----------|
|
||||
|<a href="https://github.com/webpack/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/MoOx/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="http://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
|
||||
[eslint-npm]: https://img.shields.io/npm/v/eslint-loader.svg
|
||||
[eslint-size]: https://packagephobia.now.sh/badge?p=eslint-loader
|
||||
[jshint-npm]: https://img.shields.io/npm/v/jshint-loader.svg
|
||||
[jshint-size]: https://packagephobia.now.sh/badge?p=jshint-loader
|
||||
[jscs-npm]: https://img.shields.io/npm/v/jscs-loader.svg
|
||||
[jscs-size]: https://packagephobia.now.sh/badge?p=jscs-loader
|
||||
|
||||
#### Frameworks
|
||||
|
||||
|Name|Status|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]|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]|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]| Loads and compiles Angular 2 Components|
|
||||
|<a href="https://github.com/riot/tag-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/riot.svg"></a>|![riot-npm]| 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/tag-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
|
||||
[polymer-npm]: https://img.shields.io/npm/v/polymer-webpack-loader.svg
|
||||
[polymer-size]: https://packagephobia.now.sh/badge?p=polymer-webpack-loader
|
||||
[angular-npm]: https://img.shields.io/npm/v/angular2-template-loader.svg
|
||||
[angular-size]: https://packagephobia.now.sh/badge?p=angular2-template-loader
|
||||
[riot-npm]: https://img.shields.io/npm/v/riot-tag-loader.svg
|
||||
[riot-size]: https://packagephobia.now.sh/badge?p=riot-tag-loader
|
||||
|
||||
### Performance
|
||||
|
||||
|
@ -287,6 +328,8 @@ We consider webpack to be a low-level tool used not only individually but also l
|
|||
|
||||
If you're just getting started, take a look at [our new docs and concepts page](https://webpack.js.org/concepts/). This has a high level overview that is great for beginners!!
|
||||
|
||||
Looking for webpack 1 docs? Please check out the old [wiki](https://github.com/webpack/docs/wiki/contents), but note that this deprecated version is no longer supported.
|
||||
|
||||
If you want to discuss something or just need help, [here is our Gitter room](https://gitter.im/webpack/webpack) where there are always individuals looking to help out!
|
||||
|
||||
If you are still having difficulty, we would love for you to post
|
||||
|
|
22
appveyor.yml
22
appveyor.yml
|
@ -9,24 +9,28 @@ branches:
|
|||
init:
|
||||
- git config --global core.autocrlf input
|
||||
|
||||
cache:
|
||||
- "..\\.yarn-cache"
|
||||
- ".jest-cache"
|
||||
|
||||
# what combinations to test
|
||||
environment:
|
||||
matrix:
|
||||
- nodejs_version: 8
|
||||
- nodejs_version: 10
|
||||
job_part: unit
|
||||
- nodejs_version: 8
|
||||
jest: --maxWorkers=2 --cacheDirectory .jest-cache
|
||||
- nodejs_version: 10
|
||||
job_part: integration
|
||||
jest: --maxWorkers=2
|
||||
jest: --maxWorkers=2 --cacheDirectory .jest-cache
|
||||
- nodejs_version: 6
|
||||
job_part: integration
|
||||
jest: --maxWorkers=2
|
||||
jest: --maxWorkers=2 --cacheDirectory .jest-cache
|
||||
|
||||
install:
|
||||
- ps: Install-Product node $env:nodejs_version x64
|
||||
- npm install yarn -g
|
||||
- yarn install --frozen-lockfile
|
||||
- yarn link --frozen-lockfile || yarn link --frozen-lockfile
|
||||
- yarn link webpack --frozen-lockfile
|
||||
- yarn --frozen-lockfile --preferred-cache-folder ..\\.yarn-cache
|
||||
- yarn link --frozen-lockfile --preferred-cache-folder ..\\.yarn-cache || yarn link --frozen-lockfile --preferred-cache-folder ..\\.yarn-cache
|
||||
- yarn link webpack --frozen-lockfile --preferred-cache-folder ..\\.yarn-cache
|
||||
|
||||
build: off
|
||||
|
||||
|
@ -38,5 +42,7 @@ test_script:
|
|||
- yarn --version
|
||||
- cmd: set JEST=%jest%
|
||||
- cmd: yarn appveyor:%job_part%
|
||||
- cmd: yarn istanbul report --report lcovonly
|
||||
- cmd: yarn unlink webpack
|
||||
- cmd: yarn global add codecov && codecov -F %job_part% --disable=gcov
|
||||
- cmd: del /F /Q .jest-cache\\haste-map* .jest-cache\\perf-cache* 2> null || Ver > null
|
||||
|
|
|
@ -14,13 +14,15 @@ const benchmarkOptions = {
|
|||
};
|
||||
|
||||
function runTimes(compiler, times, deferred) {
|
||||
fs.writeFileSync(path.join(fixtures, "0.js"), "module.exports = " + Math.random(), "utf-8");
|
||||
fs.writeFileSync(
|
||||
path.join(fixtures, "0.js"),
|
||||
"module.exports = " + Math.random(),
|
||||
"utf-8"
|
||||
);
|
||||
compiler.run(err => {
|
||||
if(err) throw err;
|
||||
if(times === 1)
|
||||
deferred.resolve();
|
||||
else
|
||||
runTimes(compiler, times - 1, deferred);
|
||||
if (err) throw err;
|
||||
if (times === 1) deferred.resolve();
|
||||
else runTimes(compiler, times - 1, deferred);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -28,103 +30,102 @@ const tests = {
|
|||
"normal build": [
|
||||
[0, 1, 5, 10, 50, 100, 200],
|
||||
(size, deferred) => {
|
||||
webpack({
|
||||
context: fixtures,
|
||||
entry: `./${size}.js`,
|
||||
output: {
|
||||
path: outputPath,
|
||||
filename: "bundle.js"
|
||||
webpack(
|
||||
{
|
||||
context: fixtures,
|
||||
entry: `./${size}.js`,
|
||||
output: {
|
||||
path: outputPath,
|
||||
filename: "bundle.js"
|
||||
}
|
||||
},
|
||||
err => {
|
||||
if (err) throw err;
|
||||
deferred.resolve();
|
||||
}
|
||||
}, err => {
|
||||
if(err) throw err;
|
||||
deferred.resolve();
|
||||
});
|
||||
);
|
||||
}
|
||||
],
|
||||
"eval dev build": [
|
||||
[0, 1, 2, 5, 10, 15],
|
||||
(size, deferred) => {
|
||||
webpack({
|
||||
context: fixtures,
|
||||
entry: `./${size}.big.js`,
|
||||
output: {
|
||||
path: outputPath,
|
||||
filename: "bundle.js"
|
||||
webpack(
|
||||
{
|
||||
context: fixtures,
|
||||
entry: `./${size}.big.js`,
|
||||
output: {
|
||||
path: outputPath,
|
||||
filename: "bundle.js"
|
||||
},
|
||||
devtool: "eval"
|
||||
},
|
||||
devtool: "eval"
|
||||
}, err => {
|
||||
if(err) throw err;
|
||||
deferred.resolve();
|
||||
});
|
||||
err => {
|
||||
if (err) throw err;
|
||||
deferred.resolve();
|
||||
}
|
||||
);
|
||||
}
|
||||
],
|
||||
"sourcemap build": [
|
||||
[0, 1, 2, 5, 10, 15],
|
||||
(size, deferred) => {
|
||||
webpack({
|
||||
context: fixtures,
|
||||
entry: `./${size}.big.js`,
|
||||
output: {
|
||||
path: outputPath,
|
||||
filename: "bundle.js"
|
||||
webpack(
|
||||
{
|
||||
context: fixtures,
|
||||
entry: `./${size}.big.js`,
|
||||
output: {
|
||||
path: outputPath,
|
||||
filename: "bundle.js"
|
||||
},
|
||||
devtool: "source-map"
|
||||
},
|
||||
devtool: "source-map"
|
||||
}, err => {
|
||||
if(err) throw err;
|
||||
deferred.resolve();
|
||||
});
|
||||
err => {
|
||||
if (err) throw err;
|
||||
deferred.resolve();
|
||||
}
|
||||
);
|
||||
}
|
||||
],
|
||||
"cheap sourcemap build": [
|
||||
[0, 1, 2, 5, 10, 15],
|
||||
(size, deferred) => {
|
||||
webpack({
|
||||
context: fixtures,
|
||||
entry: `./${size}.big.js`,
|
||||
output: {
|
||||
path: outputPath,
|
||||
filename: "bundle.js"
|
||||
webpack(
|
||||
{
|
||||
context: fixtures,
|
||||
entry: `./${size}.big.js`,
|
||||
output: {
|
||||
path: outputPath,
|
||||
filename: "bundle.js"
|
||||
},
|
||||
devtool: "cheap-source-map"
|
||||
},
|
||||
devtool: "cheap-source-map"
|
||||
}, err => {
|
||||
if(err) throw err;
|
||||
deferred.resolve();
|
||||
});
|
||||
err => {
|
||||
if (err) throw err;
|
||||
deferred.resolve();
|
||||
}
|
||||
);
|
||||
}
|
||||
],
|
||||
"build w/ chunks": [
|
||||
[0, 1, 5, 10, 50, 100, 200],
|
||||
(size, deferred) => {
|
||||
webpack({
|
||||
context: fixtures,
|
||||
entry: `./${size}.async.js`,
|
||||
output: {
|
||||
path: outputPath,
|
||||
filename: "bundle.js"
|
||||
webpack(
|
||||
{
|
||||
context: fixtures,
|
||||
entry: `./${size}.async.js`,
|
||||
output: {
|
||||
path: outputPath,
|
||||
filename: "bundle.js"
|
||||
}
|
||||
},
|
||||
err => {
|
||||
if (err) throw err;
|
||||
deferred.resolve();
|
||||
}
|
||||
}, err => {
|
||||
if(err) throw err;
|
||||
deferred.resolve();
|
||||
});
|
||||
);
|
||||
}
|
||||
],
|
||||
"build w/ chunks": [
|
||||
[0, 1, 5, 10, 50, 100, 200],
|
||||
(size, deferred) => {
|
||||
webpack({
|
||||
context: fixtures,
|
||||
entry: "./" + size + ".async.js",
|
||||
output: {
|
||||
path: outputPath,
|
||||
filename: "bundle.js"
|
||||
}
|
||||
}, err => {
|
||||
if(err) throw err;
|
||||
deferred.resolve();
|
||||
});
|
||||
}
|
||||
],
|
||||
"incremental": [
|
||||
incremental: [
|
||||
[0, 1, 5, 10, 50, 100, 200],
|
||||
(size, deferred) => {
|
||||
var compiler = webpack({
|
||||
|
@ -155,7 +156,7 @@ const tests = {
|
|||
runTimes(compiler, size, deferred);
|
||||
}
|
||||
],
|
||||
"incremental2": [
|
||||
incremental2: [
|
||||
[0, 1, 5, 10, 50, 100, 200],
|
||||
(size, deferred) => {
|
||||
var compiler = webpack({
|
||||
|
@ -170,7 +171,7 @@ const tests = {
|
|||
runTimes(compiler, 3, deferred);
|
||||
}
|
||||
],
|
||||
"incremental4": [
|
||||
incremental4: [
|
||||
[0, 1, 5, 10, 50, 100, 200],
|
||||
(size, deferred) => {
|
||||
var compiler = webpack({
|
||||
|
@ -185,7 +186,7 @@ const tests = {
|
|||
runTimes(compiler, 5, deferred);
|
||||
}
|
||||
],
|
||||
"incremental16": [
|
||||
incremental16: [
|
||||
[0, 1, 5, 10, 50, 100, 200],
|
||||
(size, deferred) => {
|
||||
var compiler = webpack({
|
||||
|
@ -199,25 +200,38 @@ const tests = {
|
|||
});
|
||||
runTimes(compiler, 17, deferred);
|
||||
}
|
||||
],
|
||||
]
|
||||
};
|
||||
|
||||
const suite = new Benchmark.Suite;
|
||||
const suite = new Benchmark.Suite();
|
||||
|
||||
Object.keys(tests).filter(name => process.argv.length > 2 ? name.includes(process.argv[2]) : true)
|
||||
Object.keys(tests)
|
||||
.filter(
|
||||
name => (process.argv.length > 2 ? name.includes(process.argv[2]) : true)
|
||||
)
|
||||
.forEach(name => {
|
||||
const test = tests[name];
|
||||
test[0].forEach(size => {
|
||||
suite.add(`${name} ${size}`, deferred => {
|
||||
test[1](size, deferred);
|
||||
}, benchmarkOptions);
|
||||
suite.add(
|
||||
`${name} ${size}`,
|
||||
deferred => {
|
||||
test[1](size, deferred);
|
||||
},
|
||||
benchmarkOptions
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
suite.on("cycle", event => {
|
||||
process.stderr.write("\n");
|
||||
const b = event.target;
|
||||
console.log(b.name + "\t" + Math.floor(1000 * (b.stats.mean - b.stats.moe)) + "\t" + Math.floor(1000 * (b.stats.mean + b.stats.moe)));
|
||||
console.log(
|
||||
b.name +
|
||||
"\t" +
|
||||
Math.floor(1000 * (b.stats.mean - b.stats.moe)) +
|
||||
"\t" +
|
||||
Math.floor(1000 * (b.stats.mean + b.stats.moe))
|
||||
);
|
||||
});
|
||||
|
||||
suite.run({
|
||||
|
|
|
@ -1,22 +1,28 @@
|
|||
const webpack = require("webpack");
|
||||
const webpack = require("../");
|
||||
const path = require("path");
|
||||
|
||||
webpack({
|
||||
context: __dirname,
|
||||
entry: "./createBenchmark/entry.js",
|
||||
output: {
|
||||
path: __dirname,
|
||||
filename: "benchmark-bundle.js"
|
||||
webpack(
|
||||
{
|
||||
context: __dirname,
|
||||
entry: "./createBenchmark/entry.js",
|
||||
output: {
|
||||
path: __dirname,
|
||||
filename: "benchmark-bundle.js"
|
||||
},
|
||||
target: "node",
|
||||
node: {
|
||||
__dirname: false
|
||||
},
|
||||
plugins: [
|
||||
new webpack.NamedModulesPlugin(),
|
||||
new webpack.IgnorePlugin(/^(fsevents|uglify-js)$/),
|
||||
new webpack.NormalModuleReplacementPlugin(
|
||||
/^.\/loadLoader$/,
|
||||
path.resolve(__dirname, "./createBenchmark/loadLoader")
|
||||
)
|
||||
]
|
||||
},
|
||||
target: "node",
|
||||
node: {
|
||||
__dirname: false
|
||||
},
|
||||
plugins: [
|
||||
new webpack.NamedModulesPlugin(),
|
||||
new webpack.IgnorePlugin(/^(fsevents|uglify-js)$/),
|
||||
new webpack.NormalModuleReplacementPlugin(/^.\/loadLoader$/, path.resolve(__dirname, "./createBenchmark/loadLoader"))
|
||||
]
|
||||
}, (err, stats) => {
|
||||
console.log(stats.toString());
|
||||
});
|
||||
(err, stats) => {
|
||||
console.log(stats.toString());
|
||||
}
|
||||
);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
const webpack = require("webpack");
|
||||
const MemoryFs = require("memory-fs");
|
||||
const webpack = require("../../");
|
||||
const path = require("path");
|
||||
|
||||
const testCase = process.argv[2];
|
||||
|
@ -15,11 +14,13 @@ const config = {
|
|||
|
||||
const compiler = webpack(config);
|
||||
compiler.run((err, stats) => {
|
||||
if(err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
} else {
|
||||
console.log(stats.toString({
|
||||
errorDetails: true
|
||||
}));
|
||||
console.log(
|
||||
stats.toString({
|
||||
errorDetails: true
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module.exports = (loader, callback) => {
|
||||
callback(new Error("Loaders are not supported"));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,55 +5,55 @@ const fixtures = path.join(__dirname, "fixtures");
|
|||
|
||||
try {
|
||||
fs.mkdirSync(fixtures);
|
||||
} catch(e) {}
|
||||
} catch (e) {
|
||||
// The directory already exists
|
||||
}
|
||||
|
||||
function generateRequireString(conditional, suffix) {
|
||||
const prefixedSuffix = suffix ? `.${suffix}` : "";
|
||||
return `require(${JSON.stringify(`./${conditional}${prefixedSuffix}.js`)});`;
|
||||
}
|
||||
|
||||
for(let i = 0; i < 10000; i++) {
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
const source = [];
|
||||
if(i > 8)
|
||||
source.push(generateRequireString((i / 8 | 0)));
|
||||
if(i > 4)
|
||||
source.push(generateRequireString((i / 4 | 0)));
|
||||
if(i > 2)
|
||||
source.push(generateRequireString((i / 2 | 0)));
|
||||
if(i > 0)
|
||||
source.push(generateRequireString((i - 1)));
|
||||
if (i > 8) source.push(generateRequireString((i / 8) | 0));
|
||||
if (i > 4) source.push(generateRequireString((i / 4) | 0));
|
||||
if (i > 2) source.push(generateRequireString((i / 2) | 0));
|
||||
if (i > 0) source.push(generateRequireString(i - 1));
|
||||
source.push("module.exports = " + i + ";");
|
||||
fs.writeFileSync(path.join(fixtures, i + ".js"), source.join("\n"), "utf-8");
|
||||
}
|
||||
|
||||
for(let i = 0; i < 10000; i++) {
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
const source = [];
|
||||
source.push("require.ensure([], function(require) {");
|
||||
if(i > 8)
|
||||
source.push(generateRequireString((i / 8 | 0), "async"));
|
||||
if(i > 4)
|
||||
source.push(generateRequireString((i / 4 | 0), "async"));
|
||||
if(i > 2)
|
||||
source.push(generateRequireString((i / 2 | 0), "async"));
|
||||
if(i > 0)
|
||||
source.push(generateRequireString((i - 1), "async"));
|
||||
if (i > 8) source.push(generateRequireString((i / 8) | 0, "async"));
|
||||
if (i > 4) source.push(generateRequireString((i / 4) | 0, "async"));
|
||||
if (i > 2) source.push(generateRequireString((i / 2) | 0, "async"));
|
||||
if (i > 0) source.push(generateRequireString(i - 1, "async"));
|
||||
source.push("});");
|
||||
source.push("module.exports = " + i + ";");
|
||||
fs.writeFileSync(path.join(fixtures, i + ".async.js"), source.join("\n"), "utf-8");
|
||||
fs.writeFileSync(
|
||||
path.join(fixtures, i + ".async.js"),
|
||||
source.join("\n"),
|
||||
"utf-8"
|
||||
);
|
||||
}
|
||||
|
||||
for(let i = 0; i < 100; i++) {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
const source = [];
|
||||
if(i > 8)
|
||||
source.push(generateRequireString((i / 8 | 0), "big"));
|
||||
if(i > 4)
|
||||
source.push(generateRequireString((i / 4 | 0), "big"));
|
||||
if(i > 2)
|
||||
source.push(generateRequireString((i / 2 | 0), "big"));
|
||||
if(i > 0)
|
||||
source.push(generateRequireString((i - 1), "big"));
|
||||
for(let j = 0; j < 300; j++)
|
||||
source.push("if(Math.random())hello.world();test.a.b.c.d();x(1,2,3,4);var a,b,c,d,e,f;");
|
||||
if (i > 8) source.push(generateRequireString((i / 8) | 0, "big"));
|
||||
if (i > 4) source.push(generateRequireString((i / 4) | 0, "big"));
|
||||
if (i > 2) source.push(generateRequireString((i / 2) | 0, "big"));
|
||||
if (i > 0) source.push(generateRequireString(i - 1, "big"));
|
||||
for (let j = 0; j < 300; j++)
|
||||
source.push(
|
||||
"if(Math.random())hello.world();test.a.b.c.d();x(1,2,3,4);var a,b,c,d,e,f;"
|
||||
);
|
||||
source.push("module.exports = " + i + ";");
|
||||
fs.writeFileSync(path.join(fixtures, i + ".big.js"), source.join("\n"), "utf-8");
|
||||
fs.writeFileSync(
|
||||
path.join(fixtures, i + ".big.js"),
|
||||
source.join("\n"),
|
||||
"utf-8"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,45 +5,57 @@ const fixtures = path.join(__dirname, "fixtures");
|
|||
|
||||
try {
|
||||
fs.mkdirSync(fixtures);
|
||||
} catch(e) {}
|
||||
} catch (e) {
|
||||
// The directory already exists
|
||||
}
|
||||
|
||||
function genModule(prefix, depth, asyncDepth, multiplex, r, circular) {
|
||||
const source = [];
|
||||
const isAsync = depth >= asyncDepth;
|
||||
if(!isAsync)
|
||||
circular.push(path.resolve(fixtures, prefix + "/index.js"));
|
||||
if (!isAsync) circular.push(path.resolve(fixtures, prefix + "/index.js"));
|
||||
source.push("(function() {");
|
||||
const m = (r % multiplex) + 1;
|
||||
let sum = 1;
|
||||
let item;
|
||||
try {
|
||||
fs.mkdirSync(path.resolve(fixtures, prefix));
|
||||
} catch(e) {}
|
||||
if(depth > 0) {
|
||||
for(let i = 0; i < m; i++) {
|
||||
sum += genModule(prefix + "/" + i, depth - 1, asyncDepth, multiplex, (r + i + depth) * m + i + depth, circular);
|
||||
} catch (e) {
|
||||
// The directory already exists
|
||||
}
|
||||
if (depth > 0) {
|
||||
for (let i = 0; i < m; i++) {
|
||||
sum += genModule(
|
||||
prefix + "/" + i,
|
||||
depth - 1,
|
||||
asyncDepth,
|
||||
multiplex,
|
||||
(r + i + depth) * m + i + depth,
|
||||
circular
|
||||
);
|
||||
source.push("require(" + JSON.stringify("./" + i) + ");");
|
||||
if(i === 0) {
|
||||
if(isAsync)
|
||||
source.push("}); require.ensure([], function() {");
|
||||
if (i === 0) {
|
||||
if (isAsync) source.push("}); require.ensure([], function() {");
|
||||
}
|
||||
}
|
||||
item = circular[r % circular.length];
|
||||
}
|
||||
source.push("}, " + JSON.stringify(prefix) + ");");
|
||||
if(item)
|
||||
source.push("require(" + JSON.stringify(item) + ");");
|
||||
if (item) source.push("require(" + JSON.stringify(item) + ");");
|
||||
source.push("module.exports = " + JSON.stringify(prefix) + ";");
|
||||
fs.writeFileSync(path.resolve(fixtures, prefix + "/index.js"), source.join("\n"), "utf-8");
|
||||
fs.writeFileSync(
|
||||
path.resolve(fixtures, prefix + "/index.js"),
|
||||
source.join("\n"),
|
||||
"utf-8"
|
||||
);
|
||||
return sum;
|
||||
}
|
||||
|
||||
for(let i = 2; i < 14; i++) {
|
||||
for (let i = 2; i < 14; i++) {
|
||||
const count = genModule("tree-" + i, 6, 100, i, 0, []);
|
||||
console.log("generated tree", i, count);
|
||||
}
|
||||
|
||||
for(let i = 2; i < 14; i++) {
|
||||
for (let i = 2; i < 14; i++) {
|
||||
const count = genModule("async-tree-" + i, 6, 1, i, 0, []);
|
||||
console.log("generated async tree", i, count);
|
||||
}
|
||||
|
|
|
@ -30,9 +30,9 @@ function c() {}
|
|||
function d() {}
|
||||
function e() {}
|
||||
function f() {}
|
||||
`
|
||||
`;
|
||||
|
||||
for(let i = 0; i < 2; i++) {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
avgJs += `(function() {${avgJs}}());`;
|
||||
}
|
||||
|
||||
|
@ -50,20 +50,33 @@ function createTree(fs, count, folder) {
|
|||
let remaining = count - 1;
|
||||
|
||||
function make(prefix, count, depth) {
|
||||
if(count === 0) {
|
||||
if (count === 0) {
|
||||
fs.writeFileSync(`${folder}/${prefix}.js`, `export default 1;\n${avgJs}`);
|
||||
} else {
|
||||
const list = [];
|
||||
for(let i = 0; i < count; i++) {
|
||||
if(remaining-- <= 0) break;
|
||||
if(depth <= 4 && i >= 3 && i <= 4) {
|
||||
list.push(`const module${i} = import("./${prefix}-${i}");\ncounter += module${i};`);
|
||||
for (let i = 0; i < count; i++) {
|
||||
if (remaining-- <= 0) break;
|
||||
if (depth <= 4 && i >= 3 && i <= 4) {
|
||||
list.push(
|
||||
`const module${i} = import("./${prefix}-${i}");\ncounter += module${i};`
|
||||
);
|
||||
} else {
|
||||
list.push(`import module${i} from "./${prefix}-${i}";\ncounter += module${i};`);
|
||||
list.push(
|
||||
`import module${i} from "./${prefix}-${i}";\ncounter += module${i};`
|
||||
);
|
||||
}
|
||||
make(`${prefix}-${i}`, depth > 4 || count > 30 ? 0 : count + depth + i ** 2, depth + 1);
|
||||
make(
|
||||
`${prefix}-${i}`,
|
||||
depth > 4 || count > 30 ? 0 : count + depth + Math.pow(i, 2),
|
||||
depth + 1
|
||||
);
|
||||
}
|
||||
fs.writeFileSync(`${folder}/${prefix}.js`, `let counter = 0;\n${list.join("\n")};\nexport default counter;\n${avgJs}`)
|
||||
fs.writeFileSync(
|
||||
`${folder}/${prefix}.js`,
|
||||
`let counter = 0;\n${list.join(
|
||||
"\n"
|
||||
)};\nexport default counter;\n${avgJs}`
|
||||
);
|
||||
}
|
||||
}
|
||||
make("index", 2, 0);
|
||||
|
|
171
bin/webpack.js
171
bin/webpack.js
|
@ -1,8 +1,16 @@
|
|||
#!/usr/bin/env node
|
||||
function runCommand(command, options) {
|
||||
|
||||
process.exitCode = 0;
|
||||
|
||||
/**
|
||||
* @param {string} command process to run
|
||||
* @param {string[]} args commandline arguments
|
||||
* @returns {Promise<void>} promise
|
||||
*/
|
||||
const runCommand = (command, args) => {
|
||||
const cp = require("child_process");
|
||||
return new Promise((resolve, reject) => {
|
||||
const executedCommand = cp.spawn(command, options, {
|
||||
const executedCommand = cp.spawn(command, args, {
|
||||
stdio: "inherit",
|
||||
shell: true
|
||||
});
|
||||
|
@ -13,69 +21,146 @@ function runCommand(command, options) {
|
|||
|
||||
executedCommand.on("exit", code => {
|
||||
if (code === 0) {
|
||||
resolve(true);
|
||||
resolve();
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let webpackCliInstalled = false;
|
||||
try {
|
||||
require.resolve("webpack-cli");
|
||||
webpackCliInstalled = true;
|
||||
} catch (err) {
|
||||
webpackCliInstalled = false;
|
||||
}
|
||||
/**
|
||||
* @param {string} packageName name of the package
|
||||
* @returns {boolean} is the package installed?
|
||||
*/
|
||||
const isInstalled = packageName => {
|
||||
try {
|
||||
require.resolve(packageName);
|
||||
|
||||
if (!webpackCliInstalled) {
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {Object} CliOption
|
||||
* @property {string} name display name
|
||||
* @property {string} package npm package name
|
||||
* @property {string} alias shortcut for choice
|
||||
* @property {boolean} installed currently installed?
|
||||
* @property {string} url homepage
|
||||
* @property {string} description description
|
||||
*/
|
||||
|
||||
/** @type {CliOption[]} */
|
||||
const CLIs = [
|
||||
{
|
||||
name: "webpack-cli",
|
||||
package: "webpack-cli",
|
||||
alias: "cli",
|
||||
installed: isInstalled("webpack-cli"),
|
||||
url: "https://github.com/webpack/webpack-cli",
|
||||
description: "The original webpack full-featured CLI."
|
||||
},
|
||||
{
|
||||
name: "webpack-command",
|
||||
package: "webpack-command",
|
||||
alias: "command",
|
||||
installed: isInstalled("webpack-command"),
|
||||
url: "https://github.com/webpack-contrib/webpack-command",
|
||||
description: "A lightweight, opinionated webpack CLI."
|
||||
}
|
||||
];
|
||||
|
||||
const installedClis = CLIs.filter(cli => cli.installed);
|
||||
|
||||
if (installedClis.length === 0) {
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const readLine = require("readline");
|
||||
|
||||
let notify =
|
||||
"One CLI for webpack must be installed. These are recommended choices, delivered as separate packages:";
|
||||
|
||||
for (const item of CLIs) {
|
||||
notify += `\n - ${item.name} (${item.url})\n ${item.description}`;
|
||||
}
|
||||
|
||||
console.error(notify);
|
||||
|
||||
const isYarn = fs.existsSync(path.resolve(process.cwd(), "yarn.lock"));
|
||||
|
||||
const packageManager = isYarn ? "yarn" : "npm";
|
||||
const options = ["install", "-D", "webpack-cli"];
|
||||
const installOptions = [isYarn ? "add" : "install", "-D"];
|
||||
|
||||
if (isYarn) {
|
||||
options[0] = "add";
|
||||
}
|
||||
console.error(
|
||||
`We will use "${packageManager}" to install the CLI via "${packageManager} ${installOptions.join(
|
||||
" "
|
||||
)}".`
|
||||
);
|
||||
|
||||
const commandToBeRun = `${packageManager} ${options.join(" ")}`;
|
||||
let question = `Which one do you like to install (${CLIs.map(
|
||||
item => item.name
|
||||
).join("/")}):\n`;
|
||||
|
||||
const question = `Would you like to install webpack-cli? (That will run ${commandToBeRun}) (yes/NO)`;
|
||||
|
||||
console.error("The CLI moved into a separate package: webpack-cli");
|
||||
const questionInterface = readLine.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout
|
||||
output: process.stderr
|
||||
});
|
||||
questionInterface.question(question, answer => {
|
||||
questionInterface.close();
|
||||
switch (answer.toLowerCase()) {
|
||||
case "y":
|
||||
case "yes":
|
||||
case "1": {
|
||||
runCommand(packageManager, options)
|
||||
.then(result => {
|
||||
return require("webpack-cli"); //eslint-disable-line
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
console.error(
|
||||
"It needs to be installed alongside webpack to use the CLI"
|
||||
);
|
||||
process.exitCode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
const normalizedAnswer = answer.toLowerCase();
|
||||
const selectedPackage = CLIs.find(item => {
|
||||
return item.name === normalizedAnswer || item.alias === normalizedAnswer;
|
||||
});
|
||||
|
||||
if (!normalizedAnswer) {
|
||||
console.error(
|
||||
"One CLI needs to be installed alongside webpack to use the CLI."
|
||||
);
|
||||
process.exitCode = 1;
|
||||
|
||||
return;
|
||||
} else if (!selectedPackage) {
|
||||
console.error(
|
||||
"No matching choice.\n" +
|
||||
"One CLI needs to be installed alongside webpack to use the CLI.\n" +
|
||||
"Try to installing your CLI of choice manually."
|
||||
);
|
||||
process.exitCode = 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const packageName = selectedPackage.package;
|
||||
|
||||
console.log(
|
||||
`Installing '${
|
||||
selectedPackage.name
|
||||
}' (running '${packageManager} ${installOptions.join(
|
||||
" "
|
||||
)} ${packageName}')...`
|
||||
);
|
||||
|
||||
runCommand(packageManager, installOptions.concat(packageName))
|
||||
.then(() => {
|
||||
require(packageName); //eslint-disable-line
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
});
|
||||
} else if (installedClis.length === 1) {
|
||||
require(installedClis[0].package); // eslint-disable-line
|
||||
} else {
|
||||
require("webpack-cli"); // eslint-disable-line
|
||||
console.warn(
|
||||
`You have installed ${installedClis
|
||||
.map(item => item.name)
|
||||
.join(
|
||||
" and "
|
||||
)} together. To work with the "webpack" command you need only one CLI package, please remove one of them or use them directly via their binary.`
|
||||
);
|
||||
}
|
||||
|
|
15
codecov.yml
15
codecov.yml
|
@ -7,6 +7,9 @@ coverage:
|
|||
status:
|
||||
project:
|
||||
default: off
|
||||
basic:
|
||||
flags: basic
|
||||
target: auto
|
||||
integration:
|
||||
flags: integration
|
||||
target: auto
|
||||
|
@ -15,6 +18,10 @@ coverage:
|
|||
target: 0%
|
||||
patch:
|
||||
default: off
|
||||
integration:
|
||||
flags: integration
|
||||
target: 90%
|
||||
base: pr
|
||||
integration:
|
||||
flags: integration
|
||||
target: 90%
|
||||
|
@ -25,6 +32,9 @@ coverage:
|
|||
base: pr
|
||||
changes:
|
||||
default: off
|
||||
basic:
|
||||
flags: basic
|
||||
target: 0%
|
||||
integration:
|
||||
flags: integration
|
||||
target: 0%
|
||||
|
@ -32,3 +42,8 @@ coverage:
|
|||
flags: unit
|
||||
target: 0%
|
||||
comment: off
|
||||
flags:
|
||||
basic:
|
||||
joined: false
|
||||
unit:
|
||||
joined: false
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
declare module "*.json";
|
||||
declare module "webpack-cli";
|
||||
|
||||
// Deprecated NodeJS API usages in Webpack
|
||||
declare namespace NodeJS {
|
||||
|
@ -8,6 +7,7 @@ declare namespace NodeJS {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
declare module "neo-async" {
|
||||
export interface Dictionary<T> {
|
||||
[key: string]: T;
|
||||
|
@ -101,27 +101,6 @@ declare module "neo-async" {
|
|||
export const forEach: typeof each;
|
||||
}
|
||||
|
||||
// There are no typings for chrome-trace-event
|
||||
declare module "chrome-trace-event" {
|
||||
interface Event {
|
||||
name: string;
|
||||
id?: number;
|
||||
cat: string[];
|
||||
args?: Object;
|
||||
}
|
||||
|
||||
export class Tracer {
|
||||
constructor(options: { noStream: boolean });
|
||||
pipe(stream: NodeJS.WritableStream): void;
|
||||
instantEvent(event: Event): void;
|
||||
counter: number;
|
||||
trace: {
|
||||
begin(event: Event): void;
|
||||
end(event: Event): void;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// There are no typings for @webassemblyjs/ast
|
||||
declare module "@webassemblyjs/ast" {
|
||||
export function traverse(
|
||||
|
@ -130,6 +109,7 @@ declare module "@webassemblyjs/ast" {
|
|||
ModuleImport?: (p: NodePath<ModuleImport>) => void;
|
||||
ModuleExport?: (p: NodePath<ModuleExport>) => void;
|
||||
Start?: (p: NodePath<Start>) => void;
|
||||
Global?: (p: NodePath<Global>) => void;
|
||||
}
|
||||
);
|
||||
export class NodePath<T> {
|
||||
|
@ -146,52 +126,98 @@ declare module "@webassemblyjs/ast" {
|
|||
module: string;
|
||||
descr: {
|
||||
type: string;
|
||||
valtype: string;
|
||||
id: string;
|
||||
valtype?: string;
|
||||
id?: Identifier;
|
||||
signature?: Signature;
|
||||
};
|
||||
name: string;
|
||||
}
|
||||
export class ModuleExport extends Node {
|
||||
name: string;
|
||||
descr: ModuleExportDescr;
|
||||
}
|
||||
type Index = Identifier | NumberLiteral;
|
||||
export class ModuleExportDescr extends Node {
|
||||
type: string;
|
||||
exportType: string;
|
||||
id: Index;
|
||||
}
|
||||
export class NumberLiteral extends Node {
|
||||
value: number;
|
||||
raw: string;
|
||||
}
|
||||
export class FloatLiteral extends Node {}
|
||||
export class GlobalType extends Node {
|
||||
valtype: string;
|
||||
}
|
||||
export class Global extends Node {
|
||||
init: Instruction[];
|
||||
globalType: GlobalType;
|
||||
}
|
||||
export class FuncParam extends Node {
|
||||
valtype: string;
|
||||
}
|
||||
export class Instruction extends Node {
|
||||
id: string;
|
||||
args: NumberLiteral[];
|
||||
}
|
||||
export class IndexLiteral extends Node {}
|
||||
export class NumberLiteral extends Node {}
|
||||
export class Global extends Node {}
|
||||
export class FuncParam extends Node {}
|
||||
export class Instruction extends Node {}
|
||||
export class CallInstruction extends Instruction {}
|
||||
export class ObjectInstruction extends Instruction {}
|
||||
export class Func extends Node {
|
||||
signature: Signature;
|
||||
}
|
||||
export class Signature {
|
||||
params: any;
|
||||
result: any;
|
||||
type: "Signature";
|
||||
params: FuncParam[];
|
||||
results: string[];
|
||||
}
|
||||
export class TypeInstructionFunc extends Node {}
|
||||
export class TypeInstruction extends Node {}
|
||||
export class IndexInFuncSection extends Node {}
|
||||
export function indexLiteral(index: number): IndexLiteral;
|
||||
export function numberLiteral(num: number): NumberLiteral;
|
||||
export function indexLiteral(index: number): Index;
|
||||
export function numberLiteralFromRaw(num: number): NumberLiteral;
|
||||
export function floatLiteral(
|
||||
value: number,
|
||||
nan?: boolean,
|
||||
inf?: boolean,
|
||||
raw?: string
|
||||
): FloatLiteral;
|
||||
export function global(globalType: string, nodes: Node[]): Global;
|
||||
export function identifier(indentifier: string): Identifier;
|
||||
export function funcParam(valType: string, id: Identifier): FuncParam;
|
||||
export function instruction(inst: string, args: Node[]): Instruction;
|
||||
export function callInstruction(funcIndex: IndexLiteral): CallInstruction;
|
||||
export function callInstruction(funcIndex: Index): CallInstruction;
|
||||
export function objectInstruction(
|
||||
kind: string,
|
||||
type: string,
|
||||
init: Node[]
|
||||
): ObjectInstruction;
|
||||
export function func(initFuncId, funcParams, funcResults, funcBody): Func;
|
||||
export function typeInstructionFunc(params, result): TypeInstructionFunc;
|
||||
export function indexInFuncSection(index: IndexLiteral): IndexInFuncSection;
|
||||
export function signature(params: FuncParam[], results: string[]): Signature;
|
||||
export function func(initFuncId, signature: Signature, funcBody): Func;
|
||||
export function typeInstruction(
|
||||
id: Identifier,
|
||||
functype: Signature
|
||||
): TypeInstruction;
|
||||
export function indexInFuncSection(index: Index): IndexInFuncSection;
|
||||
export function moduleExport(
|
||||
identifier: string,
|
||||
type: string,
|
||||
index: IndexLiteral
|
||||
descr: ModuleExportDescr
|
||||
): ModuleExport;
|
||||
export function moduleExportDescr(
|
||||
type: string,
|
||||
index: Index
|
||||
): ModuleExportDescr;
|
||||
|
||||
export function getSectionMetadata(ast: any, section: string);
|
||||
export class FuncSignature {
|
||||
args: string[];
|
||||
result: string[];
|
||||
}
|
||||
|
||||
// Node matcher
|
||||
export function isGlobalType(n: Node): boolean;
|
||||
export function isTable(n: Node): boolean;
|
||||
export function isMemory(n: Node): boolean;
|
||||
export function isFuncImportDescr(n: Node): boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -120,8 +120,9 @@
|
|||
If you think an example is missing, please report it as issue. :)
|
||||
|
||||
# Building an Example
|
||||
1. Run `npm install` in the root of the project.
|
||||
2. Run `npm link webpack` in the root of the project.
|
||||
3. Run `node build.js` in the specific example directory. (Ex: `cd examples/commonjs && node build.js`)
|
||||
1. Run `yarn` in the root of the project.
|
||||
2. Run `yarn link webpack` in the root of the project.
|
||||
3. Run `yarn add --dev webpack-cli` in the root of the project.
|
||||
4. Run `node build.js` in the specific example directory. (Ex: `cd examples/commonjs && node build.js`)
|
||||
|
||||
Note: To build all examples run `npm run build:examples`
|
||||
|
|
|
@ -259,7 +259,7 @@ function webpackContext(req) {
|
|||
function webpackContextResolve(req) {
|
||||
var id = map[req];
|
||||
if(!(id + 1)) { // check for number or string
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
}
|
||||
|
|
|
@ -259,7 +259,7 @@ function webpackContext(req) {
|
|||
function webpackContextResolve(req) {
|
||||
var id = map[req];
|
||||
if(!(id + 1)) { // check for number or string
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
}
|
||||
|
|
|
@ -248,7 +248,7 @@ function webpackAsyncContext(req) {
|
|||
var ids = map[req];
|
||||
if(!ids) {
|
||||
return Promise.resolve().then(function() {
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
});
|
||||
|
|
|
@ -275,7 +275,7 @@ function webpackAsyncContext(req) {
|
|||
var ids = map[req];
|
||||
if(!ids) {
|
||||
return Promise.resolve().then(function() {
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
});
|
||||
|
|
|
@ -264,7 +264,7 @@ function webpackAsyncContext(req) {
|
|||
var ids = map[req];
|
||||
if(!ids) {
|
||||
return Promise.resolve().then(function() {
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
});
|
||||
|
|
|
@ -256,7 +256,7 @@ function webpackAsyncContext(req) {
|
|||
var ids = map[req];
|
||||
if(!ids) {
|
||||
return Promise.resolve().then(function() {
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
This is the vendor build part.
|
||||
|
||||
It's built separately from the app part. The vendors dll is only built when vendors has changed and not while the normal development cycle.
|
||||
It's built separately from the app part. The vendors dll is only built when the array of vendors has changed and not during the normal development cycle.
|
||||
|
||||
The DllPlugin in combination with the `output.library` option exposes the internal require function as global variable in the target environment.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
This is the vendor build part.
|
||||
|
||||
It's built separately from the app part. The vendors dll is only built when vendors has changed and not while the normal development cycle.
|
||||
It's built separately from the app part. The vendors dll is only built when the array of vendors has changed and not during the normal development cycle.
|
||||
|
||||
The DllPlugin in combination with the `output.library` option exposes the internal require function as global variable in the target environment.
|
||||
|
||||
|
|
|
@ -0,0 +1,282 @@
|
|||
# Dll scope hoisting
|
||||
|
||||
[DllPlugin documentation](https://webpack.js.org/plugins/dll-plugin)
|
||||
|
||||
This example demonstrates the usage of `entryOnly` option in combination with module concatenation / scope hoisting.
|
||||
|
||||
By default `DllPlugin` exposes all the modules referenced in the bundle as separate entries.
|
||||
The manifest includes the individual modules available for use by `DllReferencePlugin`.
|
||||
Since all the modules are being accounted for, this prevents advanced optimizations such as tree shaking.
|
||||
|
||||
The `entryOnly` flag tells `DllPlugin` to only expose the modules which are configured as entry points;
|
||||
this affects both the manifest and the resulting bundle.
|
||||
Since some of the modules are no longer included in the "public contract" of the Dll,
|
||||
they can be optimized by merging (concatenating) multiple modules together or removing unused code.
|
||||
This allows to take advantage of tree shaking (scope hoisting and dead code removal) optimizations.
|
||||
|
||||
In this example only `example.js` module is exposed, since it's the entry point.
|
||||
Modules `a.js` and `b.js` are concatenated into `example.js`.
|
||||
Module `cjs.js` is left as is, since it's in CommonJS format.
|
||||
|
||||
The manifest includes `example.js` as the only exposed module and lists the exports as `["a","b","c"]`
|
||||
from the corresponding modules `a.js`, `b.js` and `cjs.js`. None of the other modules are exposed.
|
||||
|
||||
Also see [tree shaking](https://github.com/webpack/webpack/tree/master/examples/harmony-unused)
|
||||
and [scope hoisting example](https://github.com/webpack/webpack/tree/master/examples/scope-hoisting).
|
||||
|
||||
|
||||
# example.js
|
||||
|
||||
``` javascript
|
||||
export { a, b } from "./a";
|
||||
export { c } from "./cjs";
|
||||
```
|
||||
|
||||
# webpack.config.js
|
||||
|
||||
``` javascript
|
||||
var path = require("path");
|
||||
var webpack = require("../../");
|
||||
|
||||
module.exports = {
|
||||
// mode: "development" || "production",
|
||||
entry: {
|
||||
dll: ["./example"]
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, "dist"),
|
||||
filename: "[name].js",
|
||||
library: "[name]_[hash]"
|
||||
},
|
||||
optimization: {
|
||||
concatenateModules: true // this is enabled by default in production mode
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DllPlugin({
|
||||
path: path.join(__dirname, "dist", "[name]-manifest.json"),
|
||||
name: "[name]_[hash]",
|
||||
entryOnly: true
|
||||
})
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
# dist/dll.js
|
||||
|
||||
``` javascript
|
||||
var dll_3392692e94d8b928900f =
|
||||
```
|
||||
<details><summary><code>/******/ (function(modules) { /* webpackBootstrap */ })</code></summary>
|
||||
|
||||
``` js
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, {
|
||||
/******/ configurable: false,
|
||||
/******/ enumerable: true,
|
||||
/******/ get: getter
|
||||
/******/ });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // define __esModule on exports
|
||||
/******/ __webpack_require__.r = function(exports) {
|
||||
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "dist/";
|
||||
/******/
|
||||
/******/
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(__webpack_require__.s = 0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
``` js
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/*!***************!*\
|
||||
!*** dll dll ***!
|
||||
\***************/
|
||||
/*! no static exports found */
|
||||
/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
module.exports = __webpack_require__;
|
||||
|
||||
/***/ }),
|
||||
/* 1 */
|
||||
/*!****************!*\
|
||||
!*** ./cjs.js ***!
|
||||
\****************/
|
||||
/*! no static exports found */
|
||||
/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
// module cjs (commonjs)
|
||||
exports.c = "c";
|
||||
|
||||
|
||||
/***/ }),
|
||||
/* 2 */
|
||||
/*!********************************!*\
|
||||
!*** ./example.js + 2 modules ***!
|
||||
\********************************/
|
||||
/*! exports provided: a, b, c */
|
||||
/*! ModuleConcatenation bailout: Cannot concat with ./cjs.js (<- Module is not an ECMAScript module) */
|
||||
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
// CONCATENATED MODULE: ./b.js
|
||||
// module b
|
||||
function b() {
|
||||
return "b";
|
||||
}
|
||||
|
||||
// CONCATENATED MODULE: ./a.js
|
||||
// module a
|
||||
var a = "a";
|
||||
|
||||
|
||||
// EXTERNAL MODULE: ./cjs.js
|
||||
var cjs = __webpack_require__(1);
|
||||
|
||||
// CONCATENATED MODULE: ./example.js
|
||||
/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, "a", function() { return a; });
|
||||
/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, "b", function() { return b; });
|
||||
/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, "c", function() { return cjs["c"]; });
|
||||
|
||||
|
||||
|
||||
|
||||
/***/ })
|
||||
/******/ ]);
|
||||
```
|
||||
|
||||
# dist/dll-manifest.json
|
||||
|
||||
``` javascript
|
||||
{"name":"dll_3392692e94d8b928900f","content":{"./example.js":{"id":2,"buildMeta":{"exportsType":"namespace","providedExports":["a","b","c"]}}}}
|
||||
```
|
||||
|
||||
# Info
|
||||
|
||||
## Unoptimized
|
||||
|
||||
```
|
||||
Hash: 0a1b2c3d4e5f6a7b8c9d
|
||||
Version: webpack 4.8.3
|
||||
Asset Size Chunks Chunk Names
|
||||
dll.js 4.01 KiB 0 [emitted] dll
|
||||
Entrypoint dll = dll.js
|
||||
chunk {0} dll.js (dll) 216 bytes [entry] [rendered]
|
||||
> dll
|
||||
[0] dll dll 12 bytes {0} [built]
|
||||
dll entry
|
||||
[1] ./cjs.js 42 bytes {0} [built]
|
||||
harmony side effect evaluation ./cjs [2] ./example.js + 2 modules 2:0-26
|
||||
harmony export imported specifier ./cjs [2] ./example.js + 2 modules 2:0-26
|
||||
[2] ./example.js + 2 modules 162 bytes {0} [built]
|
||||
[exports: a, b, c]
|
||||
single entry ./example [0] dll dll dll:0
|
||||
| ./example.js 55 bytes [built]
|
||||
| [exports: a, b, c]
|
||||
| single entry ./example [0] dll dll dll:0
|
||||
| ./a.js 53 bytes [built]
|
||||
| [exports: a, b]
|
||||
| harmony side effect evaluation ./a ./example.js 1:0-27
|
||||
| harmony export imported specifier ./a ./example.js 1:0-27
|
||||
| harmony export imported specifier ./a ./example.js 1:0-27
|
||||
| ./b.js 49 bytes [built]
|
||||
| [exports: b]
|
||||
| harmony side effect evaluation ./b ./a.js 3:0-20
|
||||
| harmony export imported specifier ./b ./a.js 3:0-20
|
||||
```
|
||||
|
||||
## Production mode
|
||||
|
||||
```
|
||||
Hash: 0a1b2c3d4e5f6a7b8c9d
|
||||
Version: webpack 4.8.3
|
||||
Asset Size Chunks Chunk Names
|
||||
dll.js 791 bytes 0 [emitted] dll
|
||||
Entrypoint dll = dll.js
|
||||
chunk {0} dll.js (dll) 216 bytes [entry] [rendered]
|
||||
> dll
|
||||
[0] ./cjs.js 42 bytes {0} [built]
|
||||
[only some exports used: c]
|
||||
harmony side effect evaluation ./cjs [1] ./example.js + 2 modules 2:0-26
|
||||
harmony export imported specifier ./cjs [1] ./example.js + 2 modules 2:0-26
|
||||
[1] ./example.js + 2 modules 162 bytes {0} [built]
|
||||
[exports: a, b, c]
|
||||
single entry ./example [2] dll dll dll:0
|
||||
| ./example.js 55 bytes [built]
|
||||
| [exports: a, b, c]
|
||||
| single entry ./example [2] dll dll dll:0
|
||||
| ./a.js 53 bytes [built]
|
||||
| [exports: a, b]
|
||||
| [all exports used]
|
||||
| harmony side effect evaluation ./a ./example.js 1:0-27
|
||||
| harmony export imported specifier ./a ./example.js 1:0-27
|
||||
| harmony export imported specifier ./a ./example.js 1:0-27
|
||||
| ./b.js 49 bytes [built]
|
||||
| [exports: b]
|
||||
| [all exports used]
|
||||
| harmony side effect evaluation ./b ./a.js 3:0-20
|
||||
| harmony export imported specifier ./b ./a.js 3:0-20
|
||||
[2] dll dll 12 bytes {0} [built]
|
||||
dll entry
|
||||
```
|
|
@ -0,0 +1,3 @@
|
|||
// module a
|
||||
export var a = "a";
|
||||
export * from "./b";
|
|
@ -0,0 +1,4 @@
|
|||
// module b
|
||||
export function b() {
|
||||
return "b";
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
global.NO_TARGET_ARGS = true;
|
||||
require("../build-common");
|
|
@ -0,0 +1,2 @@
|
|||
// module cjs (commonjs)
|
||||
exports.c = "c";
|
|
@ -0,0 +1,2 @@
|
|||
export { a, b } from "./a";
|
||||
export { c } from "./cjs";
|
|
@ -0,0 +1,64 @@
|
|||
# Dll scope hoisting
|
||||
|
||||
[DllPlugin documentation](https://webpack.js.org/plugins/dll-plugin)
|
||||
|
||||
This example demonstrates the usage of `entryOnly` option in combination with module concatenation / scope hoisting.
|
||||
|
||||
By default `DllPlugin` exposes all the modules referenced in the bundle as separate entries.
|
||||
The manifest includes the individual modules available for use by `DllReferencePlugin`.
|
||||
Since all the modules are being accounted for, this prevents advanced optimizations such as tree shaking.
|
||||
|
||||
The `entryOnly` flag tells `DllPlugin` to only expose the modules which are configured as entry points;
|
||||
this affects both the manifest and the resulting bundle.
|
||||
Since some of the modules are no longer included in the "public contract" of the Dll,
|
||||
they can be optimized by merging (concatenating) multiple modules together or removing unused code.
|
||||
This allows to take advantage of tree shaking (scope hoisting and dead code removal) optimizations.
|
||||
|
||||
In this example only `example.js` module is exposed, since it's the entry point.
|
||||
Modules `a.js` and `b.js` are concatenated into `example.js`.
|
||||
Module `cjs.js` is left as is, since it's in CommonJS format.
|
||||
|
||||
The manifest includes `example.js` as the only exposed module and lists the exports as `["a","b","c"]`
|
||||
from the corresponding modules `a.js`, `b.js` and `cjs.js`. None of the other modules are exposed.
|
||||
|
||||
Also see [tree shaking](https://github.com/webpack/webpack/tree/master/examples/harmony-unused)
|
||||
and [scope hoisting example](https://github.com/webpack/webpack/tree/master/examples/scope-hoisting).
|
||||
|
||||
|
||||
# example.js
|
||||
|
||||
``` javascript
|
||||
{{example.js}}
|
||||
```
|
||||
|
||||
# webpack.config.js
|
||||
|
||||
``` javascript
|
||||
{{webpack.config.js}}
|
||||
```
|
||||
|
||||
# dist/dll.js
|
||||
|
||||
``` javascript
|
||||
{{dist/dll.js}}
|
||||
```
|
||||
|
||||
# dist/dll-manifest.json
|
||||
|
||||
``` javascript
|
||||
{{dist/dll-manifest.json}}
|
||||
```
|
||||
|
||||
# Info
|
||||
|
||||
## Unoptimized
|
||||
|
||||
```
|
||||
{{stdout}}
|
||||
```
|
||||
|
||||
## Production mode
|
||||
|
||||
```
|
||||
{{production:stdout}}
|
||||
```
|
|
@ -0,0 +1,24 @@
|
|||
var path = require("path");
|
||||
var webpack = require("../../");
|
||||
|
||||
module.exports = {
|
||||
// mode: "development" || "production",
|
||||
entry: {
|
||||
dll: ["./example"]
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, "dist"),
|
||||
filename: "[name].js",
|
||||
library: "[name]_[hash]"
|
||||
},
|
||||
optimization: {
|
||||
concatenateModules: true // this is enabled by default in production mode
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DllPlugin({
|
||||
path: path.join(__dirname, "dist", "[name]-manifest.json"),
|
||||
name: "[name]_[hash]",
|
||||
entryOnly: true
|
||||
})
|
||||
]
|
||||
};
|
|
@ -153,7 +153,7 @@ function webpackAsyncContext(req) {
|
|||
var ids = map[req];
|
||||
if(!ids) {
|
||||
return Promise.resolve().then(function() {
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
});
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
# Info
|
||||
|
||||
This example illustrates webpack's algorthim for automatic deduplication using `optimization.splitChunks`.
|
||||
|
||||
This example application contains 7 pages, each of them importing 1-3 modules from the `node_modules` folder (vendor libs) and 0-3 modules from the `stuff` folder (application modules). In reallity 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.
|
||||
|
||||
# Interpreting the result
|
||||
|
||||
* `pageA.js` the normal output files for the entrypoint `pageA`
|
||||
* `vendors~pageD~pageE~pageF~pageG.js` vendor libs shared by these pages extracted into a separate output file when larger then the threshold in size
|
||||
* `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.
|
||||
|
||||
Some modules are intentially 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.
|
||||
|
||||
## webpack.config.js
|
||||
|
||||
```
|
||||
module.exports = {
|
||||
// mode: "development || "production",
|
||||
entry: {
|
||||
pageA: "./pages/a",
|
||||
pageB: "./pages/b",
|
||||
pageC: "./pages/c",
|
||||
pageD: "./pages/d",
|
||||
pageE: "./pages/e",
|
||||
pageF: "./pages/f",
|
||||
pageG: "./pages/g"
|
||||
},
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
chunks: "all",
|
||||
maxInitialRequests: 20, // for HTTP2
|
||||
maxAsyncRequests: 20, // for HTTP2
|
||||
minSize: 40 // for example only: choosen to match 2 modules
|
||||
// omit minSize in real use case to use the default of 30kb
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Production mode
|
||||
|
||||
```
|
||||
Hash: 0a1b2c3d4e5f6a7b8c9d
|
||||
Version: webpack 4.8.3
|
||||
Asset Size Chunks Chunk Names
|
||||
pageG.js 1.15 KiB 7 [emitted] pageG
|
||||
vendors~pageD~pageE~pageF~pageG.js 119 bytes 0 [emitted] vendors~pageD~pageE~pageF~pageG
|
||||
vendors~pageD~pageE~pageF.js 178 bytes 2 [emitted] vendors~pageD~pageE~pageF
|
||||
vendors~pageA~pageB~pageC.js 180 bytes 3 [emitted] vendors~pageA~pageB~pageC
|
||||
vendors~pageC.js 121 bytes 4 [emitted] vendors~pageC
|
||||
vendors~pageB.js 121 bytes 5 [emitted] vendors~pageB
|
||||
vendors~pageA.js 121 bytes 6 [emitted] vendors~pageA
|
||||
pageA~pageD~pageF.js 156 bytes 1 [emitted] pageA~pageD~pageF
|
||||
pageF.js 1.18 KiB 8 [emitted] pageF
|
||||
pageE.js 1.17 KiB 9 [emitted] pageE
|
||||
pageD.js 1.18 KiB 10 [emitted] pageD
|
||||
pageC.js 1.27 KiB 11 [emitted] pageC
|
||||
pageB.js 1.27 KiB 12 [emitted] pageB
|
||||
pageA.js 1.18 KiB 13 [emitted] pageA
|
||||
Entrypoint pageA = vendors~pageA~pageB~pageC.js vendors~pageA.js pageA~pageD~pageF.js pageA.js
|
||||
Entrypoint pageB = vendors~pageA~pageB~pageC.js vendors~pageB.js pageB.js
|
||||
Entrypoint pageC = vendors~pageA~pageB~pageC.js vendors~pageC.js pageC.js
|
||||
Entrypoint pageD = vendors~pageD~pageE~pageF~pageG.js vendors~pageD~pageE~pageF.js pageA~pageD~pageF.js pageD.js
|
||||
Entrypoint pageE = vendors~pageD~pageE~pageF~pageG.js vendors~pageD~pageE~pageF.js pageE.js
|
||||
Entrypoint pageF = vendors~pageD~pageE~pageF~pageG.js vendors~pageD~pageE~pageF.js pageA~pageD~pageF.js pageF.js
|
||||
Entrypoint pageG = vendors~pageD~pageE~pageF~pageG.js pageG.js
|
||||
chunk {0} vendors~pageD~pageE~pageF~pageG.js (vendors~pageD~pageE~pageF~pageG) 43 bytes ={1}= ={10}= ={2}= ={7}= ={8}= ={9}= [initial] [rendered] split chunk (cache group: vendors) (name: vendors~pageD~pageE~pageF~pageG)
|
||||
> ./pages/d pageD
|
||||
> ./pages/e pageE
|
||||
> ./pages/f pageF
|
||||
> ./pages/g pageG
|
||||
1 module
|
||||
chunk {1} pageA~pageD~pageF.js (pageA~pageD~pageF) 62 bytes ={0}= ={10}= ={13}= ={2}= ={3}= ={6}= ={8}= [initial] [rendered] split chunk (cache group: default) (name: pageA~pageD~pageF)
|
||||
> ./pages/a pageA
|
||||
> ./pages/d pageD
|
||||
> ./pages/f pageF
|
||||
[6] ./stuff/s3.js 31 bytes {1} [built]
|
||||
[7] ./stuff/s2.js 31 bytes {1} [built]
|
||||
chunk {2} vendors~pageD~pageE~pageF.js (vendors~pageD~pageE~pageF) 86 bytes ={0}= ={1}= ={10}= ={8}= ={9}= [initial] [rendered] split chunk (cache group: vendors) (name: vendors~pageD~pageE~pageF)
|
||||
> ./pages/d pageD
|
||||
> ./pages/e pageE
|
||||
> ./pages/f pageF
|
||||
2 modules
|
||||
chunk {3} vendors~pageA~pageB~pageC.js (vendors~pageA~pageB~pageC) 86 bytes ={1}= ={11}= ={12}= ={13}= ={4}= ={5}= ={6}= [initial] [rendered] split chunk (cache group: vendors) (name: vendors~pageA~pageB~pageC)
|
||||
> ./pages/a pageA
|
||||
> ./pages/b pageB
|
||||
> ./pages/c pageC
|
||||
2 modules
|
||||
chunk {4} vendors~pageC.js (vendors~pageC) 43 bytes ={11}= ={3}= [initial] [rendered] split chunk (cache group: vendors) (name: vendors~pageC)
|
||||
> ./pages/c pageC
|
||||
1 module
|
||||
chunk {5} vendors~pageB.js (vendors~pageB) 43 bytes ={12}= ={3}= [initial] [rendered] split chunk (cache group: vendors) (name: vendors~pageB)
|
||||
> ./pages/b pageB
|
||||
1 module
|
||||
chunk {6} vendors~pageA.js (vendors~pageA) 43 bytes ={1}= ={13}= ={3}= [initial] [rendered] split chunk (cache group: vendors) (name: vendors~pageA)
|
||||
> ./pages/a pageA
|
||||
1 module
|
||||
chunk {7} pageG.js (pageG) 70 bytes ={0}= [entry] [rendered]
|
||||
> ./pages/g pageG
|
||||
[0] ./stuff/s1.js 31 bytes {7} {8} {10} {12} [built]
|
||||
[10] ./pages/g.js 39 bytes {7} [built]
|
||||
chunk {8} pageF.js (pageF) 144 bytes ={0}= ={1}= ={2}= [entry] [rendered]
|
||||
> ./pages/f pageF
|
||||
[0] ./stuff/s1.js 31 bytes {7} {8} {10} {12} [built]
|
||||
[11] ./pages/f.js 113 bytes {8} [built]
|
||||
chunk {9} pageE.js (pageE) 98 bytes ={0}= ={2}= [entry] [rendered]
|
||||
> ./pages/e pageE
|
||||
[4] ./stuff/s7.js 31 bytes {9} {12} [built]
|
||||
[12] ./pages/e.js 67 bytes {9} [built]
|
||||
chunk {10} pageD.js (pageD) 144 bytes ={0}= ={1}= ={2}= [entry] [rendered]
|
||||
> ./pages/d pageD
|
||||
[0] ./stuff/s1.js 31 bytes {7} {8} {10} {12} [built]
|
||||
[13] ./pages/d.js 113 bytes {10} [built]
|
||||
chunk {11} pageC.js (pageC) 206 bytes ={3}= ={4}= [entry] [rendered]
|
||||
> ./pages/c pageC
|
||||
[5] ./stuff/s4.js 31 bytes {11} {13} [built]
|
||||
[14] ./stuff/s6.js 31 bytes {11} [built]
|
||||
[15] ./stuff/s5.js 31 bytes {11} [built]
|
||||
[17] ./pages/c.js 113 bytes {11} [built]
|
||||
chunk {12} pageB.js (pageB) 206 bytes ={3}= ={5}= [entry] [rendered]
|
||||
> ./pages/b pageB
|
||||
[0] ./stuff/s1.js 31 bytes {7} {8} {10} {12} [built]
|
||||
[4] ./stuff/s7.js 31 bytes {9} {12} [built]
|
||||
[18] ./stuff/s8.js 31 bytes {12} [built]
|
||||
[20] ./pages/b.js 113 bytes {12} [built]
|
||||
chunk {13} pageA.js (pageA) 144 bytes ={1}= ={3}= ={6}= [entry] [rendered]
|
||||
> ./pages/a pageA
|
||||
[5] ./stuff/s4.js 31 bytes {11} {13} [built]
|
||||
[22] ./pages/a.js 113 bytes {13} [built]
|
||||
```
|
|
@ -0,0 +1,3 @@
|
|||
global.NO_TARGET_ARGS = true;
|
||||
global.NO_REASONS = true;
|
||||
require("../build-common");
|
|
@ -0,0 +1 @@
|
|||
console.log("a module installed from npm");
|
|
@ -0,0 +1 @@
|
|||
console.log("a module installed from npm");
|
|
@ -0,0 +1 @@
|
|||
console.log("a module installed from npm");
|
|
@ -0,0 +1 @@
|
|||
console.log("a module installed from npm");
|
|
@ -0,0 +1 @@
|
|||
console.log("a module installed from npm");
|
|
@ -0,0 +1 @@
|
|||
console.log("a module installed from npm");
|
|
@ -0,0 +1 @@
|
|||
console.log("a module installed from npm");
|
|
@ -0,0 +1 @@
|
|||
console.log("a module installed from npm");
|
|
@ -0,0 +1,7 @@
|
|||
import "m1";
|
||||
import "m2";
|
||||
import "m3";
|
||||
|
||||
import "../stuff/s2";
|
||||
import "../stuff/s3";
|
||||
import "../stuff/s4";
|
|
@ -0,0 +1,7 @@
|
|||
import "m1";
|
||||
import "m2";
|
||||
import "m4";
|
||||
|
||||
import "../stuff/s1";
|
||||
import "../stuff/s7";
|
||||
import "../stuff/s8";
|
|
@ -0,0 +1,7 @@
|
|||
import "m1";
|
||||
import "m2";
|
||||
import "m5";
|
||||
|
||||
import "../stuff/s4";
|
||||
import "../stuff/s5";
|
||||
import "../stuff/s6";
|
|
@ -0,0 +1,7 @@
|
|||
import "m6";
|
||||
import "m7";
|
||||
import "m8";
|
||||
|
||||
import "../stuff/s1";
|
||||
import "../stuff/s2";
|
||||
import "../stuff/s3";
|
|
@ -0,0 +1,5 @@
|
|||
import "m6";
|
||||
import "m7";
|
||||
import "m8";
|
||||
|
||||
import "../stuff/s7";
|
|
@ -0,0 +1,7 @@
|
|||
import "m6";
|
||||
import "m7";
|
||||
import "m8";
|
||||
|
||||
import "../stuff/s1";
|
||||
import "../stuff/s2";
|
||||
import "../stuff/s3";
|
|
@ -0,0 +1,3 @@
|
|||
import "m6";
|
||||
|
||||
import "../stuff/s1";
|
|
@ -0,0 +1 @@
|
|||
console.log("some own module");
|
|
@ -0,0 +1 @@
|
|||
console.log("some own module");
|
|
@ -0,0 +1 @@
|
|||
console.log("some own module");
|
|
@ -0,0 +1 @@
|
|||
console.log("some own module");
|
|
@ -0,0 +1 @@
|
|||
console.log("some own module");
|
|
@ -0,0 +1 @@
|
|||
console.log("some own module");
|
|
@ -0,0 +1 @@
|
|||
console.log("some own module");
|
|
@ -0,0 +1 @@
|
|||
console.log("some own module");
|
|
@ -0,0 +1,35 @@
|
|||
# Info
|
||||
|
||||
This example illustrates webpack's algorthim for automatic deduplication using `optimization.splitChunks`.
|
||||
|
||||
This example application contains 7 pages, each of them importing 1-3 modules from the `node_modules` folder (vendor libs) and 0-3 modules from the `stuff` folder (application modules). In reallity 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.
|
||||
|
||||
# Interpreting the result
|
||||
|
||||
* `pageA.js` the normal output files for the entrypoint `pageA`
|
||||
* `vendors~pageD~pageE~pageF~pageG.js` vendor libs shared by these pages extracted into a separate output file when larger then the threshold in size
|
||||
* `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.
|
||||
|
||||
Some modules are intentially 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.
|
||||
|
||||
## webpack.config.js
|
||||
|
||||
```
|
||||
{{webpack.config.js}}
|
||||
```
|
||||
|
||||
## Production mode
|
||||
|
||||
```
|
||||
{{production:stdout}}
|
||||
```
|
|
@ -0,0 +1,21 @@
|
|||
module.exports = {
|
||||
// mode: "development || "production",
|
||||
entry: {
|
||||
pageA: "./pages/a",
|
||||
pageB: "./pages/b",
|
||||
pageC: "./pages/c",
|
||||
pageD: "./pages/d",
|
||||
pageE: "./pages/e",
|
||||
pageF: "./pages/f",
|
||||
pageG: "./pages/g"
|
||||
},
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
chunks: "all",
|
||||
maxInitialRequests: 20, // for HTTP2
|
||||
maxAsyncRequests: 20, // for HTTP2
|
||||
minSize: 40 // for example only: choosen to match 2 modules
|
||||
// omit minSize in real use case to use the default of 30kb
|
||||
}
|
||||
}
|
||||
};
|
|
@ -357,7 +357,7 @@ function webpackContext(req) {
|
|||
function webpackContextResolve(req) {
|
||||
var id = map[req];
|
||||
if(!(id + 1)) { // check for number or string
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ function webpackContext(req) {
|
|||
function webpackContextResolve(req) {
|
||||
var id = map[req];
|
||||
if(!(id + 1)) { // check for number or string
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
}
|
||||
|
|
|
@ -284,7 +284,7 @@ function webpackContext(req) {
|
|||
function webpackContextResolve(req) {
|
||||
var id = map[req];
|
||||
if(!(id + 1)) { // check for number or string
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
}
|
||||
|
|
|
@ -8,11 +8,21 @@
|
|||
const { ConcatSource } = require("webpack-sources");
|
||||
const Template = require("./Template");
|
||||
|
||||
/** @typedef {import("./Compilation")} Compilation */
|
||||
|
||||
class AmdMainTemplatePlugin {
|
||||
/**
|
||||
* @param {string} name the library name
|
||||
*/
|
||||
constructor(name) {
|
||||
/** @type {string} */
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Compilation} compilation the compilation instance
|
||||
* @returns {void}
|
||||
*/
|
||||
apply(compilation) {
|
||||
const { mainTemplate, chunkTemplate } = compilation;
|
||||
|
||||
|
@ -61,7 +71,9 @@ class AmdMainTemplatePlugin {
|
|||
}
|
||||
|
||||
mainTemplate.hooks.globalHashPaths.tap("AmdMainTemplatePlugin", paths => {
|
||||
if (this.name) paths.push(this.name);
|
||||
if (this.name) {
|
||||
paths.push(this.name);
|
||||
}
|
||||
return paths;
|
||||
});
|
||||
|
||||
|
|
|
@ -6,16 +6,26 @@
|
|||
|
||||
const WebpackError = require("./WebpackError");
|
||||
|
||||
module.exports = class AsyncDependencyToInitialChunkError extends WebpackError {
|
||||
/** @typedef {import("./Module")} Module */
|
||||
|
||||
class AsyncDependencyToInitialChunkError extends WebpackError {
|
||||
/**
|
||||
* Creates an instance of AsyncDependencyToInitialChunkError.
|
||||
* @param {string} chunkName Name of Chunk
|
||||
* @param {Module} module module tied to dependency
|
||||
* @param {TODO} loc location of dependency
|
||||
*/
|
||||
constructor(chunkName, module, loc) {
|
||||
super();
|
||||
super(
|
||||
`It's not allowed to load an initial chunk on demand. The chunk name "${chunkName}" is already used by an entrypoint.`
|
||||
);
|
||||
|
||||
this.name = "AsyncDependencyToInitialChunkError";
|
||||
this.message = `It's not allowed to load an initial chunk on demand. The chunk name "${chunkName}" is already used by an entrypoint.`;
|
||||
this.module = module;
|
||||
this.origin = module;
|
||||
this.originLoc = loc;
|
||||
this.loc = loc;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = AsyncDependencyToInitialChunkError;
|
||||
|
|
|
@ -13,7 +13,9 @@ const validateOptions = require("schema-utils");
|
|||
const schema = require("../schemas/plugins/BannerPlugin.json");
|
||||
|
||||
const wrapComment = str => {
|
||||
if (!str.includes("\n")) return Template.toComment(str);
|
||||
if (!str.includes("\n")) {
|
||||
return Template.toComment(str);
|
||||
}
|
||||
return `/*!\n * ${str
|
||||
.replace(/\*\//g, "* /")
|
||||
.split("\n")
|
||||
|
|
|
@ -90,20 +90,21 @@ class BasicEvaluatedExpression {
|
|||
|
||||
asBool() {
|
||||
if (this.truthy) return true;
|
||||
else if (this.falsy) return false;
|
||||
else if (this.isBoolean()) return this.bool;
|
||||
else if (this.isNull()) return false;
|
||||
else if (this.isString()) return this.string !== "";
|
||||
else if (this.isNumber()) return this.number !== 0;
|
||||
else if (this.isRegExp()) return true;
|
||||
else if (this.isArray()) return true;
|
||||
else if (this.isConstArray()) return true;
|
||||
else if (this.isWrapped())
|
||||
if (this.falsy) return false;
|
||||
if (this.isBoolean()) return this.bool;
|
||||
if (this.isNull()) return false;
|
||||
if (this.isString()) return this.string !== "";
|
||||
if (this.isNumber()) return this.number !== 0;
|
||||
if (this.isRegExp()) return true;
|
||||
if (this.isArray()) return true;
|
||||
if (this.isConstArray()) return true;
|
||||
if (this.isWrapped()) {
|
||||
return (this.prefix && this.prefix.asBool()) ||
|
||||
(this.postfix && this.postfix.asBool())
|
||||
? true
|
||||
: undefined;
|
||||
else if (this.isTemplateString()) {
|
||||
}
|
||||
if (this.isTemplateString()) {
|
||||
for (const quasi of this.quasis) {
|
||||
if (quasi.asBool()) return true;
|
||||
}
|
||||
|
@ -165,7 +166,9 @@ class BasicEvaluatedExpression {
|
|||
this.type = TypeConditional;
|
||||
this.options = [];
|
||||
}
|
||||
for (const item of options) this.options.push(item);
|
||||
for (const item of options) {
|
||||
this.options.push(item);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,12 +26,17 @@ class CachePlugin {
|
|||
(childCompiler, compilerName, compilerIndex) => {
|
||||
if (cache) {
|
||||
let childCache;
|
||||
if (!cache.children) cache.children = {};
|
||||
if (!cache.children[compilerName])
|
||||
if (!cache.children) {
|
||||
cache.children = {};
|
||||
}
|
||||
if (!cache.children[compilerName]) {
|
||||
cache.children[compilerName] = [];
|
||||
if (cache.children[compilerName][compilerIndex])
|
||||
}
|
||||
if (cache.children[compilerName][compilerIndex]) {
|
||||
childCache = cache.children[compilerName][compilerIndex];
|
||||
else cache.children[compilerName].push((childCache = {}));
|
||||
} else {
|
||||
cache.children[compilerName].push((childCache = {}));
|
||||
}
|
||||
registerCacheToCompiler(childCompiler, childCache);
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +48,9 @@ class CachePlugin {
|
|||
this.watching = true;
|
||||
});
|
||||
compiler.hooks.run.tapAsync("CachePlugin", (compiler, callback) => {
|
||||
if (!compiler._lastCompilationFileDependencies) return callback();
|
||||
if (!compiler._lastCompilationFileDependencies) {
|
||||
return callback();
|
||||
}
|
||||
const fs = compiler.inputFileSystem;
|
||||
const fileTs = (compiler.fileTimestamps = new Map());
|
||||
asyncLib.forEach(
|
||||
|
|
|
@ -6,48 +6,62 @@
|
|||
|
||||
const WebpackError = require("./WebpackError");
|
||||
|
||||
module.exports = class CaseSensitiveModulesWarning extends WebpackError {
|
||||
constructor(modules) {
|
||||
super();
|
||||
/** @typedef {import("./Module")} Module */
|
||||
|
||||
this.name = "CaseSensitiveModulesWarning";
|
||||
const sortedModules = this._sort(modules);
|
||||
const modulesList = this._moduleMessages(sortedModules);
|
||||
this.message = `There are multiple modules with names that only differ in casing.
|
||||
/**
|
||||
* @param {Module[]} modules the modules to be sorted
|
||||
* @returns {Module[]} sorted version of original modules
|
||||
*/
|
||||
const sortModules = modules => {
|
||||
return modules.slice().sort((a, b) => {
|
||||
const aIdent = a.identifier();
|
||||
const bIdent = b.identifier();
|
||||
/* istanbul ignore next */
|
||||
if (aIdent < bIdent) return -1;
|
||||
/* istanbul ignore next */
|
||||
if (aIdent > bIdent) return 1;
|
||||
/* istanbul ignore next */
|
||||
return 0;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Module[]} modules each module from throw
|
||||
* @returns {string} each message from provided moduels
|
||||
*/
|
||||
const createModulesListMessage = modules => {
|
||||
return modules
|
||||
.map(m => {
|
||||
let message = `* ${m.identifier()}`;
|
||||
const validReasons = m.reasons.filter(reason => reason.module);
|
||||
|
||||
if (validReasons.length > 0) {
|
||||
message += `\n Used by ${validReasons.length} module(s), i. e.`;
|
||||
message += `\n ${validReasons[0].module.identifier()}`;
|
||||
}
|
||||
return message;
|
||||
})
|
||||
.join("\n");
|
||||
};
|
||||
|
||||
class CaseSensitiveModulesWarning extends WebpackError {
|
||||
/**
|
||||
* Creates an instance of CaseSensitiveModulesWarning.
|
||||
* @param {Module[]} modules modules that were detected
|
||||
*/
|
||||
constructor(modules) {
|
||||
const sortedModules = sortModules(modules);
|
||||
const modulesList = createModulesListMessage(sortedModules);
|
||||
super(`There are multiple modules with names that only differ in casing.
|
||||
This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.
|
||||
Use equal casing. Compare these module identifiers:
|
||||
${modulesList}`;
|
||||
${modulesList}`);
|
||||
|
||||
this.name = "CaseSensitiveModulesWarning";
|
||||
this.origin = this.module = sortedModules[0];
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
||||
|
||||
_sort(modules) {
|
||||
return modules.slice().sort((a, b) => {
|
||||
a = a.identifier();
|
||||
b = b.identifier();
|
||||
/* istanbul ignore next */
|
||||
if (a < b) return -1;
|
||||
/* istanbul ignore next */
|
||||
if (a > b) return 1;
|
||||
/* istanbul ignore next */
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
_moduleMessages(modules) {
|
||||
return modules
|
||||
.map(m => {
|
||||
let message = `* ${m.identifier()}`;
|
||||
const validReasons = m.reasons.filter(reason => reason.module);
|
||||
|
||||
if (validReasons.length > 0) {
|
||||
message += `\n Used by ${validReasons.length} module(s), i. e.`;
|
||||
message += `\n ${validReasons[0].module.identifier()}`;
|
||||
}
|
||||
return message;
|
||||
})
|
||||
.join("\n");
|
||||
}
|
||||
};
|
||||
module.exports = CaseSensitiveModulesWarning;
|
||||
|
|
134
lib/Chunk.js
134
lib/Chunk.js
|
@ -20,35 +20,43 @@ const ERR_CHUNK_INITIAL =
|
|||
/** @typedef {import("crypto").Hash} Hash */
|
||||
|
||||
/**
|
||||
* @typedef {Object} Identifiable an object who contains an identifier function property
|
||||
* @property {() => string} identifier the resource or unique identifier of something
|
||||
* @typedef {Object} WithId an object who has an id property *
|
||||
* @property {string | number} id the id of the object
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} WithId an object who has an id property
|
||||
* @property {string} id the id of the object
|
||||
* Compare two Modules based on their ids for sorting
|
||||
* @param {Module} a module
|
||||
* @param {Module} b module
|
||||
* @returns {-1|0|1} sort value
|
||||
*/
|
||||
|
||||
// TODO use @callback
|
||||
/** @typedef {(a: Module, b: Module) => -1|0|1} ModuleSortPredicate */
|
||||
/** @typedef {(m: Module) => boolean} ModuleFilterPredicate */
|
||||
/** @typedef {(c: Chunk) => boolean} ChunkFilterPredicate */
|
||||
|
||||
/**
|
||||
* @param {WithId} a object that contains an ID property
|
||||
* @param {WithId} b object that contains an ID property
|
||||
* @returns {-1|0|1} sort value
|
||||
*/
|
||||
const sortById = (a, b) => {
|
||||
const sortModuleById = (a, b) => {
|
||||
if (a.id < b.id) return -1;
|
||||
if (b.id < a.id) return 1;
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Identifiable} a first object with ident fn
|
||||
* @param {Identifiable} b second object with ident fn
|
||||
* Compare two ChunkGroups based on their ids for sorting
|
||||
* @param {ChunkGroup} a chunk group
|
||||
* @param {ChunkGroup} b chunk group
|
||||
* @returns {-1|0|1} sort value
|
||||
*/
|
||||
const sortChunkGroupById = (a, b) => {
|
||||
if (a.id < b.id) return -1;
|
||||
if (b.id < a.id) return 1;
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compare two Identifiables , based on their ids for sorting
|
||||
* @param {Module} a first object with ident fn
|
||||
* @param {Module} b second object with ident fn
|
||||
* @returns {-1|0|1} The order number of the sort
|
||||
*/
|
||||
const sortByIdentifier = (a, b) => {
|
||||
|
@ -71,14 +79,14 @@ const getModulesIdent = set => {
|
|||
};
|
||||
|
||||
/**
|
||||
* @template {T}
|
||||
* @param {Set<T>} set the set to convert to array
|
||||
* @template T
|
||||
* @param {SortableSet<T>} set the sortable set to convert to array
|
||||
* @returns {Array<T>} the array returned from Array.from(set)
|
||||
*/
|
||||
const getArray = set => Array.from(set);
|
||||
|
||||
/**
|
||||
* @param {Set<Module>} set the Set to get the count/size of
|
||||
* @param {SortableSet<Module>} set the sortable Set to get the count/size of
|
||||
* @returns {number} the size of the modules
|
||||
*/
|
||||
const getModulesSize = set => {
|
||||
|
@ -110,13 +118,14 @@ class Chunk {
|
|||
this.preventIntegration = false;
|
||||
/** @type {Module=} */
|
||||
this.entryModule = undefined;
|
||||
//TODO make these typed generics for Module[] and ChunkGroup[] and their sort being (T, T): => 1,-1,0
|
||||
//See https://github.com/webpack/webpack/pull/7046
|
||||
/** @private */
|
||||
/** @private @type {SortableSet<Module>} */
|
||||
this._modules = new SortableSet(undefined, sortByIdentifier);
|
||||
|
||||
/** @private */
|
||||
this._groups = new SortableSet(undefined, sortById);
|
||||
/** @type {string[]} */
|
||||
/** @private @type {SortableSet<ChunkGroup>} */
|
||||
this._groups = new SortableSet(undefined, sortChunkGroupById);
|
||||
/** @type {Source[]} */
|
||||
this.files = [];
|
||||
/** @type {boolean} */
|
||||
this.rendered = false;
|
||||
|
@ -380,13 +389,14 @@ class Chunk {
|
|||
otherChunk._groups.clear();
|
||||
|
||||
if (this.name && otherChunk.name) {
|
||||
if (this.name.length !== otherChunk.name.length)
|
||||
if (this.name.length !== otherChunk.name.length) {
|
||||
this.name =
|
||||
this.name.length < otherChunk.name.length
|
||||
? this.name
|
||||
: otherChunk.name;
|
||||
else
|
||||
} else {
|
||||
this.name = this.name < otherChunk.name ? this.name : otherChunk.name;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -422,12 +432,16 @@ class Chunk {
|
|||
for (const chunkGroup of queue) {
|
||||
if (a.isInGroup(chunkGroup)) continue;
|
||||
if (chunkGroup.isInitial()) return false;
|
||||
for (const parent of chunkGroup.parentsIterable) queue.add(parent);
|
||||
for (const parent of chunkGroup.parentsIterable) {
|
||||
queue.add(parent);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if (this.preventIntegration || otherChunk.preventIntegration) return false;
|
||||
if (this.preventIntegration || otherChunk.preventIntegration) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.hasRuntime() !== otherChunk.hasRuntime()) {
|
||||
if (this.hasRuntime()) {
|
||||
|
@ -438,7 +452,11 @@ class Chunk {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
if (this.hasEntryModule() || otherChunk.hasEntryModule()) return false;
|
||||
|
||||
if (this.hasEntryModule() || otherChunk.hasEntryModule()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -496,14 +514,14 @@ class Chunk {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {ModuleSortPredicate=} sortByFn a predicate function used to sort modules
|
||||
* @param {function(Module, Module): -1|0|1=} sortByFn a predicate function used to sort modules
|
||||
* @returns {void}
|
||||
*/
|
||||
sortModules(sortByFn) {
|
||||
this._modules.sortWith(sortByFn || sortById);
|
||||
this._modules.sortWith(sortByFn || sortModuleById);
|
||||
}
|
||||
|
||||
sortItems(sortChunks) {
|
||||
sortItems() {
|
||||
this.sortModules();
|
||||
}
|
||||
|
||||
|
@ -519,14 +537,20 @@ class Chunk {
|
|||
);
|
||||
|
||||
for (const chunkGroup of this.groupsIterable) {
|
||||
for (const child of chunkGroup.childrenIterable) queue.add(child);
|
||||
for (const child of chunkGroup.childrenIterable) {
|
||||
queue.add(child);
|
||||
}
|
||||
}
|
||||
|
||||
for (const chunkGroup of queue) {
|
||||
for (const chunk of chunkGroup.chunks) {
|
||||
if (!initialChunks.has(chunk)) chunks.add(chunk);
|
||||
if (!initialChunks.has(chunk)) {
|
||||
chunks.add(chunk);
|
||||
}
|
||||
}
|
||||
for (const child of chunkGroup.childrenIterable) {
|
||||
queue.add(child);
|
||||
}
|
||||
for (const child of chunkGroup.childrenIterable) queue.add(child);
|
||||
}
|
||||
|
||||
return chunks;
|
||||
|
@ -554,11 +578,14 @@ class Chunk {
|
|||
for (const chunk of this.getAllAsyncChunks()) {
|
||||
chunkHashMap[chunk.id] = realHash ? chunk.hash : chunk.renderedHash;
|
||||
for (const key of Object.keys(chunk.contentHash)) {
|
||||
if (!chunkContentHashMap[key])
|
||||
if (!chunkContentHashMap[key]) {
|
||||
chunkContentHashMap[key] = Object.create(null);
|
||||
}
|
||||
chunkContentHashMap[key][chunk.id] = chunk.contentHash[key];
|
||||
}
|
||||
if (chunk.name) chunkNameMap[chunk.id] = chunk.name;
|
||||
if (chunk.name) {
|
||||
chunkNameMap[chunk.id] = chunk.name;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -599,12 +626,16 @@ class Chunk {
|
|||
const cmp = b.order - a.order;
|
||||
if (cmp !== 0) return cmp;
|
||||
// TOOD webpack 5 remove this check of compareTo
|
||||
if (a.group.compareTo) return a.group.compareTo(b.group);
|
||||
if (a.group.compareTo) {
|
||||
return a.group.compareTo(b.group);
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
result[name] = Array.from(
|
||||
list.reduce((set, item) => {
|
||||
for (const chunk of item.group.chunks) set.add(chunk.id);
|
||||
for (const chunk of item.group.chunks) {
|
||||
set.add(chunk.id);
|
||||
}
|
||||
return set;
|
||||
}, new Set())
|
||||
);
|
||||
|
@ -612,18 +643,28 @@ class Chunk {
|
|||
return result;
|
||||
}
|
||||
|
||||
getChildIdsByOrdersMap() {
|
||||
getChildIdsByOrdersMap(includeDirectChildren) {
|
||||
const chunkMaps = Object.create(null);
|
||||
|
||||
for (const chunk of this.getAllAsyncChunks()) {
|
||||
const addChildIdsByOrdersToMap = chunk => {
|
||||
const data = chunk.getChildIdsByOrders();
|
||||
for (const key of Object.keys(data)) {
|
||||
let chunkMap = chunkMaps[key];
|
||||
if (chunkMap === undefined)
|
||||
if (chunkMap === undefined) {
|
||||
chunkMaps[key] = chunkMap = Object.create(null);
|
||||
}
|
||||
chunkMap[chunk.id] = data[key];
|
||||
}
|
||||
};
|
||||
|
||||
if (includeDirectChildren) {
|
||||
addChildIdsByOrdersToMap(this);
|
||||
}
|
||||
|
||||
for (const chunk of this.getAllAsyncChunks()) {
|
||||
addChildIdsByOrdersToMap(chunk);
|
||||
}
|
||||
|
||||
return chunkMaps;
|
||||
}
|
||||
|
||||
|
@ -669,8 +710,8 @@ class Chunk {
|
|||
|
||||
/**
|
||||
*
|
||||
* @param {ModuleFilterPredicate} filterFn predicate function used to filter modules
|
||||
* @param {ChunkFilterPredicate} filterChunkFn predicate function used to filter chunks
|
||||
* @param {function(Module): boolean} filterFn predicate function used to filter modules
|
||||
* @param {function(Chunk): boolean} filterChunkFn predicate function used to filter chunks
|
||||
* @returns {boolean} return true if module exists in graph
|
||||
*/
|
||||
hasModuleInGraph(filterFn, filterChunkFn) {
|
||||
|
@ -682,12 +723,17 @@ class Chunk {
|
|||
if (!chunksProcessed.has(chunk)) {
|
||||
chunksProcessed.add(chunk);
|
||||
if (!filterChunkFn || filterChunkFn(chunk)) {
|
||||
for (const module of chunk.modulesIterable)
|
||||
if (filterFn(module)) return true;
|
||||
for (const module of chunk.modulesIterable) {
|
||||
if (filterFn(module)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const child of chunkGroup.childrenIterable) queue.add(child);
|
||||
for (const child of chunkGroup.childrenIterable) {
|
||||
queue.add(child);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -18,16 +18,16 @@ const compareLocations = require("./compareLocations");
|
|||
let debugId = 5000;
|
||||
|
||||
/**
|
||||
* @template {T}
|
||||
* @param {Set<T>} set set to convert to array.
|
||||
* @template T
|
||||
* @param {SortableSet<T>} set set to convert to array.
|
||||
* @returns {T[]} the array format of existing set
|
||||
*/
|
||||
const getArray = set => Array.from(set);
|
||||
|
||||
/**
|
||||
* A convenience method used to sort chunks based on their id's
|
||||
* @param {HasId} a first sorting comparitor
|
||||
* @param {HasId} b second sorting comparitor
|
||||
* @param {HasId} a first sorting comparator
|
||||
* @param {HasId} b second sorting comparator
|
||||
* @returns {1|0|-1} a sorting index to determine order
|
||||
*/
|
||||
const sortById = (a, b) => {
|
||||
|
@ -37,8 +37,8 @@ const sortById = (a, b) => {
|
|||
};
|
||||
|
||||
/**
|
||||
* @param {OriginRecord} a the first comparitor in sort
|
||||
* @param {OriginRecord} b the second comparitor in sort
|
||||
* @param {OriginRecord} a the first comparator in sort
|
||||
* @param {OriginRecord} b the second comparator in sort
|
||||
* @returns {1|-1|0} returns sorting order as index
|
||||
*/
|
||||
const sortOrigin = (a, b) => {
|
||||
|
@ -259,7 +259,9 @@ class ChunkGroup {
|
|||
|
||||
setParents(newParents) {
|
||||
this._parents.clear();
|
||||
for (const p of newParents) this._parents.add(p);
|
||||
for (const p of newParents) {
|
||||
this._parents.add(p);
|
||||
}
|
||||
}
|
||||
|
||||
getNumberOfParents() {
|
||||
|
@ -418,7 +420,9 @@ class ChunkGroup {
|
|||
if (key.endsWith("Order")) {
|
||||
const name = key.substr(0, key.length - "Order".length);
|
||||
let list = lists.get(name);
|
||||
if (list === undefined) lists.set(name, (list = []));
|
||||
if (list === undefined) {
|
||||
lists.set(name, (list = []));
|
||||
}
|
||||
list.push({
|
||||
order: childGroup.options[key],
|
||||
group: childGroup
|
||||
|
@ -433,7 +437,9 @@ class ChunkGroup {
|
|||
const cmp = b.order - a.order;
|
||||
if (cmp !== 0) return cmp;
|
||||
// TOOD webpack 5 remove this check of compareTo
|
||||
if (a.group.compareTo) return a.group.compareTo(b.group);
|
||||
if (a.group.compareTo) {
|
||||
return a.group.compareTo(b.group);
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
result[name] = list.map(i => i.group);
|
||||
|
@ -444,20 +450,22 @@ class ChunkGroup {
|
|||
checkConstraints() {
|
||||
const chunk = this;
|
||||
for (const child of chunk._children) {
|
||||
if (!child._parents.has(chunk))
|
||||
if (!child._parents.has(chunk)) {
|
||||
throw new Error(
|
||||
`checkConstraints: child missing parent ${chunk.debugId} -> ${
|
||||
child.debugId
|
||||
}`
|
||||
);
|
||||
}
|
||||
}
|
||||
for (const parentChunk of chunk._parents) {
|
||||
if (!parentChunk._children.has(chunk))
|
||||
if (!parentChunk._children.has(chunk)) {
|
||||
throw new Error(
|
||||
`checkConstraints: parent missing child ${parentChunk.debugId} <- ${
|
||||
chunk.debugId
|
||||
}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,15 @@
|
|||
|
||||
const WebpackError = require("./WebpackError");
|
||||
|
||||
/** @typedef {import("./Chunk")} Chunk */
|
||||
|
||||
class ChunkRenderError extends WebpackError {
|
||||
/**
|
||||
* Create a new ChunkRenderError
|
||||
* @param {Chunk} chunk A chunk
|
||||
* @param {string} file Related file
|
||||
* @param {Error} error Original error
|
||||
*/
|
||||
constructor(chunk, file, error) {
|
||||
super();
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const WebpackError = require("./WebpackError");
|
||||
|
||||
class CommentCompilationWarning extends WebpackError {
|
||||
constructor(message, module, loc) {
|
||||
super(message);
|
||||
|
||||
this.name = "CommentCompilationWarning";
|
||||
|
||||
this.module = module;
|
||||
this.loc = loc;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CommentCompilationWarning;
|
|
@ -8,7 +8,14 @@ const ConstDependency = require("./dependencies/ConstDependency");
|
|||
|
||||
const NullFactory = require("./NullFactory");
|
||||
|
||||
/** @typedef {import("./Compiler.js")} Compiler */
|
||||
|
||||
class CompatibilityPlugin {
|
||||
/**
|
||||
* Apply the plugin
|
||||
* @param {Compiler} compiler Webpack Compiler
|
||||
* @returns {void}
|
||||
*/
|
||||
apply(compiler) {
|
||||
compiler.hooks.compilation.tap(
|
||||
"CompatibilityPlugin",
|
||||
|
|
|
@ -497,8 +497,9 @@ class Compilation extends Tapable {
|
|||
if (this.cache && this.cache[cacheName]) {
|
||||
const cacheModule = this.cache[cacheName];
|
||||
|
||||
if (typeof cacheModule.updateCacheModule === "function")
|
||||
if (typeof cacheModule.updateCacheModule === "function") {
|
||||
cacheModule.updateCacheModule(module);
|
||||
}
|
||||
|
||||
let rebuild = true;
|
||||
if (this.fileTimestamps && this.contextTimestamps) {
|
||||
|
@ -512,8 +513,12 @@ class Compilation extends Tapable {
|
|||
cacheModule.disconnect();
|
||||
this._modules.set(identifier, cacheModule);
|
||||
this.modules.push(cacheModule);
|
||||
for (const err of cacheModule.errors) this.errors.push(err);
|
||||
for (const err of cacheModule.warnings) this.warnings.push(err);
|
||||
for (const err of cacheModule.errors) {
|
||||
this.errors.push(err);
|
||||
}
|
||||
for (const err of cacheModule.warnings) {
|
||||
this.warnings.push(err);
|
||||
}
|
||||
return {
|
||||
module: cacheModule,
|
||||
issuer: true,
|
||||
|
@ -590,7 +595,9 @@ class Compilation extends Tapable {
|
|||
|
||||
const callback = err => {
|
||||
this._buildingModules.delete(module);
|
||||
for (const cb of callbackList) cb(err);
|
||||
for (const cb of callbackList) {
|
||||
cb(err);
|
||||
}
|
||||
};
|
||||
|
||||
this.hooks.buildModule.call(module);
|
||||
|
@ -605,8 +612,11 @@ class Compilation extends Tapable {
|
|||
const err = errors[indexError];
|
||||
err.origin = origin;
|
||||
err.dependencies = dependencies;
|
||||
if (optional) this.warnings.push(err);
|
||||
else this.errors.push(err);
|
||||
if (optional) {
|
||||
this.warnings.push(err);
|
||||
} else {
|
||||
this.errors.push(err);
|
||||
}
|
||||
}
|
||||
|
||||
const warnings = module.warnings;
|
||||
|
@ -643,15 +653,17 @@ class Compilation extends Tapable {
|
|||
const resourceIdent = dep.getResourceIdentifier();
|
||||
if (resourceIdent) {
|
||||
const factory = this.dependencyFactories.get(dep.constructor);
|
||||
if (factory === undefined)
|
||||
if (factory === undefined) {
|
||||
throw new Error(
|
||||
`No module factory available for dependency type: ${
|
||||
dep.constructor.name
|
||||
}`
|
||||
);
|
||||
}
|
||||
let innerMap = dependencies.get(factory);
|
||||
if (innerMap === undefined)
|
||||
if (innerMap === undefined) {
|
||||
dependencies.set(factory, (innerMap = new Map()));
|
||||
}
|
||||
let list = innerMap.get(resourceIdent);
|
||||
if (list === undefined) innerMap.set(resourceIdent, (list = []));
|
||||
list.push(dep);
|
||||
|
@ -724,6 +736,7 @@ class Compilation extends Tapable {
|
|||
|
||||
const errorAndCallback = err => {
|
||||
err.origin = module;
|
||||
err.dependencies = dependencies;
|
||||
this.errors.push(err);
|
||||
if (bail) {
|
||||
callback(err);
|
||||
|
@ -768,7 +781,7 @@ class Compilation extends Tapable {
|
|||
if (err) {
|
||||
semaphore.release();
|
||||
return errorOrWarningAndCallback(
|
||||
new ModuleNotFoundError(module, err, dependencies)
|
||||
new ModuleNotFoundError(module, err)
|
||||
);
|
||||
}
|
||||
if (!dependentModule) {
|
||||
|
@ -1067,7 +1080,9 @@ class Compilation extends Tapable {
|
|||
|
||||
const callback = err => {
|
||||
this._rebuildingModules.delete(module);
|
||||
for (const cb of callbackList) cb(err);
|
||||
for (const cb of callbackList) {
|
||||
cb(err);
|
||||
}
|
||||
};
|
||||
|
||||
this.hooks.rebuildModule.call(module);
|
||||
|
@ -1155,7 +1170,7 @@ class Compilation extends Tapable {
|
|||
this.assignIndex(module);
|
||||
this.assignDepth(module);
|
||||
}
|
||||
this.processDependenciesBlocksForChunkGroups(this.chunkGroups);
|
||||
this.processDependenciesBlocksForChunkGroups(this.chunkGroups.slice());
|
||||
this.sortModules(this.modules);
|
||||
this.hooks.optimize.call();
|
||||
|
||||
|
@ -1215,15 +1230,18 @@ class Compilation extends Tapable {
|
|||
|
||||
this.sortItemsWithChunkIds();
|
||||
|
||||
if (shouldRecord)
|
||||
if (shouldRecord) {
|
||||
this.hooks.recordModules.call(this.modules, this.records);
|
||||
if (shouldRecord) this.hooks.recordChunks.call(this.chunks, this.records);
|
||||
this.hooks.recordChunks.call(this.chunks, this.records);
|
||||
}
|
||||
|
||||
this.hooks.beforeHash.call();
|
||||
this.createHash();
|
||||
this.hooks.afterHash.call();
|
||||
|
||||
if (shouldRecord) this.hooks.recordHash.call(this.records);
|
||||
if (shouldRecord) {
|
||||
this.hooks.recordHash.call(this.records);
|
||||
}
|
||||
|
||||
this.hooks.beforeModuleAssets.call();
|
||||
this.createModuleAssets();
|
||||
|
@ -1233,7 +1251,9 @@ class Compilation extends Tapable {
|
|||
}
|
||||
this.hooks.additionalChunkAssets.call(this.chunks);
|
||||
this.summarizeDependencies();
|
||||
if (shouldRecord) this.hooks.record.call(this, this.records);
|
||||
if (shouldRecord) {
|
||||
this.hooks.record.call(this, this.records);
|
||||
}
|
||||
|
||||
this.hooks.additionalAssets.callAsync(err => {
|
||||
if (err) {
|
||||
|
@ -1773,8 +1793,11 @@ class Compilation extends Tapable {
|
|||
|
||||
// 3. Create a new Set of available modules at this points
|
||||
newAvailableModules = new Set(availableModules);
|
||||
for (const chunk of chunkGroup.chunks)
|
||||
for (const m of chunk.modulesIterable) newAvailableModules.add(m);
|
||||
for (const chunk of chunkGroup.chunks) {
|
||||
for (const m of chunk.modulesIterable) {
|
||||
newAvailableModules.add(m);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Filter edges with available modules
|
||||
const filteredDeps = deps.filter(filterFn);
|
||||
|
@ -1948,8 +1971,11 @@ class Compilation extends Tapable {
|
|||
for (let indexModule2 = 0; indexModule2 < modules2.length; indexModule2++) {
|
||||
const module2 = modules2[indexModule2];
|
||||
if (module2.id === null) {
|
||||
if (unusedIds.length > 0) module2.id = unusedIds.pop();
|
||||
else module2.id = nextFreeModuleId++;
|
||||
if (unusedIds.length > 0) {
|
||||
module2.id = unusedIds.pop();
|
||||
} else {
|
||||
module2.id = nextFreeModuleId++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2008,8 +2034,11 @@ class Compilation extends Tapable {
|
|||
for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
|
||||
const chunk = chunks[indexChunk];
|
||||
if (chunk.id === null) {
|
||||
if (unusedIds.length > 0) chunk.id = unusedIds.pop();
|
||||
else chunk.id = nextFreeChunkId++;
|
||||
if (unusedIds.length > 0) {
|
||||
chunk.id = unusedIds.pop();
|
||||
} else {
|
||||
chunk.id = nextFreeChunkId++;
|
||||
}
|
||||
}
|
||||
if (!chunk.ids) {
|
||||
chunk.ids = [chunk.id];
|
||||
|
@ -2128,14 +2157,23 @@ class Compilation extends Tapable {
|
|||
const hashDigest = outputOptions.hashDigest;
|
||||
const hashDigestLength = outputOptions.hashDigestLength;
|
||||
const hash = createHash(hashFunction);
|
||||
if (outputOptions.hashSalt) hash.update(outputOptions.hashSalt);
|
||||
if (outputOptions.hashSalt) {
|
||||
hash.update(outputOptions.hashSalt);
|
||||
}
|
||||
this.mainTemplate.updateHash(hash);
|
||||
this.chunkTemplate.updateHash(hash);
|
||||
for (const key of Object.keys(this.moduleTemplates).sort())
|
||||
for (const key of Object.keys(this.moduleTemplates).sort()) {
|
||||
this.moduleTemplates[key].updateHash(hash);
|
||||
for (const child of this.children) hash.update(child.hash);
|
||||
for (const warning of this.warnings) hash.update(`${warning.message}`);
|
||||
for (const error of this.errors) hash.update(`${error.message}`);
|
||||
}
|
||||
for (const child of this.children) {
|
||||
hash.update(child.hash);
|
||||
}
|
||||
for (const warning of this.warnings) {
|
||||
hash.update(`${warning.message}`);
|
||||
}
|
||||
for (const error of this.errors) {
|
||||
hash.update(`${error.message}`);
|
||||
}
|
||||
const modules = this.modules;
|
||||
for (let i = 0; i < modules.length; i++) {
|
||||
const module = modules[i];
|
||||
|
@ -2161,7 +2199,9 @@ class Compilation extends Tapable {
|
|||
for (let i = 0; i < chunks.length; i++) {
|
||||
const chunk = chunks[i];
|
||||
const chunkHash = createHash(hashFunction);
|
||||
if (outputOptions.hashSalt) chunkHash.update(outputOptions.hashSalt);
|
||||
if (outputOptions.hashSalt) {
|
||||
chunkHash.update(outputOptions.hashSalt);
|
||||
}
|
||||
chunk.updateHash(chunkHash);
|
||||
const template = chunk.hasRuntime()
|
||||
? this.mainTemplate
|
||||
|
@ -2258,10 +2298,11 @@ class Compilation extends Tapable {
|
|||
}
|
||||
}
|
||||
file = this.getPath(filenameTemplate, fileManifest.pathOptions);
|
||||
if (this.assets[file] && this.assets[file] !== source)
|
||||
if (this.assets[file] && this.assets[file] !== source) {
|
||||
throw new Error(
|
||||
`Conflict: Multiple assets emit to the same filename ${file}`
|
||||
);
|
||||
}
|
||||
this.assets[file] = source;
|
||||
chunk.files.push(file);
|
||||
this.hooks.chunkAsset.call(chunk, file);
|
||||
|
@ -2315,18 +2356,20 @@ class Compilation extends Tapable {
|
|||
for (let indexModule = 0; indexModule < modules.length; indexModule++) {
|
||||
const moduleId = modules[indexModule].id;
|
||||
if (moduleId === null) continue;
|
||||
if (usedIds.has(moduleId))
|
||||
if (usedIds.has(moduleId)) {
|
||||
throw new Error(`checkConstraints: duplicate module id ${moduleId}`);
|
||||
}
|
||||
usedIds.add(moduleId);
|
||||
}
|
||||
|
||||
const chunks = this.chunks;
|
||||
for (let indexChunk = 0; indexChunk < chunks.length; indexChunk++) {
|
||||
const chunk = chunks[indexChunk];
|
||||
if (chunks.indexOf(chunk) !== indexChunk)
|
||||
if (chunks.indexOf(chunk) !== indexChunk) {
|
||||
throw new Error(
|
||||
`checkConstraints: duplicate chunk in compilation ${chunk.debugId}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (const chunkGroup of this.chunkGroups) {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
const parseJson = require("json-parse-better-errors");
|
||||
const asyncLib = require("neo-async");
|
||||
const path = require("path");
|
||||
const util = require("util");
|
||||
|
@ -306,8 +307,9 @@ class Compiler extends Tapable {
|
|||
}
|
||||
|
||||
purgeInputFileSystem() {
|
||||
if (this.inputFileSystem && this.inputFileSystem.purge)
|
||||
if (this.inputFileSystem && this.inputFileSystem.purge) {
|
||||
this.inputFileSystem.purge();
|
||||
}
|
||||
}
|
||||
|
||||
emitAssets(compilation, callback) {
|
||||
|
@ -352,7 +354,9 @@ class Compiler extends Tapable {
|
|||
this.outputFileSystem.join(outputPath, dir),
|
||||
writeOut
|
||||
);
|
||||
} else writeOut();
|
||||
} else {
|
||||
writeOut();
|
||||
}
|
||||
},
|
||||
err => {
|
||||
if (err) return callback(err);
|
||||
|
@ -378,10 +382,11 @@ class Compiler extends Tapable {
|
|||
const idx1 = this.recordsOutputPath.lastIndexOf("/");
|
||||
const idx2 = this.recordsOutputPath.lastIndexOf("\\");
|
||||
let recordsOutputPathDirectory = null;
|
||||
if (idx1 > idx2)
|
||||
if (idx1 > idx2) {
|
||||
recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx1);
|
||||
if (idx1 < idx2)
|
||||
} else if (idx1 < idx2) {
|
||||
recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx2);
|
||||
}
|
||||
|
||||
const writeFile = () => {
|
||||
this.outputFileSystem.writeFile(
|
||||
|
@ -391,7 +396,9 @@ class Compiler extends Tapable {
|
|||
);
|
||||
};
|
||||
|
||||
if (!recordsOutputPathDirectory) return writeFile();
|
||||
if (!recordsOutputPathDirectory) {
|
||||
return writeFile();
|
||||
}
|
||||
this.outputFileSystem.mkdirp(recordsOutputPathDirectory, err => {
|
||||
if (err) return callback(err);
|
||||
writeFile();
|
||||
|
@ -412,7 +419,7 @@ class Compiler extends Tapable {
|
|||
if (err) return callback(err);
|
||||
|
||||
try {
|
||||
this.records = JSON.parse(content.toString("utf-8"));
|
||||
this.records = parseJson(content.toString("utf-8"));
|
||||
} catch (e) {
|
||||
e.message = "Cannot parse records: " + e.message;
|
||||
return callback(e);
|
||||
|
@ -432,7 +439,9 @@ class Compiler extends Tapable {
|
|||
) {
|
||||
const childCompiler = new Compiler(this.context);
|
||||
if (Array.isArray(plugins)) {
|
||||
for (const plugin of plugins) plugin.apply(childCompiler);
|
||||
for (const plugin of plugins) {
|
||||
plugin.apply(childCompiler);
|
||||
}
|
||||
}
|
||||
for (const name in this.hooks) {
|
||||
if (
|
||||
|
@ -446,8 +455,9 @@ class Compiler extends Tapable {
|
|||
"thisCompilation"
|
||||
].includes(name)
|
||||
) {
|
||||
if (childCompiler.hooks[name])
|
||||
if (childCompiler.hooks[name]) {
|
||||
childCompiler.hooks[name].taps = this.hooks[name].taps.slice();
|
||||
}
|
||||
}
|
||||
}
|
||||
childCompiler.name = compilerName;
|
||||
|
@ -459,11 +469,14 @@ class Compiler extends Tapable {
|
|||
childCompiler.contextTimestamps = this.contextTimestamps;
|
||||
|
||||
const relativeCompilerName = makePathsRelative(this.context, compilerName);
|
||||
if (!this.records[relativeCompilerName])
|
||||
if (!this.records[relativeCompilerName]) {
|
||||
this.records[relativeCompilerName] = [];
|
||||
if (this.records[relativeCompilerName][compilerIndex])
|
||||
}
|
||||
if (this.records[relativeCompilerName][compilerIndex]) {
|
||||
childCompiler.records = this.records[relativeCompilerName][compilerIndex];
|
||||
else this.records[relativeCompilerName].push((childCompiler.records = {}));
|
||||
} else {
|
||||
this.records[relativeCompilerName].push((childCompiler.records = {}));
|
||||
}
|
||||
|
||||
childCompiler.options = Object.create(this.options);
|
||||
childCompiler.options.output = Object.create(childCompiler.options.output);
|
||||
|
|
|
@ -21,13 +21,19 @@ const collectDeclaration = (declarations, pattern) => {
|
|||
declarations.add(node.name);
|
||||
break;
|
||||
case "ArrayPattern":
|
||||
for (const element of node.elements) if (element) stack.push(element);
|
||||
for (const element of node.elements) {
|
||||
if (element) {
|
||||
stack.push(element);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "AssignmentPattern":
|
||||
stack.push(node.left);
|
||||
break;
|
||||
case "ObjectPattern":
|
||||
for (const property of node.properties) stack.push(property.value);
|
||||
for (const property of node.properties) {
|
||||
stack.push(property.value);
|
||||
}
|
||||
break;
|
||||
case "RestElement":
|
||||
stack.push(node.argument);
|
||||
|
@ -47,7 +53,9 @@ const getHoistedDeclarations = (branch, includeFunctionDeclarations) => {
|
|||
// Walk through control statements to look for hoisted declarations.
|
||||
// Some branches are skipped since they do not allow declarations.
|
||||
case "BlockStatement":
|
||||
for (const stmt of node.body) stack.push(stmt);
|
||||
for (const stmt of node.body) {
|
||||
stack.push(stmt);
|
||||
}
|
||||
break;
|
||||
case "IfStatement":
|
||||
stack.push(node.consequent);
|
||||
|
@ -68,22 +76,30 @@ const getHoistedDeclarations = (branch, includeFunctionDeclarations) => {
|
|||
stack.push(node.body);
|
||||
break;
|
||||
case "SwitchStatement":
|
||||
for (const cs of node.cases)
|
||||
for (const consequent of cs.consequent) stack.push(consequent);
|
||||
for (const cs of node.cases) {
|
||||
for (const consequent of cs.consequent) {
|
||||
stack.push(consequent);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "TryStatement":
|
||||
stack.push(node.block);
|
||||
if (node.handler) stack.push(node.handler.body);
|
||||
if (node.handler) {
|
||||
stack.push(node.handler.body);
|
||||
}
|
||||
stack.push(node.finalizer);
|
||||
break;
|
||||
case "FunctionDeclaration":
|
||||
if (includeFunctionDeclarations)
|
||||
if (includeFunctionDeclarations) {
|
||||
collectDeclaration(declarations, node.id);
|
||||
}
|
||||
break;
|
||||
case "VariableDeclaration":
|
||||
if (node.kind === "var")
|
||||
for (const decl of node.declarations)
|
||||
if (node.kind === "var") {
|
||||
for (const decl of node.declarations) {
|
||||
collectDeclaration(declarations, decl.id);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ const AsyncDependenciesBlock = require("./AsyncDependenciesBlock");
|
|||
const ModuleDependency = require("./dependencies/ModuleDependency");
|
||||
const Template = require("./Template");
|
||||
|
||||
/** @typedef {import("./dependencies/ContextElementDependency")} ContextElementDependency */
|
||||
|
||||
class ContextModule extends Module {
|
||||
// type ContextMode = "sync" | "eager" | "weak" | "async-weak" | "lazy" | "lazy-once"
|
||||
// type ContextOptions = { resource: string, recursive: boolean, regExp: RegExp, addon?: string, mode?: ContextMode, chunkName?: string, include?: RegExp, exclude?: RegExp, groupOptions?: Object }
|
||||
|
@ -36,14 +38,16 @@ class ContextModule extends Module {
|
|||
resource: resource,
|
||||
resourceQuery: resourceQuery
|
||||
});
|
||||
if (options.resolveOptions !== undefined)
|
||||
if (options.resolveOptions !== undefined) {
|
||||
this.resolveOptions = options.resolveOptions;
|
||||
}
|
||||
|
||||
// Info from Build
|
||||
this._contextDependencies = new Set([this.context]);
|
||||
|
||||
if (typeof options.mode !== "string")
|
||||
if (typeof options.mode !== "string") {
|
||||
throw new Error("options.mode is a required option");
|
||||
}
|
||||
|
||||
this._identifier = this._createIdentifier();
|
||||
}
|
||||
|
@ -74,22 +78,37 @@ class ContextModule extends Module {
|
|||
|
||||
_createIdentifier() {
|
||||
let identifier = this.context;
|
||||
if (this.options.resourceQuery)
|
||||
if (this.options.resourceQuery) {
|
||||
identifier += ` ${this.options.resourceQuery}`;
|
||||
if (this.options.mode) identifier += ` ${this.options.mode}`;
|
||||
if (!this.options.recursive) identifier += " nonrecursive";
|
||||
if (this.options.addon) identifier += ` ${this.options.addon}`;
|
||||
if (this.options.regExp) identifier += ` ${this.options.regExp}`;
|
||||
if (this.options.include) identifier += ` include: ${this.options.include}`;
|
||||
if (this.options.exclude) identifier += ` exclude: ${this.options.exclude}`;
|
||||
}
|
||||
if (this.options.mode) {
|
||||
identifier += ` ${this.options.mode}`;
|
||||
}
|
||||
if (!this.options.recursive) {
|
||||
identifier += " nonrecursive";
|
||||
}
|
||||
if (this.options.addon) {
|
||||
identifier += ` ${this.options.addon}`;
|
||||
}
|
||||
if (this.options.regExp) {
|
||||
identifier += ` ${this.options.regExp}`;
|
||||
}
|
||||
if (this.options.include) {
|
||||
identifier += ` include: ${this.options.include}`;
|
||||
}
|
||||
if (this.options.exclude) {
|
||||
identifier += ` exclude: ${this.options.exclude}`;
|
||||
}
|
||||
if (this.options.groupOptions) {
|
||||
identifier += ` groupOptions: ${JSON.stringify(
|
||||
this.options.groupOptions
|
||||
)}`;
|
||||
}
|
||||
if (this.options.namespaceObject === "strict")
|
||||
if (this.options.namespaceObject === "strict") {
|
||||
identifier += " strict namespace object";
|
||||
else if (this.options.namespaceObject) identifier += " namespace object";
|
||||
} else if (this.options.namespaceObject) {
|
||||
identifier += " namespace object";
|
||||
}
|
||||
|
||||
return identifier;
|
||||
}
|
||||
|
@ -100,42 +119,62 @@ class ContextModule extends Module {
|
|||
|
||||
readableIdentifier(requestShortener) {
|
||||
let identifier = requestShortener.shorten(this.context);
|
||||
if (this.options.resourceQuery)
|
||||
if (this.options.resourceQuery) {
|
||||
identifier += ` ${this.options.resourceQuery}`;
|
||||
if (this.options.mode) identifier += ` ${this.options.mode}`;
|
||||
if (!this.options.recursive) identifier += " nonrecursive";
|
||||
if (this.options.addon)
|
||||
}
|
||||
if (this.options.mode) {
|
||||
identifier += ` ${this.options.mode}`;
|
||||
}
|
||||
if (!this.options.recursive) {
|
||||
identifier += " nonrecursive";
|
||||
}
|
||||
if (this.options.addon) {
|
||||
identifier += ` ${requestShortener.shorten(this.options.addon)}`;
|
||||
if (this.options.regExp)
|
||||
}
|
||||
if (this.options.regExp) {
|
||||
identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`;
|
||||
if (this.options.include)
|
||||
}
|
||||
if (this.options.include) {
|
||||
identifier += ` include: ${this.prettyRegExp(this.options.include + "")}`;
|
||||
if (this.options.exclude)
|
||||
}
|
||||
if (this.options.exclude) {
|
||||
identifier += ` exclude: ${this.prettyRegExp(this.options.exclude + "")}`;
|
||||
}
|
||||
if (this.options.groupOptions) {
|
||||
const groupOptions = this.options.groupOptions;
|
||||
for (const key of Object.keys(groupOptions))
|
||||
for (const key of Object.keys(groupOptions)) {
|
||||
identifier += ` ${key}: ${groupOptions[key]}`;
|
||||
}
|
||||
}
|
||||
if (this.options.namespaceObject === "strict")
|
||||
if (this.options.namespaceObject === "strict") {
|
||||
identifier += " strict namespace object";
|
||||
else if (this.options.namespaceObject) identifier += " namespace object";
|
||||
} else if (this.options.namespaceObject) {
|
||||
identifier += " namespace object";
|
||||
}
|
||||
|
||||
return identifier;
|
||||
}
|
||||
|
||||
libIdent(options) {
|
||||
let identifier = this.contextify(options.context, this.context);
|
||||
if (this.options.mode) identifier += ` ${this.options.mode}`;
|
||||
if (this.options.recursive) identifier += " recursive";
|
||||
if (this.options.addon)
|
||||
if (this.options.mode) {
|
||||
identifier += ` ${this.options.mode}`;
|
||||
}
|
||||
if (this.options.recursive) {
|
||||
identifier += " recursive";
|
||||
}
|
||||
if (this.options.addon) {
|
||||
identifier += ` ${this.contextify(options.context, this.options.addon)}`;
|
||||
if (this.options.regExp)
|
||||
}
|
||||
if (this.options.regExp) {
|
||||
identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`;
|
||||
if (this.options.include)
|
||||
}
|
||||
if (this.options.include) {
|
||||
identifier += ` include: ${this.prettyRegExp(this.options.include + "")}`;
|
||||
if (this.options.exclude)
|
||||
}
|
||||
if (this.options.exclude) {
|
||||
identifier += ` exclude: ${this.prettyRegExp(this.options.exclude + "")}`;
|
||||
}
|
||||
|
||||
return identifier;
|
||||
}
|
||||
|
@ -207,7 +246,9 @@ class ContextModule extends Module {
|
|||
for (const dep of dependencies) {
|
||||
let chunkName = this.options.chunkName;
|
||||
if (chunkName) {
|
||||
if (!/\[(index|request)\]/.test(chunkName)) chunkName += "[index]";
|
||||
if (!/\[(index|request)\]/.test(chunkName)) {
|
||||
chunkName += "[index]";
|
||||
}
|
||||
chunkName = chunkName.replace(/\[index\]/g, index++);
|
||||
chunkName = chunkName.replace(
|
||||
/\[request\]/g,
|
||||
|
@ -254,7 +295,9 @@ class ContextModule extends Module {
|
|||
}
|
||||
|
||||
getFakeMap(dependencies) {
|
||||
if (!this.options.namespaceObject) return 1;
|
||||
if (!this.options.namespaceObject) {
|
||||
return 9;
|
||||
}
|
||||
// if we filter first we get a new array
|
||||
// therefor we dont need to create a clone of dependencies explicitly
|
||||
// therefore the order of this is !important!
|
||||
|
@ -269,20 +312,31 @@ class ContextModule extends Module {
|
|||
.reduce((map, dep) => {
|
||||
const exportsType =
|
||||
dep.module.buildMeta && dep.module.buildMeta.exportsType;
|
||||
if (!exportsType) hasNonHarmony = true;
|
||||
if (exportsType === "namespace") hasNamespace = true;
|
||||
if (exportsType === "named") hasNamed = true;
|
||||
map[dep.module.id] =
|
||||
{
|
||||
namespace: 1,
|
||||
named: 2
|
||||
}[exportsType] || 0;
|
||||
const id = dep.module.id;
|
||||
if (!exportsType) {
|
||||
map[id] = this.options.namespaceObject === "strict" ? 1 : 7;
|
||||
hasNonHarmony = true;
|
||||
} else if (exportsType === "namespace") {
|
||||
map[id] = 9;
|
||||
hasNamespace = true;
|
||||
} else if (exportsType === "named") {
|
||||
map[id] = 3;
|
||||
hasNamed = true;
|
||||
}
|
||||
return map;
|
||||
}, Object.create(null));
|
||||
if (!hasNamespace && hasNonHarmony && !hasNamed) return 0;
|
||||
if (hasNamespace && !hasNonHarmony && !hasNamed) return 1;
|
||||
if (!hasNamespace && !hasNonHarmony && hasNamed) return 2;
|
||||
if (!hasNamespace && !hasNonHarmony && !hasNamed) return 1;
|
||||
if (!hasNamespace && hasNonHarmony && !hasNamed) {
|
||||
return this.options.namespaceObject === "strict" ? 1 : 7;
|
||||
}
|
||||
if (hasNamespace && !hasNonHarmony && !hasNamed) {
|
||||
return 9;
|
||||
}
|
||||
if (!hasNamespace && !hasNonHarmony && hasNamed) {
|
||||
return 3;
|
||||
}
|
||||
if (!hasNamespace && !hasNonHarmony && !hasNamed) {
|
||||
return 9;
|
||||
}
|
||||
return fakeMap;
|
||||
}
|
||||
|
||||
|
@ -293,26 +347,17 @@ class ContextModule extends Module {
|
|||
}
|
||||
|
||||
getReturn(type) {
|
||||
if (type === 1) return "module";
|
||||
if (type === 2)
|
||||
return 'Object.assign({/* fake namespace object */}, typeof module === "object" && module, { "default": module })';
|
||||
if (type === 0) {
|
||||
if (this.options.namespaceObject === "strict") {
|
||||
return '/* fake namespace object */ { "default": module }';
|
||||
} else {
|
||||
return '(typeof module === "object" && module && module.__esModule ? module : Object.assign({/* fake namespace object */}, typeof module === "object" && module, { "default": module }))';
|
||||
}
|
||||
if (type === 9) {
|
||||
return "__webpack_require__(id)";
|
||||
}
|
||||
return `__webpack_require__.t(id, ${type})`;
|
||||
}
|
||||
|
||||
getReturnModuleObjectSource(fakeMap, fakeMapDataExpression = "fakeMap[id]") {
|
||||
if (typeof fakeMap === "number")
|
||||
if (typeof fakeMap === "number") {
|
||||
return `return ${this.getReturn(fakeMap)};`;
|
||||
return `return ${fakeMapDataExpression} === 1 ? ${this.getReturn(
|
||||
1
|
||||
)} : ${fakeMapDataExpression} ? ${this.getReturn(2)} : ${this.getReturn(
|
||||
0
|
||||
)};`;
|
||||
}
|
||||
return `return __webpack_require__.t(id, ${fakeMapDataExpression})`;
|
||||
}
|
||||
|
||||
getSyncSource(dependencies, id) {
|
||||
|
@ -325,13 +370,12 @@ ${this.getFakeMapInitStatement(fakeMap)}
|
|||
|
||||
function webpackContext(req) {
|
||||
var id = webpackContextResolve(req);
|
||||
var module = __webpack_require__(id);
|
||||
${returnModuleObject}
|
||||
}
|
||||
function webpackContextResolve(req) {
|
||||
var id = map[req];
|
||||
if(!(id + 1)) { // check for number or string
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
}
|
||||
|
@ -360,13 +404,12 @@ function webpackContext(req) {
|
|||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
}
|
||||
var module = __webpack_require__(id);
|
||||
${returnModuleObject}
|
||||
}
|
||||
function webpackContextResolve(req) {
|
||||
var id = map[req];
|
||||
if(!(id + 1)) { // check for number or string
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
}
|
||||
|
@ -395,7 +438,6 @@ function webpackAsyncContext(req) {
|
|||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
}
|
||||
var module = __webpack_require__(id);
|
||||
${returnModuleObject}
|
||||
});
|
||||
}
|
||||
|
@ -405,7 +447,7 @@ function webpackAsyncContextResolve(req) {
|
|||
return Promise.resolve().then(function() {
|
||||
var id = map[req];
|
||||
if(!(id + 1)) { // check for number or string
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
}
|
||||
|
@ -424,11 +466,10 @@ module.exports = webpackAsyncContext;`;
|
|||
const map = this.getUserRequestMap(dependencies);
|
||||
const fakeMap = this.getFakeMap(dependencies);
|
||||
const thenFunction =
|
||||
fakeMap !== 1
|
||||
fakeMap !== 9
|
||||
? `function(id) {
|
||||
var module = __webpack_require__(id);
|
||||
${this.getReturnModuleObjectSource(fakeMap)}
|
||||
}`
|
||||
${this.getReturnModuleObjectSource(fakeMap)}
|
||||
}`
|
||||
: "__webpack_require__";
|
||||
return `var map = ${JSON.stringify(map, null, "\t")};
|
||||
${this.getFakeMapInitStatement(fakeMap)}
|
||||
|
@ -442,7 +483,7 @@ function webpackAsyncContextResolve(req) {
|
|||
return Promise.resolve().then(function() {
|
||||
var id = map[req];
|
||||
if(!(id + 1)) { // check for number or string
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
}
|
||||
|
@ -465,9 +506,8 @@ module.exports = webpackAsyncContext;`;
|
|||
const map = this.getUserRequestMap(dependencies);
|
||||
const fakeMap = this.getFakeMap(dependencies);
|
||||
const thenFunction =
|
||||
fakeMap !== 1
|
||||
fakeMap !== 9
|
||||
? `function(id) {
|
||||
var module = __webpack_require__(id);
|
||||
${this.getReturnModuleObjectSource(fakeMap)};
|
||||
}`
|
||||
: "__webpack_require__";
|
||||
|
@ -482,7 +522,7 @@ function webpackAsyncContextResolve(req) {
|
|||
return ${promise}.then(function() {
|
||||
var id = map[req];
|
||||
if(!(id + 1)) { // check for number or string
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
}
|
||||
|
@ -518,8 +558,9 @@ module.exports = webpackAsyncContext;`;
|
|||
hasMultipleOrNoChunks = true;
|
||||
}
|
||||
const arrayStart = [item.dependency.module.id];
|
||||
if (typeof fakeMap === "object")
|
||||
if (typeof fakeMap === "object") {
|
||||
arrayStart.push(fakeMap[item.dependency.module.id]);
|
||||
}
|
||||
map[item.userRequest] = arrayStart.concat(
|
||||
chunks.map(chunk => chunk.id)
|
||||
);
|
||||
|
@ -541,13 +582,13 @@ function webpackAsyncContext(req) {
|
|||
var ids = map[req];
|
||||
if(!ids) {
|
||||
return Promise.resolve().then(function() {
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
return ${requestPrefix}.then(function() {
|
||||
var module = __webpack_require__(ids[0]);
|
||||
var id = ids[0];
|
||||
${returnModuleObject}
|
||||
});
|
||||
}
|
||||
|
@ -560,7 +601,7 @@ module.exports = webpackAsyncContext;`;
|
|||
|
||||
getSourceForEmptyContext(id) {
|
||||
return `function webpackEmptyContext(req) {
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
}
|
||||
|
@ -575,7 +616,7 @@ webpackEmptyContext.id = ${JSON.stringify(id)};`;
|
|||
// Here Promise.resolve().then() is used instead of new Promise() to prevent
|
||||
// uncaught exception popping up in devtools
|
||||
return Promise.resolve().then(function() {
|
||||
var e = new Error('Cannot find module "' + req + '".');
|
||||
var e = new Error("Cannot find module '" + req + "'");
|
||||
e.code = 'MODULE_NOT_FOUND';
|
||||
throw e;
|
||||
});
|
||||
|
@ -647,11 +688,8 @@ webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`;
|
|||
|
||||
// if we dont have dependencies we stop here.
|
||||
return this.dependencies.reduce((size, dependency) => {
|
||||
if (dependency instanceof ModuleDependency) {
|
||||
return size + 5 + dependency.userRequest.length;
|
||||
} else {
|
||||
return size;
|
||||
}
|
||||
const element = /** @type {ContextElementDependency} */ (dependency);
|
||||
return size + 5 + element.userRequest.length;
|
||||
}, initialSize);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,17 +67,24 @@ module.exports = class ContextModuleFactory extends Tapable {
|
|||
loadersPrefix = "";
|
||||
const idx = request.lastIndexOf("!");
|
||||
if (idx >= 0) {
|
||||
loaders = request.substr(0, idx + 1);
|
||||
let loadersRequest = request.substr(0, idx + 1);
|
||||
let i;
|
||||
for (i = 0; i < loaders.length && loaders[i] === "!"; i++) {
|
||||
for (
|
||||
i = 0;
|
||||
i < loadersRequest.length && loadersRequest[i] === "!";
|
||||
i++
|
||||
) {
|
||||
loadersPrefix += "!";
|
||||
}
|
||||
loaders = loaders
|
||||
loadersRequest = loadersRequest
|
||||
.substr(i)
|
||||
.replace(/!+$/, "")
|
||||
.replace(/!!+/g, "!");
|
||||
if (loaders === "") loaders = [];
|
||||
else loaders = loaders.split("!");
|
||||
if (loadersRequest === "") {
|
||||
loaders = [];
|
||||
} else {
|
||||
loaders = loadersRequest.split("!");
|
||||
}
|
||||
resource = request.substr(idx + 1);
|
||||
} else {
|
||||
loaders = [];
|
||||
|
@ -222,9 +229,13 @@ module.exports = class ContextModuleFactory extends Tapable {
|
|||
callback(null, alternatives);
|
||||
}
|
||||
);
|
||||
} else callback();
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
} else callback();
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
(err, result) => {
|
||||
if (err) return callback(err);
|
||||
|
|
|
@ -60,12 +60,15 @@ class ContextReplacementPlugin {
|
|||
cmf.hooks.beforeResolve.tap("ContextReplacementPlugin", result => {
|
||||
if (!result) return;
|
||||
if (resourceRegExp.test(result.request)) {
|
||||
if (typeof newContentResource !== "undefined")
|
||||
if (typeof newContentResource !== "undefined") {
|
||||
result.request = newContentResource;
|
||||
if (typeof newContentRecursive !== "undefined")
|
||||
}
|
||||
if (typeof newContentRecursive !== "undefined") {
|
||||
result.recursive = newContentRecursive;
|
||||
if (typeof newContentRegExp !== "undefined")
|
||||
}
|
||||
if (typeof newContentRegExp !== "undefined") {
|
||||
result.regExp = newContentRegExp;
|
||||
}
|
||||
if (typeof newContentCallback === "function") {
|
||||
newContentCallback(result);
|
||||
} else {
|
||||
|
@ -79,16 +82,20 @@ class ContextReplacementPlugin {
|
|||
cmf.hooks.afterResolve.tap("ContextReplacementPlugin", result => {
|
||||
if (!result) return;
|
||||
if (resourceRegExp.test(result.resource)) {
|
||||
if (typeof newContentResource !== "undefined")
|
||||
if (typeof newContentResource !== "undefined") {
|
||||
result.resource = path.resolve(result.resource, newContentResource);
|
||||
if (typeof newContentRecursive !== "undefined")
|
||||
}
|
||||
if (typeof newContentRecursive !== "undefined") {
|
||||
result.recursive = newContentRecursive;
|
||||
if (typeof newContentRegExp !== "undefined")
|
||||
}
|
||||
if (typeof newContentRegExp !== "undefined") {
|
||||
result.regExp = newContentRegExp;
|
||||
if (typeof newContentCreateContextMap === "function")
|
||||
}
|
||||
if (typeof newContentCreateContextMap === "function") {
|
||||
result.resolveDependencies = createResolveDependenciesFromContextMap(
|
||||
newContentCreateContextMap
|
||||
);
|
||||
}
|
||||
if (typeof newContentCallback === "function") {
|
||||
const origResource = result.resource;
|
||||
newContentCallback(result);
|
||||
|
|
|
@ -23,13 +23,22 @@ const stringifyObj = obj => {
|
|||
};
|
||||
|
||||
const toCode = code => {
|
||||
if (code === null) return "null";
|
||||
else if (code === undefined) return "undefined";
|
||||
else if (code instanceof RegExp && code.toString) return code.toString();
|
||||
else if (typeof code === "function" && code.toString)
|
||||
if (code === null) {
|
||||
return "null";
|
||||
}
|
||||
if (code === undefined) {
|
||||
return "undefined";
|
||||
}
|
||||
if (code instanceof RegExp && code.toString) {
|
||||
return code.toString();
|
||||
}
|
||||
if (typeof code === "function" && code.toString) {
|
||||
return "(" + code.toString() + ")";
|
||||
else if (typeof code === "object") return stringifyObj(code);
|
||||
else return code + "";
|
||||
}
|
||||
if (typeof code === "object") {
|
||||
return stringifyObj(code);
|
||||
}
|
||||
return code + "";
|
||||
};
|
||||
|
||||
class DefinePlugin {
|
||||
|
|
|
@ -64,7 +64,7 @@ class DelegatedModule extends Module {
|
|||
}
|
||||
|
||||
source(depTemplates, runtime) {
|
||||
const dep = this.delegatedSourceDependency;
|
||||
const dep = /** @type {DelegatedSourceDependency} */ (this.dependencies[0]);
|
||||
const sourceModule = dep.module;
|
||||
let str;
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ const DependenciesBlockVariable = require("./DependenciesBlockVariable");
|
|||
/** @typedef {(d: Dependency) => boolean} DependencyFilterFunction */
|
||||
/** @typedef {import("crypto").Hash} Hash */
|
||||
|
||||
|
||||
class DependenciesBlock {
|
||||
constructor() {
|
||||
/** @type {Dependency[]} */
|
||||
|
@ -67,7 +68,9 @@ class DependenciesBlock {
|
|||
*/
|
||||
removeDependency(dependency) {
|
||||
const idx = this.dependencies.indexOf(dependency);
|
||||
if (idx >= 0) this.dependencies.splice(idx, 1);
|
||||
if (idx >= 0) {
|
||||
this.dependencies.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -47,8 +47,9 @@ class DependenciesBlockVariable {
|
|||
const source = new ReplaceSource(new RawSource(this.expression), null);
|
||||
for (const dep of this.dependencies) {
|
||||
const template = dependencyTemplates.get(dep.constructor);
|
||||
if (!template)
|
||||
if (!template) {
|
||||
throw new Error(`No template for dependency: ${dep.constructor.name}`);
|
||||
}
|
||||
template.apply(dep, source, runtimeTemplate, dependencyTemplates);
|
||||
}
|
||||
return source;
|
||||
|
|
|
@ -20,6 +20,7 @@ class Dependency {
|
|||
constructor() {
|
||||
/** @type {Module|null} */
|
||||
this.module = null;
|
||||
// TODO remove in webpack 5
|
||||
this.weak = false;
|
||||
this.optional = false;
|
||||
this.loc = undefined;
|
||||
|
|
|
@ -20,8 +20,10 @@ class DllPlugin {
|
|||
apply(compiler) {
|
||||
compiler.hooks.entryOption.tap("DllPlugin", (context, entry) => {
|
||||
const itemToPlugin = (item, name) => {
|
||||
if (Array.isArray(item)) return new DllEntryPlugin(context, item, name);
|
||||
else throw new Error("DllPlugin: supply an Array as entry");
|
||||
if (Array.isArray(item)) {
|
||||
return new DllEntryPlugin(context, item, name);
|
||||
}
|
||||
throw new Error("DllPlugin: supply an Array as entry");
|
||||
};
|
||||
if (typeof entry === "object" && !Array.isArray(entry)) {
|
||||
Object.keys(entry).forEach(name => {
|
||||
|
@ -33,7 +35,9 @@ class DllPlugin {
|
|||
return true;
|
||||
});
|
||||
new LibManifestPlugin(this.options).apply(compiler);
|
||||
new FlagInitialModulesAsUsedPlugin("DllPlugin").apply(compiler);
|
||||
if (!this.options.entryOnly) {
|
||||
new FlagInitialModulesAsUsedPlugin("DllPlugin").apply(compiler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
"use strict";
|
||||
|
||||
const parseJson = require("json-parse-better-errors");
|
||||
const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency");
|
||||
const DelegatedModuleFactoryPlugin = require("./DelegatedModuleFactoryPlugin");
|
||||
const ExternalModuleFactoryPlugin = require("./ExternalModuleFactoryPlugin");
|
||||
|
@ -42,7 +43,7 @@ class DllReferencePlugin {
|
|||
params.compilationDependencies.add(manifest);
|
||||
compiler.inputFileSystem.readFile(manifest, (err, result) => {
|
||||
if (err) return callback(err);
|
||||
params["dll reference " + manifest] = JSON.parse(
|
||||
params["dll reference " + manifest] = parseJson(
|
||||
result.toString("utf-8")
|
||||
);
|
||||
return callback();
|
||||
|
|
|
@ -87,7 +87,9 @@ module.exports = DynamicEntryPlugin;
|
|||
* @returns {SingleEntryDependency|MultiEntryDependency} returns dep
|
||||
*/
|
||||
DynamicEntryPlugin.createDependency = (entry, name) => {
|
||||
if (Array.isArray(entry))
|
||||
if (Array.isArray(entry)) {
|
||||
return MultiEntryPlugin.createDependency(entry, name);
|
||||
else return SingleEntryPlugin.createDependency(entry, name);
|
||||
} else {
|
||||
return SingleEntryPlugin.createDependency(entry, name);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -8,10 +8,9 @@ const WebpackError = require("./WebpackError");
|
|||
|
||||
class EntryModuleNotFoundError extends WebpackError {
|
||||
constructor(err) {
|
||||
super();
|
||||
super("Entry module not found: " + err);
|
||||
|
||||
this.name = "EntryModuleNotFoundError";
|
||||
this.message = "Entry module not found: " + err;
|
||||
this.details = err.details;
|
||||
this.error = err;
|
||||
|
||||
|
|
|
@ -10,8 +10,11 @@ const webpackOptionsFlag = "WEBPACK_OPTIONS";
|
|||
|
||||
exports.cutOffByFlag = (stack, flag) => {
|
||||
stack = stack.split("\n");
|
||||
for (let i = 0; i < stack.length; i++)
|
||||
if (stack[i].includes(flag)) stack.length = i;
|
||||
for (let i = 0; i < stack.length; i++) {
|
||||
if (stack[i].includes(flag)) {
|
||||
stack.length = i;
|
||||
}
|
||||
}
|
||||
return stack.join("\n");
|
||||
};
|
||||
|
||||
|
|
|
@ -9,10 +9,11 @@ const SourceMapDevToolModuleOptionsPlugin = require("./SourceMapDevToolModuleOpt
|
|||
|
||||
class EvalSourceMapDevToolPlugin {
|
||||
constructor(options) {
|
||||
if (arguments.length > 1)
|
||||
if (arguments.length > 1) {
|
||||
throw new Error(
|
||||
"EvalSourceMapDevToolPlugin only takes one argument (pass an options object)"
|
||||
);
|
||||
}
|
||||
if (typeof options === "string") {
|
||||
options = {
|
||||
append: options
|
||||
|
|
|
@ -6,15 +6,28 @@
|
|||
|
||||
const { ConcatSource } = require("webpack-sources");
|
||||
|
||||
/** @typedef {import("./Compilation")} Compilation */
|
||||
|
||||
/**
|
||||
* @param {string[]} accessor the accessor to convert to path
|
||||
* @returns {string} the path
|
||||
*/
|
||||
const accessorToObjectAccess = accessor => {
|
||||
return accessor.map(a => `[${JSON.stringify(a)}]`).join("");
|
||||
};
|
||||
|
||||
class ExportPropertyMainTemplatePlugin {
|
||||
/**
|
||||
* @param {string|string[]} property the name of the property to export
|
||||
*/
|
||||
constructor(property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Compilation} compilation the compilation instance
|
||||
* @returns {void}
|
||||
*/
|
||||
apply(compilation) {
|
||||
const { mainTemplate, chunkTemplate } = compilation;
|
||||
|
||||
|
|
|
@ -20,22 +20,28 @@ const isSubset = (biggerSet, subset) => {
|
|||
class FlagDependencyUsagePlugin {
|
||||
apply(compiler) {
|
||||
compiler.hooks.compilation.tap("FlagDependencyUsagePlugin", compilation => {
|
||||
compilation.hooks.optimizeModulesAdvanced.tap(
|
||||
compilation.hooks.optimizeDependencies.tap(
|
||||
"FlagDependencyUsagePlugin",
|
||||
modules => {
|
||||
const processModule = (module, usedExports) => {
|
||||
module.used = true;
|
||||
if (module.usedExports === true) return;
|
||||
else if (usedExports === true) module.usedExports = true;
|
||||
else if (Array.isArray(usedExports)) {
|
||||
if (usedExports === true) {
|
||||
module.usedExports = true;
|
||||
} else if (Array.isArray(usedExports)) {
|
||||
const old = module.usedExports ? module.usedExports.length : -1;
|
||||
module.usedExports = addToSet(
|
||||
module.usedExports || [],
|
||||
usedExports
|
||||
);
|
||||
if (module.usedExports.length === old) return;
|
||||
} else if (Array.isArray(module.usedExports)) return;
|
||||
else module.usedExports = false;
|
||||
if (module.usedExports.length === old) {
|
||||
return;
|
||||
}
|
||||
} else if (Array.isArray(module.usedExports)) {
|
||||
return;
|
||||
} else {
|
||||
module.usedExports = false;
|
||||
}
|
||||
|
||||
// for a module without side effects we stop tracking usage here when no export is used
|
||||
// This module won't be evaluated in this case
|
||||
|
@ -66,6 +72,7 @@ class FlagDependencyUsagePlugin {
|
|||
};
|
||||
|
||||
const processDependency = dep => {
|
||||
// TODO remove dep.getReference existance check in webpack 5
|
||||
const reference = dep.getReference && dep.getReference();
|
||||
if (!reference) return;
|
||||
const module = reference.module;
|
||||
|
@ -86,9 +93,9 @@ class FlagDependencyUsagePlugin {
|
|||
}
|
||||
|
||||
const queue = [];
|
||||
for (const chunk of compilation.chunks) {
|
||||
if (chunk.entryModule) {
|
||||
processModule(chunk.entryModule, true);
|
||||
for (const preparedEntrypoint of compilation._preparedEntrypoints) {
|
||||
if (preparedEntrypoint.module) {
|
||||
processModule(preparedEntrypoint.module, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,30 +47,32 @@ class FunctionModuleTemplatePlugin {
|
|||
if (
|
||||
Array.isArray(module.buildMeta.providedExports) &&
|
||||
module.buildMeta.providedExports.length === 0
|
||||
)
|
||||
) {
|
||||
source.add(Template.toComment("no exports provided") + "\n");
|
||||
else if (Array.isArray(module.buildMeta.providedExports))
|
||||
} else if (Array.isArray(module.buildMeta.providedExports)) {
|
||||
source.add(
|
||||
Template.toComment(
|
||||
"exports provided: " +
|
||||
module.buildMeta.providedExports.join(", ")
|
||||
) + "\n"
|
||||
);
|
||||
else if (module.buildMeta.providedExports)
|
||||
} else if (module.buildMeta.providedExports) {
|
||||
source.add(Template.toComment("no static exports found") + "\n");
|
||||
}
|
||||
if (
|
||||
Array.isArray(module.usedExports) &&
|
||||
module.usedExports.length === 0
|
||||
)
|
||||
) {
|
||||
source.add(Template.toComment("no exports used") + "\n");
|
||||
else if (Array.isArray(module.usedExports))
|
||||
} else if (Array.isArray(module.usedExports)) {
|
||||
source.add(
|
||||
Template.toComment(
|
||||
"exports used: " + module.usedExports.join(", ")
|
||||
) + "\n"
|
||||
);
|
||||
else if (module.usedExports)
|
||||
} else if (module.usedExports) {
|
||||
source.add(Template.toComment("all exports used") + "\n");
|
||||
}
|
||||
if (module.optimizationBailout) {
|
||||
for (const text of module.optimizationBailout) {
|
||||
let code;
|
||||
|
|
|
@ -8,9 +8,8 @@ const WebpackError = require("./WebpackError");
|
|||
module.exports = class HarmonyLinkingError extends WebpackError {
|
||||
/** @param {string} message Error message */
|
||||
constructor(message) {
|
||||
super();
|
||||
super(message);
|
||||
this.name = "HarmonyLinkingError";
|
||||
this.message = message;
|
||||
this.hideStack = true;
|
||||
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
|
|
|
@ -19,13 +19,16 @@ module.exports = function() {
|
|||
var fn = function(request) {
|
||||
if (me.hot.active) {
|
||||
if (installedModules[request]) {
|
||||
if (installedModules[request].parents.indexOf(moduleId) === -1)
|
||||
if (installedModules[request].parents.indexOf(moduleId) === -1) {
|
||||
installedModules[request].parents.push(moduleId);
|
||||
}
|
||||
} else {
|
||||
hotCurrentParents = [moduleId];
|
||||
hotCurrentChildModule = request;
|
||||
}
|
||||
if (me.children.indexOf(request) === -1) me.children.push(request);
|
||||
if (me.children.indexOf(request) === -1) {
|
||||
me.children.push(request);
|
||||
}
|
||||
} else {
|
||||
console.warn(
|
||||
"[HMR] unexpected require(" +
|
||||
|
@ -52,7 +55,8 @@ module.exports = function() {
|
|||
for (var name in $require$) {
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call($require$, name) &&
|
||||
name !== "e"
|
||||
name !== "e" &&
|
||||
name !== "t"
|
||||
) {
|
||||
Object.defineProperty(fn, name, ObjectFactory(name));
|
||||
}
|
||||
|
@ -77,6 +81,10 @@ module.exports = function() {
|
|||
}
|
||||
}
|
||||
};
|
||||
fn.t = function(value, mode) {
|
||||
if (mode & 1) value = fn(value);
|
||||
return $require$.t(value, mode & ~1);
|
||||
};
|
||||
return fn;
|
||||
}
|
||||
|
||||
|
@ -167,8 +175,9 @@ module.exports = function() {
|
|||
}
|
||||
|
||||
function hotCheck(apply) {
|
||||
if (hotStatus !== "idle")
|
||||
if (hotStatus !== "idle") {
|
||||
throw new Error("check() is only allowed in idle status");
|
||||
}
|
||||
hotApplyOnUpdate = apply;
|
||||
hotSetStatus("check");
|
||||
return hotDownloadManifest(hotRequestTimeout).then(function(update) {
|
||||
|
|
|
@ -255,8 +255,11 @@ module.exports = class HotModuleReplacementPlugin {
|
|||
mainTemplate.hooks.currentHash.tap(
|
||||
"HotModuleReplacementPlugin",
|
||||
(_, length) => {
|
||||
if (isFinite(length)) return `hotCurrentHash.substr(0, ${length})`;
|
||||
else return "hotCurrentHash";
|
||||
if (isFinite(length)) {
|
||||
return `hotCurrentHash.substr(0, ${length})`;
|
||||
} else {
|
||||
return "hotCurrentHash";
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -301,21 +304,24 @@ module.exports = class HotModuleReplacementPlugin {
|
|||
}
|
||||
);
|
||||
// TODO webpack 5: refactor this, no custom hooks
|
||||
if (!parser.hooks.hotAcceptCallback)
|
||||
if (!parser.hooks.hotAcceptCallback) {
|
||||
parser.hooks.hotAcceptCallback = new SyncBailHook([
|
||||
"expression",
|
||||
"requests"
|
||||
]);
|
||||
if (!parser.hooks.hotAcceptWithoutCallback)
|
||||
}
|
||||
if (!parser.hooks.hotAcceptWithoutCallback) {
|
||||
parser.hooks.hotAcceptWithoutCallback = new SyncBailHook([
|
||||
"expression",
|
||||
"requests"
|
||||
]);
|
||||
}
|
||||
parser.hooks.call
|
||||
.for("module.hot.accept")
|
||||
.tap("HotModuleReplacementPlugin", expr => {
|
||||
if (!parser.state.compilation.hotUpdateChunkTemplate)
|
||||
if (!parser.state.compilation.hotUpdateChunkTemplate) {
|
||||
return false;
|
||||
}
|
||||
if (expr.arguments.length >= 1) {
|
||||
const arg = parser.evaluateExpression(expr.arguments[0]);
|
||||
let params = [];
|
||||
|
@ -355,8 +361,9 @@ module.exports = class HotModuleReplacementPlugin {
|
|||
parser.hooks.call
|
||||
.for("module.hot.decline")
|
||||
.tap("HotModuleReplacementPlugin", expr => {
|
||||
if (!parser.state.compilation.hotUpdateChunkTemplate)
|
||||
if (!parser.state.compilation.hotUpdateChunkTemplate) {
|
||||
return false;
|
||||
}
|
||||
if (expr.arguments.length === 1) {
|
||||
const arg = parser.evaluateExpression(expr.arguments[0]);
|
||||
let params = [];
|
||||
|
|
|
@ -143,10 +143,11 @@ class JavascriptGenerator {
|
|||
|
||||
sourceDependency(dependency, dependencyTemplates, source, runtimeTemplate) {
|
||||
const template = dependencyTemplates.get(dependency.constructor);
|
||||
if (!template)
|
||||
if (!template) {
|
||||
throw new Error(
|
||||
"No template for dependency: " + dependency.constructor.name
|
||||
);
|
||||
}
|
||||
template.apply(dependency, source, runtimeTemplate, dependencyTemplates);
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue