mirror of https://github.com/webpack/webpack.git
Merge branch 'master' into patch-2
This commit is contained in:
commit
c3d1806329
|
@ -8,15 +8,11 @@ trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
max_line_length = 233
|
max_line_length = 233
|
||||||
|
|
||||||
[*.json]
|
[.prettierrc]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
[*.yml]
|
[*.{yml,yaml,json}]
|
||||||
indent_style = space
|
|
||||||
indent_size = 2
|
|
||||||
|
|
||||||
[*.yaml]
|
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
|
72
.eslintrc.js
72
.eslintrc.js
|
@ -1,15 +1,16 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"root": true,
|
root: true,
|
||||||
"plugins": ["node"],
|
plugins: ["prettier", "node"],
|
||||||
"extends": ["eslint:recommended", "plugin:node/recommended"],
|
extends: ["eslint:recommended", "plugin:node/recommended"],
|
||||||
"env": {
|
env: {
|
||||||
"node": true,
|
node: true,
|
||||||
"es6": true,
|
es6: true
|
||||||
"mocha": true,
|
|
||||||
},
|
},
|
||||||
"parserOptions": { "ecmaVersion": 2017 },
|
parserOptions: {
|
||||||
"rules": {
|
ecmaVersion: 2017
|
||||||
"quotes": ["error", "double"],
|
},
|
||||||
|
rules: {
|
||||||
|
"prettier/prettier": "error",
|
||||||
"no-undef": "error",
|
"no-undef": "error",
|
||||||
"no-extra-semi": "error",
|
"no-extra-semi": "error",
|
||||||
"semi": "error",
|
"semi": "error",
|
||||||
|
@ -21,51 +22,34 @@ module.exports = {
|
||||||
"brace-style": "error",
|
"brace-style": "error",
|
||||||
"eol-last": "error",
|
"eol-last": "error",
|
||||||
"no-extra-bind": "warn",
|
"no-extra-bind": "warn",
|
||||||
"no-empty": "off",
|
|
||||||
"no-multiple-empty-lines": "error",
|
|
||||||
"no-multi-spaces": "error",
|
|
||||||
"no-process-exit": "warn",
|
"no-process-exit": "warn",
|
||||||
"space-in-parens": "error",
|
|
||||||
"no-trailing-spaces": "error",
|
|
||||||
"no-use-before-define": "off",
|
"no-use-before-define": "off",
|
||||||
"no-unused-vars": ["error", { "args": "none" }],
|
"no-unused-vars": ["error", { args: "none" }],
|
||||||
"key-spacing": "error",
|
|
||||||
"space-infix-ops": "error",
|
|
||||||
"no-unsafe-negation": "error",
|
"no-unsafe-negation": "error",
|
||||||
"no-loop-func": "warn",
|
"no-loop-func": "warn",
|
||||||
"space-before-function-paren": ["error", "never"],
|
|
||||||
"space-before-blocks": "error",
|
|
||||||
"object-curly-spacing": ["error", "always"],
|
|
||||||
"indent": "off",
|
"indent": "off",
|
||||||
"keyword-spacing": ["error", {
|
|
||||||
"after": false,
|
|
||||||
"overrides": {
|
|
||||||
"const": { "after": true },
|
|
||||||
"try": { "after": true },
|
|
||||||
"else": { "after": true },
|
|
||||||
"throw": { "after": true },
|
|
||||||
"case": { "after": true },
|
|
||||||
"return": { "after": true },
|
|
||||||
"finally": { "after": true },
|
|
||||||
"do": { "after": true },
|
|
||||||
"of": { "after": true }
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
"no-console": "off",
|
"no-console": "off",
|
||||||
"valid-jsdoc": "error",
|
"valid-jsdoc": "error",
|
||||||
"node/no-unsupported-features": "error",
|
"node/no-unsupported-features": "error",
|
||||||
"node/no-deprecated-api": "error",
|
"node/no-deprecated-api": "error",
|
||||||
"node/no-missing-import": "error",
|
"node/no-missing-import": "error",
|
||||||
"node/no-missing-require": [
|
"node/no-missing-require": ["error", { allowModules: ["webpack"] }],
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"allowModules": [
|
|
||||||
"webpack"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"node/no-unpublished-bin": "error",
|
"node/no-unpublished-bin": "error",
|
||||||
"node/no-unpublished-require": "error",
|
"node/no-unpublished-require": "error",
|
||||||
"node/process-exit-as-throw": "error"
|
"node/process-exit-as-throw": "error"
|
||||||
}
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ["lib/**/*.runtime.js", "buildin/*.js", "hot/*.js"],
|
||||||
|
env: {
|
||||||
|
es6: false
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
Promise: false,
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
{
|
|
||||||
"js": {
|
|
||||||
"allowed_file_extensions": ["js", "json", "jshintrc", "jsbeautifyrc"],
|
|
||||||
"brace_style": "collapse",
|
|
||||||
"break_chained_methods": false,
|
|
||||||
"e4x": true,
|
|
||||||
"eval_code": false,
|
|
||||||
"end_with_newline": true,
|
|
||||||
"indent_char": "\t",
|
|
||||||
"indent_level": 0,
|
|
||||||
"indent_size": 1,
|
|
||||||
"indent_with_tabs": true,
|
|
||||||
"jslint_happy": false,
|
|
||||||
"jslint_happy_align_switch_case": true,
|
|
||||||
"space_after_anon_function": false,
|
|
||||||
"keep_array_indentation": false,
|
|
||||||
"keep_function_indentation": false,
|
|
||||||
"max_preserve_newlines": 2,
|
|
||||||
"preserve_newlines": true,
|
|
||||||
"space_before_conditional": false,
|
|
||||||
"space_in_paren": false,
|
|
||||||
"unescape_strings": false,
|
|
||||||
"wrap_line_length": 0
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": true
|
||||||
|
}
|
|
@ -31,20 +31,7 @@ If you have created your own loader/plugin please include it on the relevant doc
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
```bash
|
[Setup your local webpack repository](_SETUP.md)
|
||||||
git clone https://github.com/webpack/webpack.git
|
|
||||||
cd webpack
|
|
||||||
npm install -g yarn
|
|
||||||
yarn
|
|
||||||
yarn link
|
|
||||||
yarn link webpack
|
|
||||||
```
|
|
||||||
|
|
||||||
To run the entire test suite use:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yarn test
|
|
||||||
```
|
|
||||||
|
|
||||||
## Submitting Changes
|
## Submitting Changes
|
||||||
|
|
||||||
|
|
12
README.md
12
README.md
|
@ -1,6 +1,6 @@
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://github.com/webpack/webpack">
|
<a href="https://github.com/webpack/webpack">
|
||||||
<img width="200" heigth="200" src="https://webpack.js.org/assets/icon-square-big.svg">
|
<img width="200" height="200" src="https://webpack.js.org/assets/icon-square-big.svg">
|
||||||
</a>
|
</a>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
[![licenses][licenses]][licenses-url]
|
[![licenses][licenses]][licenses-url]
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<a href="https://npmjs.com/package/webpack">
|
<a href="https://npmcharts.com/compare/webpack?minimal=true">
|
||||||
<img src="https://img.shields.io/npm/dm/webpack.svg">
|
<img src="https://img.shields.io/npm/dm/webpack.svg">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://opencollective.com/webpack#backer">
|
<a href="https://opencollective.com/webpack#backer">
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
<h1>webpack</h1>
|
<h1>webpack</h1>
|
||||||
<p>
|
<p>
|
||||||
webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.
|
webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.
|
||||||
<p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 align="center">Install</h2>
|
<h2 align="center">Install</h2>
|
||||||
|
@ -81,14 +81,12 @@ within webpack itself use this plugin interface. This makes webpack very
|
||||||
|
|
||||||
|Name|Status|Description|
|
|Name|Status|Description|
|
||||||
|:--:|:----:|:----------|
|
|:--:|:----:|:----------|
|
||||||
|[common-chunks-webpack-plugin][common]|![common-npm]|Generates chunks of common modules shared between entry points and splits them into separate bundles (e.g vendor.bundle.js && app.bundle.js)|
|
|
||||||
|[extract-text-webpack-plugin][extract]|![extract-npm]|Extracts Text (CSS) from your bundles into a separate file (app.bundle.css)|
|
|[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|
|
|[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|
|
|[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|
|
|[html-webpack-plugin][html-plugin]|![html-plugin-npm]| Simplifies creation of HTML files (`index.html`) to serve your bundles|
|
||||||
|
|
||||||
|
|
||||||
[common]: https://github.com/webpack/webpack/blob/master/lib/optimize/CommonsChunkPlugin.js
|
|
||||||
[common-npm]: https://img.shields.io/npm/v/webpack.svg
|
[common-npm]: https://img.shields.io/npm/v/webpack.svg
|
||||||
[extract]: https://github.com/webpack/extract-text-webpack-plugin
|
[extract]: https://github.com/webpack/extract-text-webpack-plugin
|
||||||
[extract-npm]: https://img.shields.io/npm/v/extract-text-webpack-plugin.svg
|
[extract-npm]: https://img.shields.io/npm/v/extract-text-webpack-plugin.svg
|
||||||
|
@ -184,7 +182,7 @@ or are automatically applied via regex from your webpack configuration.
|
||||||
|
|
||||||
|Name|Status|Description|
|
|Name|Status|Description|
|
||||||
|:--:|:----:|:----------|
|
|:--:|:----:|:----------|
|
||||||
|<a href="https://github.com/webpack/style-loader">`<style>`|![style-npm]|Add exports of a module as style to DOM|
|
|<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/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/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/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|
|
||||||
|
@ -344,7 +342,7 @@ If you have discovered a 🐜 or have a feature suggestion, feel free to create
|
||||||
<a href="https://github.com/spacek33z">Kees Kluskens</a>
|
<a href="https://github.com/spacek33z">Kees Kluskens</a>
|
||||||
<p>Development</p>
|
<p>Development</p>
|
||||||
<br>
|
<br>
|
||||||
<p>Sponsor<p>
|
<p>Sponsor</p>
|
||||||
<a href="https://codeyellow.nl/">
|
<a href="https://codeyellow.nl/">
|
||||||
<img height="15px" src="https://cloud.githubusercontent.com/assets/1365881/20286583/ad62eb04-aac7-11e6-9c14-a0fef35b9b56.png">
|
<img height="15px" src="https://cloud.githubusercontent.com/assets/1365881/20286583/ad62eb04-aac7-11e6-9c14-a0fef35b9b56.png">
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Setup
|
||||||
|
|
||||||
|
Setup your local webpack repository
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/webpack/webpack.git
|
||||||
|
cd webpack
|
||||||
|
npm install -g yarn
|
||||||
|
yarn install
|
||||||
|
yarn link
|
||||||
|
yarn link webpack
|
||||||
|
```
|
||||||
|
|
||||||
|
To run the entire test suite use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
yarn test
|
||||||
|
```
|
|
@ -4,15 +4,17 @@ let webpackCliInstalled = false;
|
||||||
try {
|
try {
|
||||||
require.resolve("webpack-cli");
|
require.resolve("webpack-cli");
|
||||||
webpackCliInstalled = true;
|
webpackCliInstalled = true;
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
webpackCliInstalled = false;
|
webpackCliInstalled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(webpackCliInstalled) {
|
if (webpackCliInstalled) {
|
||||||
require("webpack-cli"); // eslint-disable-line node/no-missing-require, node/no-extraneous-require, node/no-unpublished-require
|
require("webpack-cli"); // eslint-disable-line node/no-missing-require, node/no-extraneous-require, node/no-unpublished-require
|
||||||
} else {
|
} else {
|
||||||
console.error("The CLI moved into a separate package: webpack-cli.");
|
console.error("The CLI moved into a separate package: webpack-cli.");
|
||||||
console.error("Please install 'webpack-cli' in addition to webpack itself to use the CLI.");
|
console.error(
|
||||||
|
"Please install 'webpack-cli' in addition to webpack itself to use the CLI."
|
||||||
|
);
|
||||||
console.error("-> When using npm: npm install webpack-cli -D");
|
console.error("-> When using npm: npm install webpack-cli -D");
|
||||||
console.error("-> When using yarn: yarn add webpack-cli -D");
|
console.error("-> When using yarn: yarn add webpack-cli -D");
|
||||||
process.exitCode = 1;
|
process.exitCode = 1;
|
||||||
|
|
|
@ -7,11 +7,10 @@ g = (function() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// This works if eval is allowed (see CSP)
|
// This works if eval is allowed (see CSP)
|
||||||
g = g || Function("return this")() || (1,eval)("this");
|
g = g || Function("return this")() || (1, eval)("this");
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
// This works if the window reference is available
|
// This works if the window reference is available
|
||||||
if(typeof window === "object")
|
if (typeof window === "object") g = window;
|
||||||
g = window;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// g can still be undefined, but nothing to do about it...
|
// g can still be undefined, but nothing to do about it...
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
module.exports = function(originalModule) {
|
module.exports = function(originalModule) {
|
||||||
if(!originalModule.webpackPolyfill) {
|
if (!originalModule.webpackPolyfill) {
|
||||||
var module = Object.create(originalModule);
|
var module = Object.create(originalModule);
|
||||||
// module.parent = undefined by default
|
// module.parent = undefined by default
|
||||||
if(!module.children) module.children = [];
|
if (!module.children) module.children = [];
|
||||||
Object.defineProperty(module, "loaded", {
|
Object.defineProperty(module, "loaded", {
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
get: function() {
|
get: function() {
|
||||||
|
@ -16,7 +16,7 @@ module.exports = function(originalModule) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Object.defineProperty(module, "exports", {
|
Object.defineProperty(module, "exports", {
|
||||||
enumerable: true,
|
enumerable: true
|
||||||
});
|
});
|
||||||
module.webpackPolyfill = 1;
|
module.webpackPolyfill = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
module.exports = function(module) {
|
module.exports = function(module) {
|
||||||
if(!module.webpackPolyfill) {
|
if (!module.webpackPolyfill) {
|
||||||
module.deprecate = function() {};
|
module.deprecate = function() {};
|
||||||
module.paths = [];
|
module.paths = [];
|
||||||
// module.parent = undefined by default
|
// module.parent = undefined by default
|
||||||
if(!module.children) module.children = [];
|
if (!module.children) module.children = [];
|
||||||
Object.defineProperty(module, "loaded", {
|
Object.defineProperty(module, "loaded", {
|
||||||
enumerable: true,
|
enumerable: true,
|
||||||
get: function() {
|
get: function() {
|
||||||
|
|
|
@ -95,12 +95,12 @@ module.exports = {
|
||||||
/******/ var result;
|
/******/ var result;
|
||||||
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
||||||
/******/ var deferredModule = deferredModules[i];
|
/******/ var deferredModule = deferredModules[i];
|
||||||
/******/ var fullfilled = true;
|
/******/ var fulfilled = true;
|
||||||
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
||||||
/******/ var depId = deferredModule[j];
|
/******/ var depId = deferredModule[j];
|
||||||
/******/ if(installedChunks[depId] !== 0) fullfilled = false;
|
/******/ if(installedChunks[depId] !== 0) fulfilled = false;
|
||||||
/******/ }
|
/******/ }
|
||||||
/******/ if(fullfilled) {
|
/******/ if(fulfilled) {
|
||||||
/******/ deferredModules.splice(i--, 1);
|
/******/ deferredModules.splice(i--, 1);
|
||||||
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
||||||
/******/ }
|
/******/ }
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// mode: "development || "production",
|
// mode: "development || "production",
|
||||||
module: {
|
module: {
|
||||||
rules: [{
|
rules: [
|
||||||
test: /\.coffee$/,
|
{
|
||||||
loader: "coffee-loader"
|
test: /\.coffee$/,
|
||||||
}]
|
loader: "coffee-loader"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: [".web.coffee", ".web.js", ".coffee", ".js"]
|
extensions: [".web.coffee", ".web.js", ".coffee", ".js"]
|
||||||
|
|
|
@ -178,12 +178,12 @@ module.exports = "utility3";
|
||||||
/******/ var result;
|
/******/ var result;
|
||||||
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
||||||
/******/ var deferredModule = deferredModules[i];
|
/******/ var deferredModule = deferredModules[i];
|
||||||
/******/ var fullfilled = true;
|
/******/ var fulfilled = true;
|
||||||
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
||||||
/******/ var depId = deferredModule[j];
|
/******/ var depId = deferredModule[j];
|
||||||
/******/ if(installedChunks[depId] !== 0) fullfilled = false;
|
/******/ if(installedChunks[depId] !== 0) fulfilled = false;
|
||||||
/******/ }
|
/******/ }
|
||||||
/******/ if(fullfilled) {
|
/******/ if(fulfilled) {
|
||||||
/******/ deferredModules.splice(i--, 1);
|
/******/ deferredModules.splice(i--, 1);
|
||||||
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
||||||
/******/ }
|
/******/ }
|
||||||
|
@ -351,12 +351,12 @@ module.exports = "utility1";
|
||||||
/******/ var result;
|
/******/ var result;
|
||||||
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
||||||
/******/ var deferredModule = deferredModules[i];
|
/******/ var deferredModule = deferredModules[i];
|
||||||
/******/ var fullfilled = true;
|
/******/ var fulfilled = true;
|
||||||
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
||||||
/******/ var depId = deferredModule[j];
|
/******/ var depId = deferredModule[j];
|
||||||
/******/ if(installedChunks[depId] !== 0) fullfilled = false;
|
/******/ if(installedChunks[depId] !== 0) fulfilled = false;
|
||||||
/******/ }
|
/******/ }
|
||||||
/******/ if(fullfilled) {
|
/******/ if(fulfilled) {
|
||||||
/******/ deferredModules.splice(i--, 1);
|
/******/ deferredModules.splice(i--, 1);
|
||||||
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
||||||
/******/ }
|
/******/ }
|
||||||
|
@ -510,12 +510,12 @@ module.exports = "pageB";
|
||||||
/******/ var result;
|
/******/ var result;
|
||||||
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
||||||
/******/ var deferredModule = deferredModules[i];
|
/******/ var deferredModule = deferredModules[i];
|
||||||
/******/ var fullfilled = true;
|
/******/ var fulfilled = true;
|
||||||
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
||||||
/******/ var depId = deferredModule[j];
|
/******/ var depId = deferredModule[j];
|
||||||
/******/ if(installedChunks[depId] !== 0) fullfilled = false;
|
/******/ if(installedChunks[depId] !== 0) fulfilled = false;
|
||||||
/******/ }
|
/******/ }
|
||||||
/******/ if(fullfilled) {
|
/******/ if(fulfilled) {
|
||||||
/******/ deferredModules.splice(i--, 1);
|
/******/ deferredModules.splice(i--, 1);
|
||||||
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
||||||
/******/ }
|
/******/ }
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
This example illustrates how common modules from deep ancestors of an entry point can be split into a seperate common chunk
|
This example illustrates how common modules from deep ancestors of an entry point can be split into a separate common chunk
|
||||||
|
|
||||||
* `pageA` and `pageB` are dynamically required
|
* `pageA` and `pageB` are dynamically required
|
||||||
* `pageC` and `pageA` both require the `reusableComponent`
|
* `pageC` and `pageA` both require the `reusableComponent`
|
||||||
|
@ -93,7 +93,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
optimization: {
|
optimization: {
|
||||||
splitChunks: {
|
splitChunks: {
|
||||||
minSize: 0 // This example is too small, in pratice you can use the defaults
|
minSize: 0 // This example is too small, in practice you can use the defaults
|
||||||
},
|
},
|
||||||
occurrenceOrder: true // To keep filename consistent between different modes (for example building only)
|
occurrenceOrder: true // To keep filename consistent between different modes (for example building only)
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
This example illustrates how common modules from deep ancestors of an entry point can be split into a seperate common chunk
|
This example illustrates how common modules from deep ancestors of an entry point can be split into a separate common chunk
|
||||||
|
|
||||||
* `pageA` and `pageB` are dynamically required
|
* `pageA` and `pageB` are dynamically required
|
||||||
* `pageC` and `pageA` both require the `reusableComponent`
|
* `pageC` and `pageA` both require the `reusableComponent`
|
||||||
|
|
|
@ -8,7 +8,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
optimization: {
|
optimization: {
|
||||||
splitChunks: {
|
splitChunks: {
|
||||||
minSize: 0 // This example is too small, in pratice you can use the defaults
|
minSize: 0 // This example is too small, in practice you can use the defaults
|
||||||
},
|
},
|
||||||
occurrenceOrder: true // To keep filename consistent between different modes (for example building only)
|
occurrenceOrder: true // To keep filename consistent between different modes (for example building only)
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
This is the vendor build part.
|
This is the vendor build part.
|
||||||
|
|
||||||
It's built separatly 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 vendors has changed and not while 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.
|
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.
|
This is the vendor build part.
|
||||||
|
|
||||||
It's built separatly 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 vendors has changed and not while 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.
|
The DllPlugin in combination with the `output.library` option exposes the internal require function as global variable in the target environment.
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,12 @@ module.exports = {
|
||||||
output: {
|
output: {
|
||||||
filename: "vendor.js", // best use [hash] here too
|
filename: "vendor.js", // best use [hash] here too
|
||||||
path: path.resolve(__dirname, "dist"),
|
path: path.resolve(__dirname, "dist"),
|
||||||
library: "vendor_lib_[hash]",
|
library: "vendor_lib_[hash]"
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.DllPlugin({
|
new webpack.DllPlugin({
|
||||||
name: "vendor_lib_[hash]",
|
name: "vendor_lib_[hash]",
|
||||||
path: path.resolve(__dirname, "dist/vendor-manifest.json"),
|
path: path.resolve(__dirname, "dist/vendor-manifest.json")
|
||||||
}),
|
})
|
||||||
],
|
]
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,12 +7,12 @@ module.exports = {
|
||||||
entry: "./example-app",
|
entry: "./example-app",
|
||||||
output: {
|
output: {
|
||||||
filename: "app.js",
|
filename: "app.js",
|
||||||
path: path.resolve(__dirname, "dist"),
|
path: path.resolve(__dirname, "dist")
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.DllReferencePlugin({
|
new webpack.DllReferencePlugin({
|
||||||
context: ".",
|
context: ".",
|
||||||
manifest: require("../0-vendor/dist/vendor-manifest.json"), // eslint-disable-line
|
manifest: require("../0-vendor/dist/vendor-manifest.json") // eslint-disable-line
|
||||||
}),
|
})
|
||||||
],
|
]
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var webpack = require("../../");
|
var webpack = require("../../");
|
||||||
module.exports = [
|
module.exports = [
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "vendor",
|
name: "vendor",
|
||||||
// mode: "development || "production",
|
// mode: "development || "production",
|
||||||
|
@ -38,5 +37,4 @@ module.exports = [
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -6,7 +6,7 @@ module.exports = {
|
||||||
externals: [
|
externals: [
|
||||||
"add",
|
"add",
|
||||||
{
|
{
|
||||||
"subtract": {
|
subtract: {
|
||||||
root: "subtract",
|
root: "subtract",
|
||||||
commonjs2: "./subtract",
|
commonjs2: "./subtract",
|
||||||
commonjs: ["./math", "subtract"],
|
commonjs: ["./math", "subtract"],
|
||||||
|
|
|
@ -16,7 +16,7 @@ The example entry references two chunks:
|
||||||
|
|
||||||
These chunks share modules `a` and `b`. The optimization extract these into chunk Z:
|
These chunks share modules `a` and `b`. The optimization extract these into chunk Z:
|
||||||
|
|
||||||
Note: Actually the optimization compare size of chunk Z to some minimum value, but this is disabled from this example. In pratice there is no configuration needed for this.
|
Note: Actually the optimization compare size of chunk Z to some minimum value, but this is disabled from this example. In practice there is no configuration needed for this.
|
||||||
|
|
||||||
* entry chunk
|
* entry chunk
|
||||||
* async require -> chunk X & Z
|
* async require -> chunk X & Z
|
||||||
|
|
|
@ -16,7 +16,7 @@ The example entry references two chunks:
|
||||||
|
|
||||||
These chunks share modules `a` and `b`. The optimization extract these into chunk Z:
|
These chunks share modules `a` and `b`. The optimization extract these into chunk Z:
|
||||||
|
|
||||||
Note: Actually the optimization compare size of chunk Z to some minimum value, but this is disabled from this example. In pratice there is no configuration needed for this.
|
Note: Actually the optimization compare size of chunk Z to some minimum value, but this is disabled from this example. In practice there is no configuration needed for this.
|
||||||
|
|
||||||
* entry chunk
|
* entry chunk
|
||||||
* async require -> chunk X & Z
|
* async require -> chunk X & Z
|
||||||
|
|
|
@ -29,7 +29,7 @@ exports.readFile = function() {};
|
||||||
// using module.exports would be equivalent,
|
// using module.exports would be equivalent,
|
||||||
// webpack doesn't care which syntax is used
|
// webpack doesn't care which syntax is used
|
||||||
|
|
||||||
// AMD modules are also possible and equvivalent to CommonJs modules
|
// AMD modules are also possible and equivalent to CommonJs modules
|
||||||
```
|
```
|
||||||
|
|
||||||
# reexport-commonjs.js
|
# reexport-commonjs.js
|
||||||
|
@ -192,7 +192,7 @@ exports.readFile = function() {};
|
||||||
// using module.exports would be equivalent,
|
// using module.exports would be equivalent,
|
||||||
// webpack doesn't care which syntax is used
|
// webpack doesn't care which syntax is used
|
||||||
|
|
||||||
// AMD modules are also possible and equvivalent to CommonJs modules
|
// AMD modules are also possible and equivalent to CommonJs modules
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
|
@ -4,4 +4,4 @@ exports.readFile = function() {};
|
||||||
// using module.exports would be equivalent,
|
// using module.exports would be equivalent,
|
||||||
// webpack doesn't care which syntax is used
|
// webpack doesn't care which syntax is used
|
||||||
|
|
||||||
// AMD modules are also possible and equvivalent to CommonJs modules
|
// AMD modules are also possible and equivalent to CommonJs modules
|
||||||
|
|
|
@ -214,12 +214,12 @@ module.exports = webpackAsyncContext;
|
||||||
/******/ var result;
|
/******/ var result;
|
||||||
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
||||||
/******/ var deferredModule = deferredModules[i];
|
/******/ var deferredModule = deferredModules[i];
|
||||||
/******/ var fullfilled = true;
|
/******/ var fulfilled = true;
|
||||||
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
||||||
/******/ var depId = deferredModule[j];
|
/******/ var depId = deferredModule[j];
|
||||||
/******/ if(installedChunks[depId] !== 0) fullfilled = false;
|
/******/ if(installedChunks[depId] !== 0) fulfilled = false;
|
||||||
/******/ }
|
/******/ }
|
||||||
/******/ if(fullfilled) {
|
/******/ if(fulfilled) {
|
||||||
/******/ deferredModules.splice(i--, 1);
|
/******/ deferredModules.splice(i--, 1);
|
||||||
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
||||||
/******/ }
|
/******/ }
|
||||||
|
|
|
@ -5,7 +5,7 @@ module.exports = {
|
||||||
// The entry points for the pages
|
// The entry points for the pages
|
||||||
// They also contains router
|
// They also contains router
|
||||||
pageA: ["./aEntry", "./router"],
|
pageA: ["./aEntry", "./router"],
|
||||||
pageB: ["./bEntry", "./router"],
|
pageB: ["./bEntry", "./router"]
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: path.join(__dirname, "dist"),
|
path: path.join(__dirname, "dist"),
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var I18nPlugin = require("i18n-webpack-plugin");
|
var I18nPlugin = require("i18n-webpack-plugin");
|
||||||
var languages = {
|
var languages = {
|
||||||
"en": null,
|
en: null,
|
||||||
"de": require("./de.json")
|
de: require("./de.json")
|
||||||
};
|
};
|
||||||
module.exports = Object.keys(languages).map(function(language) {
|
module.exports = Object.keys(languages).map(function(language) {
|
||||||
return {
|
return {
|
||||||
|
@ -13,10 +13,6 @@ module.exports = Object.keys(languages).map(function(language) {
|
||||||
path: path.join(__dirname, "dist"),
|
path: path.join(__dirname, "dist"),
|
||||||
filename: language + ".output.js"
|
filename: language + ".output.js"
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [new I18nPlugin(languages[language])]
|
||||||
new I18nPlugin(
|
|
||||||
languages[language]
|
|
||||||
)
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// mode: "development || "production",
|
// mode: "development || "production",
|
||||||
module: {
|
module: {
|
||||||
rules: [{
|
rules: [
|
||||||
test: /\.css$/,
|
{
|
||||||
loader: "css-loader"
|
test: /\.css$/,
|
||||||
}]
|
loader: "css-loader"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var webpack = require("../../");
|
var webpack = require("../../");
|
||||||
module.exports = [
|
module.exports = [
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "mobile",
|
name: "mobile",
|
||||||
// mode: "development || "production",
|
// mode: "development || "production",
|
||||||
|
@ -31,5 +30,4 @@ module.exports = [
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -9,10 +9,10 @@ You can use
|
||||||
You can see the output files:
|
You can see the output files:
|
||||||
|
|
||||||
* `commons.js` contains:
|
* `commons.js` contains:
|
||||||
* the module system
|
|
||||||
* chunk loading logic
|
|
||||||
* module `common.js` which is used in both pages
|
* module `common.js` which is used in both pages
|
||||||
* `pageA.js` contains: (`pageB.js` is similar)
|
* `pageA.js` contains: (`pageB.js` is similar)
|
||||||
|
* the module system
|
||||||
|
* chunk loading logic
|
||||||
* the entry point `pageA.js`
|
* the entry point `pageA.js`
|
||||||
* it would contain any other module that is only used by `pageA`
|
* it would contain any other module that is only used by `pageA`
|
||||||
* `0.chunk.js` is an additional chunk which is used by both pages. It contains:
|
* `0.chunk.js` is an additional chunk which is used by both pages. It contains:
|
||||||
|
@ -143,12 +143,12 @@ module.exports = "Common";
|
||||||
/******/ var result;
|
/******/ var result;
|
||||||
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
||||||
/******/ var deferredModule = deferredModules[i];
|
/******/ var deferredModule = deferredModules[i];
|
||||||
/******/ var fullfilled = true;
|
/******/ var fulfilled = true;
|
||||||
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
||||||
/******/ var depId = deferredModule[j];
|
/******/ var depId = deferredModule[j];
|
||||||
/******/ if(installedChunks[depId] !== 0) fullfilled = false;
|
/******/ if(installedChunks[depId] !== 0) fulfilled = false;
|
||||||
/******/ }
|
/******/ }
|
||||||
/******/ if(fullfilled) {
|
/******/ if(fulfilled) {
|
||||||
/******/ deferredModules.splice(i--, 1);
|
/******/ deferredModules.splice(i--, 1);
|
||||||
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
||||||
/******/ }
|
/******/ }
|
||||||
|
@ -366,12 +366,12 @@ __webpack_require__.e(/*! AMD require */ 0).then(function() { var __WEBPACK_AMD_
|
||||||
/******/ var result;
|
/******/ var result;
|
||||||
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
/******/ for(var i = 0; i < deferredModules.length; i++) {
|
||||||
/******/ var deferredModule = deferredModules[i];
|
/******/ var deferredModule = deferredModules[i];
|
||||||
/******/ var fullfilled = true;
|
/******/ var fulfilled = true;
|
||||||
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
/******/ for(var j = 1; j < deferredModule.length; j++) {
|
||||||
/******/ var depId = deferredModule[j];
|
/******/ var depId = deferredModule[j];
|
||||||
/******/ if(installedChunks[depId] !== 0) fullfilled = false;
|
/******/ if(installedChunks[depId] !== 0) fulfilled = false;
|
||||||
/******/ }
|
/******/ }
|
||||||
/******/ if(fullfilled) {
|
/******/ if(fulfilled) {
|
||||||
/******/ deferredModules.splice(i--, 1);
|
/******/ deferredModules.splice(i--, 1);
|
||||||
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
|
||||||
/******/ }
|
/******/ }
|
||||||
|
@ -572,7 +572,7 @@ module.exports = function(msg) {
|
||||||
|
|
||||||
```
|
```
|
||||||
Hash: 0a1b2c3d4e5f6a7b8c9d
|
Hash: 0a1b2c3d4e5f6a7b8c9d
|
||||||
Version: webpack 4.0.0-beta.2
|
Version: webpack 4.0.0-beta.1
|
||||||
Asset Size Chunks Chunk Names
|
Asset Size Chunks Chunk Names
|
||||||
0.js 363 bytes 0 [emitted]
|
0.js 363 bytes 0 [emitted]
|
||||||
commons.js 267 bytes 1 [emitted] commons
|
commons.js 267 bytes 1 [emitted] commons
|
||||||
|
@ -588,8 +588,8 @@ chunk {0} 0.js 91 bytes <{1}> <{2}> <{3}> [rendered]
|
||||||
cjs require ./shared [2] ./pageB.js 3:14-33
|
cjs require ./shared [2] ./pageB.js 3:14-33
|
||||||
amd require ./shared [3] ./pageA.js 2:0-4:2
|
amd require ./shared [3] ./pageA.js 2:0-4:2
|
||||||
chunk {1} commons.js (commons) 26 bytes ={2}= ={3}= >{0}< [initial] [rendered] split chunk (cache group: commons) (name: commons)
|
chunk {1} commons.js (commons) 26 bytes ={2}= ={3}= >{0}< [initial] [rendered] split chunk (cache group: commons) (name: commons)
|
||||||
> ./pageA pageA
|
|
||||||
> ./pageB pageB
|
> ./pageB pageB
|
||||||
|
> ./pageA pageA
|
||||||
[1] ./common.js 26 bytes {1} [built]
|
[1] ./common.js 26 bytes {1} [built]
|
||||||
cjs require ./common [0] ./shared.js 1:13-32
|
cjs require ./common [0] ./shared.js 1:13-32
|
||||||
cjs require ./common [2] ./pageB.js 1:13-32
|
cjs require ./common [2] ./pageB.js 1:13-32
|
||||||
|
@ -608,7 +608,7 @@ chunk {3} pageA.js (pageA) 108 bytes ={1}= >{0}< [entry] [rendered]
|
||||||
|
|
||||||
```
|
```
|
||||||
Hash: 0a1b2c3d4e5f6a7b8c9d
|
Hash: 0a1b2c3d4e5f6a7b8c9d
|
||||||
Version: webpack 4.0.0-beta.2
|
Version: webpack 4.0.0-beta.1
|
||||||
Asset Size Chunks Chunk Names
|
Asset Size Chunks Chunk Names
|
||||||
0.js 120 bytes 0 [emitted]
|
0.js 120 bytes 0 [emitted]
|
||||||
commons.js 95 bytes 1 [emitted] commons
|
commons.js 95 bytes 1 [emitted] commons
|
||||||
|
@ -624,8 +624,8 @@ chunk {0} 0.js 91 bytes <{1}> <{2}> <{3}> [rendered]
|
||||||
cjs require ./shared [2] ./pageB.js 3:14-33
|
cjs require ./shared [2] ./pageB.js 3:14-33
|
||||||
amd require ./shared [3] ./pageA.js 2:0-4:2
|
amd require ./shared [3] ./pageA.js 2:0-4:2
|
||||||
chunk {1} commons.js (commons) 26 bytes ={2}= ={3}= >{0}< [initial] [rendered] split chunk (cache group: commons) (name: commons)
|
chunk {1} commons.js (commons) 26 bytes ={2}= ={3}= >{0}< [initial] [rendered] split chunk (cache group: commons) (name: commons)
|
||||||
> ./pageA pageA
|
|
||||||
> ./pageB pageB
|
> ./pageB pageB
|
||||||
|
> ./pageA pageA
|
||||||
[1] ./common.js 26 bytes {1} [built]
|
[1] ./common.js 26 bytes {1} [built]
|
||||||
cjs require ./common [0] ./shared.js 1:13-32
|
cjs require ./common [0] ./shared.js 1:13-32
|
||||||
cjs require ./common [2] ./pageB.js 1:13-32
|
cjs require ./common [2] ./pageB.js 1:13-32
|
||||||
|
|
|
@ -9,10 +9,10 @@ You can use
|
||||||
You can see the output files:
|
You can see the output files:
|
||||||
|
|
||||||
* `commons.js` contains:
|
* `commons.js` contains:
|
||||||
* the module system
|
|
||||||
* chunk loading logic
|
|
||||||
* module `common.js` which is used in both pages
|
* module `common.js` which is used in both pages
|
||||||
* `pageA.js` contains: (`pageB.js` is similar)
|
* `pageA.js` contains: (`pageB.js` is similar)
|
||||||
|
* the module system
|
||||||
|
* chunk loading logic
|
||||||
* the entry point `pageA.js`
|
* the entry point `pageA.js`
|
||||||
* it would contain any other module that is only used by `pageA`
|
* it would contain any other module that is only used by `pageA`
|
||||||
* `0.chunk.js` is an additional chunk which is used by both pages. It contains:
|
* `0.chunk.js` is an additional chunk which is used by both pages. It contains:
|
||||||
|
|
|
@ -12,7 +12,7 @@ delete require.cache[aId];
|
||||||
// require module again, it should be reexecuted
|
// require module again, it should be reexecuted
|
||||||
var a2 = require("./a");
|
var a2 = require("./a");
|
||||||
|
|
||||||
// vertify it
|
// verify it
|
||||||
if(a == a2) throw new Error("Cache clear failed :(");
|
if(a == a2) throw new Error("Cache clear failed :(");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ delete __webpack_require__.c[aId];
|
||||||
// require module again, it should be reexecuted
|
// require module again, it should be reexecuted
|
||||||
var a2 = __webpack_require__(/*! ./a */ 1);
|
var a2 = __webpack_require__(/*! ./a */ 1);
|
||||||
|
|
||||||
// vertify it
|
// verify it
|
||||||
if(a == a2) throw new Error("Cache clear failed :(");
|
if(a == a2) throw new Error("Cache clear failed :(");
|
||||||
|
|
||||||
/***/ }),
|
/***/ }),
|
||||||
|
|
|
@ -9,5 +9,5 @@ delete require.cache[aId];
|
||||||
// require module again, it should be reexecuted
|
// require module again, it should be reexecuted
|
||||||
var a2 = require("./a");
|
var a2 = require("./a");
|
||||||
|
|
||||||
// vertify it
|
// verify it
|
||||||
if(a == a2) throw new Error("Cache clear failed :(");
|
if(a == a2) throw new Error("Cache clear failed :(");
|
|
@ -18,7 +18,7 @@ webpack therefore uses a approach called **"Partial Scope Hoisting"** or "Module
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
While module concatentation identifiers in modules are renamed to avoid conflicts and internal imports are simplified. External imports and exports from the root module use the existing ESM constructs.
|
While module concatenation identifiers in modules are renamed to avoid conflicts and internal imports are simplified. External imports and exports from the root module use the existing ESM constructs.
|
||||||
|
|
||||||
# example.js
|
# example.js
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ webpack therefore uses a approach called **"Partial Scope Hoisting"** or "Module
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
While module concatentation identifiers in modules are renamed to avoid conflicts and internal imports are simplified. External imports and exports from the root module use the existing ESM constructs.
|
While module concatenation identifiers in modules are renamed to avoid conflicts and internal imports are simplified. External imports and exports from the root module use the existing ESM constructs.
|
||||||
|
|
||||||
# example.js
|
# example.js
|
||||||
|
|
||||||
|
|
|
@ -10,15 +10,15 @@ module.exports = [
|
||||||
"hidden-source-map",
|
"hidden-source-map",
|
||||||
"inline-source-map",
|
"inline-source-map",
|
||||||
"nosources-source-map",
|
"nosources-source-map",
|
||||||
"source-map",
|
"source-map"
|
||||||
].map(devtool => ({
|
].map(devtool => ({
|
||||||
mode: "development",
|
mode: "development",
|
||||||
entry: {
|
entry: {
|
||||||
bundle: "coffee-loader!./example.coffee",
|
bundle: "coffee-loader!./example.coffee"
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: path.join(__dirname, "dist"),
|
path: path.join(__dirname, "dist"),
|
||||||
filename: `./[name]-${devtool}.js`,
|
filename: `./[name]-${devtool}.js`
|
||||||
},
|
},
|
||||||
devtool,
|
devtool,
|
||||||
optimization: {
|
optimization: {
|
||||||
|
|
|
@ -242,7 +242,7 @@ export function fibonacciJavascript(i) {
|
||||||
/******/ // on error function for async loading
|
/******/ // on error function for async loading
|
||||||
/******/ __webpack_require__.oe = function(err) { console.error(err); throw err; };
|
/******/ __webpack_require__.oe = function(err) { console.error(err); throw err; };
|
||||||
/******/
|
/******/
|
||||||
/******/ // object with all compiled WebAssmbly.Modules
|
/******/ // object with all compiled WebAssembly.Modules
|
||||||
/******/ __webpack_require__.w = {};
|
/******/ __webpack_require__.w = {};
|
||||||
/******/
|
/******/
|
||||||
/******/ var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
|
/******/ var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
|
||||||
|
|
|
@ -5,10 +5,12 @@ module.exports = {
|
||||||
publicPath: "js/"
|
publicPath: "js/"
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [{
|
rules: [
|
||||||
test: /\.wasm$/,
|
{
|
||||||
type: "webassembly/experimental"
|
test: /\.wasm$/,
|
||||||
}]
|
type: "webassembly/experimental"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
optimization: {
|
optimization: {
|
||||||
occurrenceOrder: true // To keep filename consistent between different modes (for example building only)
|
occurrenceOrder: true // To keep filename consistent between different modes (for example building only)
|
||||||
|
|
|
@ -5,5 +5,4 @@
|
||||||
"rules": {
|
"rules": {
|
||||||
"node/exports-style": ["off"]
|
"node/exports-style": ["off"]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,46 +3,54 @@
|
||||||
Author Tobias Koppers @sokra
|
Author Tobias Koppers @sokra
|
||||||
*/
|
*/
|
||||||
/*globals window __webpack_hash__ */
|
/*globals window __webpack_hash__ */
|
||||||
if(module.hot) {
|
if (module.hot) {
|
||||||
var lastHash;
|
var lastHash;
|
||||||
var upToDate = function upToDate() {
|
var upToDate = function upToDate() {
|
||||||
return lastHash.indexOf(__webpack_hash__) >= 0;
|
return lastHash.indexOf(__webpack_hash__) >= 0;
|
||||||
};
|
};
|
||||||
var log = require("./log");
|
var log = require("./log");
|
||||||
var check = function check() {
|
var check = function check() {
|
||||||
module.hot.check(true).then(function(updatedModules) {
|
module.hot
|
||||||
if(!updatedModules) {
|
.check(true)
|
||||||
log("warning", "[HMR] Cannot find update. Need to do a full reload!");
|
.then(function(updatedModules) {
|
||||||
log("warning", "[HMR] (Probably because of restarting the webpack-dev-server)");
|
if (!updatedModules) {
|
||||||
window.location.reload();
|
log("warning", "[HMR] Cannot find update. Need to do a full reload!");
|
||||||
return;
|
log(
|
||||||
}
|
"warning",
|
||||||
|
"[HMR] (Probably because of restarting the webpack-dev-server)"
|
||||||
|
);
|
||||||
|
window.location.reload();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(!upToDate()) {
|
if (!upToDate()) {
|
||||||
check();
|
check();
|
||||||
}
|
}
|
||||||
|
|
||||||
require("./log-apply-result")(updatedModules, updatedModules);
|
require("./log-apply-result")(updatedModules, updatedModules);
|
||||||
|
|
||||||
if(upToDate()) {
|
if (upToDate()) {
|
||||||
log("info", "[HMR] App is up to date.");
|
log("info", "[HMR] App is up to date.");
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}).catch(function(err) {
|
.catch(function(err) {
|
||||||
var status = module.hot.status();
|
var status = module.hot.status();
|
||||||
if(["abort", "fail"].indexOf(status) >= 0) {
|
if (["abort", "fail"].indexOf(status) >= 0) {
|
||||||
log("warning", "[HMR] Cannot apply update. Need to do a full reload!");
|
log(
|
||||||
log("warning", "[HMR] " + err.stack || err.message);
|
"warning",
|
||||||
window.location.reload();
|
"[HMR] Cannot apply update. Need to do a full reload!"
|
||||||
} else {
|
);
|
||||||
log("warning", "[HMR] Update failed: " + err.stack || err.message);
|
log("warning", "[HMR] " + err.stack || err.message);
|
||||||
}
|
window.location.reload();
|
||||||
});
|
} else {
|
||||||
|
log("warning", "[HMR] Update failed: " + err.stack || err.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
var hotEmitter = require("./emitter");
|
var hotEmitter = require("./emitter");
|
||||||
hotEmitter.on("webpackHotUpdate", function(currentHash) {
|
hotEmitter.on("webpackHotUpdate", function(currentHash) {
|
||||||
lastHash = currentHash;
|
lastHash = currentHash;
|
||||||
if(!upToDate() && module.hot.status() === "idle") {
|
if (!upToDate() && module.hot.status() === "idle") {
|
||||||
log("info", "[HMR] Checking for updates on the server...");
|
log("info", "[HMR] Checking for updates on the server...");
|
||||||
check();
|
check();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,19 +8,22 @@ module.exports = function(updatedModules, renewedModules) {
|
||||||
});
|
});
|
||||||
var log = require("./log");
|
var log = require("./log");
|
||||||
|
|
||||||
if(unacceptedModules.length > 0) {
|
if (unacceptedModules.length > 0) {
|
||||||
log("warning", "[HMR] The following modules couldn't be hot updated: (They would need a full reload!)");
|
log(
|
||||||
|
"warning",
|
||||||
|
"[HMR] The following modules couldn't be hot updated: (They would need a full reload!)"
|
||||||
|
);
|
||||||
unacceptedModules.forEach(function(moduleId) {
|
unacceptedModules.forEach(function(moduleId) {
|
||||||
log("warning", "[HMR] - " + moduleId);
|
log("warning", "[HMR] - " + moduleId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!renewedModules || renewedModules.length === 0) {
|
if (!renewedModules || renewedModules.length === 0) {
|
||||||
log("info", "[HMR] Nothing hot updated.");
|
log("info", "[HMR] Nothing hot updated.");
|
||||||
} else {
|
} else {
|
||||||
log("info", "[HMR] Updated modules:");
|
log("info", "[HMR] Updated modules:");
|
||||||
renewedModules.forEach(function(moduleId) {
|
renewedModules.forEach(function(moduleId) {
|
||||||
if(typeof moduleId === "string" && moduleId.indexOf("!") !== -1) {
|
if (typeof moduleId === "string" && moduleId.indexOf("!") !== -1) {
|
||||||
var parts = moduleId.split("!");
|
var parts = moduleId.split("!");
|
||||||
log.groupCollapsed("info", "[HMR] - " + parts.pop());
|
log.groupCollapsed("info", "[HMR] - " + parts.pop());
|
||||||
log("info", "[HMR] - " + moduleId);
|
log("info", "[HMR] - " + moduleId);
|
||||||
|
@ -32,7 +35,10 @@ module.exports = function(updatedModules, renewedModules) {
|
||||||
var numberIds = renewedModules.every(function(moduleId) {
|
var numberIds = renewedModules.every(function(moduleId) {
|
||||||
return typeof moduleId === "number";
|
return typeof moduleId === "number";
|
||||||
});
|
});
|
||||||
if(numberIds)
|
if (numberIds)
|
||||||
log("info", "[HMR] Consider using the NamedModulesPlugin for module names.");
|
log(
|
||||||
|
"info",
|
||||||
|
"[HMR] Consider using the NamedModulesPlugin for module names."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
13
hot/log.js
13
hot/log.js
|
@ -3,7 +3,8 @@ var logLevel = "info";
|
||||||
function dummy() {}
|
function dummy() {}
|
||||||
|
|
||||||
function shouldLog(level) {
|
function shouldLog(level) {
|
||||||
var shouldLog = (logLevel === "info" && level === "info") ||
|
var shouldLog =
|
||||||
|
(logLevel === "info" && level === "info") ||
|
||||||
(["info", "warning"].indexOf(logLevel) >= 0 && level === "warning") ||
|
(["info", "warning"].indexOf(logLevel) >= 0 && level === "warning") ||
|
||||||
(["info", "warning", "error"].indexOf(logLevel) >= 0 && level === "error");
|
(["info", "warning", "error"].indexOf(logLevel) >= 0 && level === "error");
|
||||||
return shouldLog;
|
return shouldLog;
|
||||||
|
@ -11,19 +12,19 @@ function shouldLog(level) {
|
||||||
|
|
||||||
function logGroup(logFn) {
|
function logGroup(logFn) {
|
||||||
return function(level, msg) {
|
return function(level, msg) {
|
||||||
if(shouldLog(level)) {
|
if (shouldLog(level)) {
|
||||||
logFn(msg);
|
logFn(msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function(level, msg) {
|
module.exports = function(level, msg) {
|
||||||
if(shouldLog(level)) {
|
if (shouldLog(level)) {
|
||||||
if(level === "info") {
|
if (level === "info") {
|
||||||
console.log(msg);
|
console.log(msg);
|
||||||
} else if(level === "warning") {
|
} else if (level === "warning") {
|
||||||
console.warn(msg);
|
console.warn(msg);
|
||||||
} else if(level === "error") {
|
} else if (level === "error") {
|
||||||
console.error(msg);
|
console.error(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,65 +3,99 @@
|
||||||
Author Tobias Koppers @sokra
|
Author Tobias Koppers @sokra
|
||||||
*/
|
*/
|
||||||
/*globals __webpack_hash__ */
|
/*globals __webpack_hash__ */
|
||||||
if(module.hot) {
|
if (module.hot) {
|
||||||
var lastHash;
|
var lastHash;
|
||||||
var upToDate = function upToDate() {
|
var upToDate = function upToDate() {
|
||||||
return lastHash.indexOf(__webpack_hash__) >= 0;
|
return lastHash.indexOf(__webpack_hash__) >= 0;
|
||||||
};
|
};
|
||||||
var log = require("./log");
|
var log = require("./log");
|
||||||
var check = function check() {
|
var check = function check() {
|
||||||
module.hot.check().then(function(updatedModules) {
|
module.hot
|
||||||
if(!updatedModules) {
|
.check()
|
||||||
log("warning", "[HMR] Cannot find update. Need to do a full reload!");
|
.then(function(updatedModules) {
|
||||||
log("warning", "[HMR] (Probably because of restarting the webpack-dev-server)");
|
if (!updatedModules) {
|
||||||
return;
|
log("warning", "[HMR] Cannot find update. Need to do a full reload!");
|
||||||
}
|
log(
|
||||||
|
"warning",
|
||||||
return module.hot.apply({
|
"[HMR] (Probably because of restarting the webpack-dev-server)"
|
||||||
ignoreUnaccepted: true,
|
);
|
||||||
ignoreDeclined: true,
|
return;
|
||||||
ignoreErrored: true,
|
|
||||||
onUnaccepted: function(data) {
|
|
||||||
log("warning", "Ignored an update to unaccepted module " + data.chain.join(" -> "));
|
|
||||||
},
|
|
||||||
onDeclined: function(data) {
|
|
||||||
log("warning", "Ignored an update to declined module " + data.chain.join(" -> "));
|
|
||||||
},
|
|
||||||
onErrored: function(data) {
|
|
||||||
log("error", data.error);
|
|
||||||
log("warning", "Ignored an error while updating module " + data.moduleId + " (" + data.type + ")");
|
|
||||||
}
|
|
||||||
}).then(function(renewedModules) {
|
|
||||||
if(!upToDate()) {
|
|
||||||
check();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
require("./log-apply-result")(updatedModules, renewedModules);
|
return module.hot
|
||||||
|
.apply({
|
||||||
|
ignoreUnaccepted: true,
|
||||||
|
ignoreDeclined: true,
|
||||||
|
ignoreErrored: true,
|
||||||
|
onUnaccepted: function(data) {
|
||||||
|
log(
|
||||||
|
"warning",
|
||||||
|
"Ignored an update to unaccepted module " +
|
||||||
|
data.chain.join(" -> ")
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onDeclined: function(data) {
|
||||||
|
log(
|
||||||
|
"warning",
|
||||||
|
"Ignored an update to declined module " +
|
||||||
|
data.chain.join(" -> ")
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onErrored: function(data) {
|
||||||
|
log("error", data.error);
|
||||||
|
log(
|
||||||
|
"warning",
|
||||||
|
"Ignored an error while updating module " +
|
||||||
|
data.moduleId +
|
||||||
|
" (" +
|
||||||
|
data.type +
|
||||||
|
")"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function(renewedModules) {
|
||||||
|
if (!upToDate()) {
|
||||||
|
check();
|
||||||
|
}
|
||||||
|
|
||||||
if(upToDate()) {
|
require("./log-apply-result")(updatedModules, renewedModules);
|
||||||
log("info", "[HMR] App is up to date.");
|
|
||||||
|
if (upToDate()) {
|
||||||
|
log("info", "[HMR] App is up to date.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
var status = module.hot.status();
|
||||||
|
if (["abort", "fail"].indexOf(status) >= 0) {
|
||||||
|
log(
|
||||||
|
"warning",
|
||||||
|
"[HMR] Cannot check for update. Need to do a full reload!"
|
||||||
|
);
|
||||||
|
log("warning", "[HMR] " + err.stack || err.message);
|
||||||
|
} else {
|
||||||
|
log(
|
||||||
|
"warning",
|
||||||
|
"[HMR] Update check failed: " + err.stack || err.message
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).catch(function(err) {
|
|
||||||
var status = module.hot.status();
|
|
||||||
if(["abort", "fail"].indexOf(status) >= 0) {
|
|
||||||
log("warning", "[HMR] Cannot check for update. Need to do a full reload!");
|
|
||||||
log("warning", "[HMR] " + err.stack || err.message);
|
|
||||||
} else {
|
|
||||||
log("warning", "[HMR] Update check failed: " + err.stack || err.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
var hotEmitter = require("./emitter");
|
var hotEmitter = require("./emitter");
|
||||||
hotEmitter.on("webpackHotUpdate", function(currentHash) {
|
hotEmitter.on("webpackHotUpdate", function(currentHash) {
|
||||||
lastHash = currentHash;
|
lastHash = currentHash;
|
||||||
if(!upToDate()) {
|
if (!upToDate()) {
|
||||||
var status = module.hot.status();
|
var status = module.hot.status();
|
||||||
if(status === "idle") {
|
if (status === "idle") {
|
||||||
log("info", "[HMR] Checking for updates on the server...");
|
log("info", "[HMR] Checking for updates on the server...");
|
||||||
check();
|
check();
|
||||||
} else if(["abort", "fail"].indexOf(status) >= 0) {
|
} else if (["abort", "fail"].indexOf(status) >= 0) {
|
||||||
log("warning", "[HMR] Cannot apply update as a previous update " + status + "ed. Need to do a full reload!");
|
log(
|
||||||
|
"warning",
|
||||||
|
"[HMR] Cannot apply update as a previous update " +
|
||||||
|
status +
|
||||||
|
"ed. Need to do a full reload!"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
43
hot/poll.js
43
hot/poll.js
|
@ -3,29 +3,32 @@
|
||||||
Author Tobias Koppers @sokra
|
Author Tobias Koppers @sokra
|
||||||
*/
|
*/
|
||||||
/*globals __resourceQuery */
|
/*globals __resourceQuery */
|
||||||
if(module.hot) {
|
if (module.hot) {
|
||||||
var hotPollInterval = +(__resourceQuery.substr(1)) || (10 * 60 * 1000);
|
var hotPollInterval = +__resourceQuery.substr(1) || 10 * 60 * 1000;
|
||||||
var log = require("./log");
|
var log = require("./log");
|
||||||
|
|
||||||
var checkForUpdate = function checkForUpdate(fromUpdate) {
|
var checkForUpdate = function checkForUpdate(fromUpdate) {
|
||||||
if(module.hot.status() === "idle") {
|
if (module.hot.status() === "idle") {
|
||||||
module.hot.check(true).then(function(updatedModules) {
|
module.hot
|
||||||
if(!updatedModules) {
|
.check(true)
|
||||||
if(fromUpdate) log("info", "[HMR] Update applied.");
|
.then(function(updatedModules) {
|
||||||
return;
|
if (!updatedModules) {
|
||||||
}
|
if (fromUpdate) log("info", "[HMR] Update applied.");
|
||||||
require("./log-apply-result")(updatedModules, updatedModules);
|
return;
|
||||||
checkForUpdate(true);
|
}
|
||||||
}).catch(function(err) {
|
require("./log-apply-result")(updatedModules, updatedModules);
|
||||||
var status = module.hot.status();
|
checkForUpdate(true);
|
||||||
if(["abort", "fail"].indexOf(status) >= 0) {
|
})
|
||||||
log("warning", "[HMR] Cannot apply update.");
|
.catch(function(err) {
|
||||||
log("warning", "[HMR] " + err.stack || err.message);
|
var status = module.hot.status();
|
||||||
log("warning", "[HMR] You need to restart the application!");
|
if (["abort", "fail"].indexOf(status) >= 0) {
|
||||||
} else {
|
log("warning", "[HMR] Cannot apply update.");
|
||||||
log("warning", "[HMR] Update failed: " + err.stack || err.message);
|
log("warning", "[HMR] " + err.stack || err.message);
|
||||||
}
|
log("warning", "[HMR] You need to restart the application!");
|
||||||
});
|
} else {
|
||||||
|
log("warning", "[HMR] Update failed: " + err.stack || err.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
setInterval(checkForUpdate, hotPollInterval);
|
setInterval(checkForUpdate, hotPollInterval);
|
||||||
|
|
|
@ -3,44 +3,54 @@
|
||||||
Author Tobias Koppers @sokra
|
Author Tobias Koppers @sokra
|
||||||
*/
|
*/
|
||||||
/*globals __resourceQuery */
|
/*globals __resourceQuery */
|
||||||
if(module.hot) {
|
if (module.hot) {
|
||||||
var log = require("./log");
|
var log = require("./log");
|
||||||
var checkForUpdate = function checkForUpdate(fromUpdate) {
|
var checkForUpdate = function checkForUpdate(fromUpdate) {
|
||||||
module.hot.check().then(function(updatedModules) {
|
module.hot
|
||||||
if(!updatedModules) {
|
.check()
|
||||||
if(fromUpdate)
|
.then(function(updatedModules) {
|
||||||
log("info", "[HMR] Update applied.");
|
if (!updatedModules) {
|
||||||
else
|
if (fromUpdate) log("info", "[HMR] Update applied.");
|
||||||
log("warning", "[HMR] Cannot find update.");
|
else log("warning", "[HMR] Cannot find update.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return module.hot.apply({
|
return module.hot
|
||||||
ignoreUnaccepted: true,
|
.apply({
|
||||||
onUnaccepted: function(data) {
|
ignoreUnaccepted: true,
|
||||||
log("warning", "Ignored an update to unaccepted module " + data.chain.join(" -> "));
|
onUnaccepted: function(data) {
|
||||||
},
|
log(
|
||||||
}).then(function(renewedModules) {
|
"warning",
|
||||||
require("./log-apply-result")(updatedModules, renewedModules);
|
"Ignored an update to unaccepted module " +
|
||||||
|
data.chain.join(" -> ")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function(renewedModules) {
|
||||||
|
require("./log-apply-result")(updatedModules, renewedModules);
|
||||||
|
|
||||||
checkForUpdate(true);
|
checkForUpdate(true);
|
||||||
return null;
|
return null;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
var status = module.hot.status();
|
||||||
|
if (["abort", "fail"].indexOf(status) >= 0) {
|
||||||
|
log("warning", "[HMR] Cannot apply update.");
|
||||||
|
log("warning", "[HMR] " + err.stack || err.message);
|
||||||
|
log("warning", "[HMR] You need to restart the application!");
|
||||||
|
} else {
|
||||||
|
log("warning", "[HMR] Update failed: " + err.stack || err.message);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}).catch(function(err) {
|
|
||||||
var status = module.hot.status();
|
|
||||||
if(["abort", "fail"].indexOf(status) >= 0) {
|
|
||||||
log("warning", "[HMR] Cannot apply update.");
|
|
||||||
log("warning", "[HMR] " + err.stack || err.message);
|
|
||||||
log("warning", "[HMR] You need to restart the application!");
|
|
||||||
} else {
|
|
||||||
log("warning", "[HMR] Update failed: " + err.stack || err.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
process.on(__resourceQuery.substr(1) || "SIGUSR2", function() {
|
process.on(__resourceQuery.substr(1) || "SIGUSR2", function() {
|
||||||
if(module.hot.status() !== "idle") {
|
if (module.hot.status() !== "idle") {
|
||||||
log("warning", "[HMR] Got signal but currently in " + module.hot.status() + " state.");
|
log(
|
||||||
|
"warning",
|
||||||
|
"[HMR] Got signal but currently in " + module.hot.status() + " state."
|
||||||
|
);
|
||||||
log("warning", "[HMR] Need to be in idle state to start hot update.");
|
log("warning", "[HMR] Need to be in idle state to start hot update.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,23 +33,51 @@ const REPLACEMENT_TYPES = {
|
||||||
|
|
||||||
class APIPlugin {
|
class APIPlugin {
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compilation.tap("APIPlugin", (compilation, {
|
compiler.hooks.compilation.tap(
|
||||||
normalModuleFactory
|
"APIPlugin",
|
||||||
}) => {
|
(compilation, { normalModuleFactory }) => {
|
||||||
compilation.dependencyFactories.set(ConstDependency, new NullFactory());
|
compilation.dependencyFactories.set(ConstDependency, new NullFactory());
|
||||||
compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template());
|
compilation.dependencyTemplates.set(
|
||||||
|
ConstDependency,
|
||||||
|
new ConstDependency.Template()
|
||||||
|
);
|
||||||
|
|
||||||
const handler = parser => {
|
const handler = parser => {
|
||||||
Object.keys(REPLACEMENTS).forEach(key => {
|
Object.keys(REPLACEMENTS).forEach(key => {
|
||||||
parser.hooks.expression.for(key).tap("APIPlugin", NO_WEBPACK_REQUIRE[key] ? ParserHelpers.toConstantDependency(parser, REPLACEMENTS[key]) : ParserHelpers.toConstantDependencyWithWebpackRequire(parser, REPLACEMENTS[key]));
|
parser.hooks.expression
|
||||||
parser.hooks.evaluateTypeof.for(key).tap("APIPlugin", ParserHelpers.evaluateToString(REPLACEMENT_TYPES[key]));
|
.for(key)
|
||||||
});
|
.tap(
|
||||||
};
|
"APIPlugin",
|
||||||
|
NO_WEBPACK_REQUIRE[key]
|
||||||
|
? ParserHelpers.toConstantDependency(
|
||||||
|
parser,
|
||||||
|
REPLACEMENTS[key]
|
||||||
|
)
|
||||||
|
: ParserHelpers.toConstantDependencyWithWebpackRequire(
|
||||||
|
parser,
|
||||||
|
REPLACEMENTS[key]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
parser.hooks.evaluateTypeof
|
||||||
|
.for(key)
|
||||||
|
.tap(
|
||||||
|
"APIPlugin",
|
||||||
|
ParserHelpers.evaluateToString(REPLACEMENT_TYPES[key])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
normalModuleFactory.hooks.parser.for("javascript/auto").tap("APIPlugin", handler);
|
normalModuleFactory.hooks.parser
|
||||||
normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("APIPlugin", handler);
|
.for("javascript/auto")
|
||||||
normalModuleFactory.hooks.parser.for("javascript/esm").tap("APIPlugin", handler);
|
.tap("APIPlugin", handler);
|
||||||
});
|
normalModuleFactory.hooks.parser
|
||||||
|
.for("javascript/dynamic")
|
||||||
|
.tap("APIPlugin", handler);
|
||||||
|
normalModuleFactory.hooks.parser
|
||||||
|
.for("javascript/esm")
|
||||||
|
.tap("APIPlugin", handler);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const ConcatSource = require("webpack-sources").ConcatSource;
|
const { ConcatSource } = require("webpack-sources");
|
||||||
const Template = require("./Template");
|
const Template = require("./Template");
|
||||||
|
|
||||||
class AmdMainTemplatePlugin {
|
class AmdMainTemplatePlugin {
|
||||||
|
@ -14,42 +14,56 @@ class AmdMainTemplatePlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(compilation) {
|
apply(compilation) {
|
||||||
const {
|
const { mainTemplate, chunkTemplate } = compilation;
|
||||||
mainTemplate,
|
|
||||||
chunkTemplate
|
|
||||||
} = compilation;
|
|
||||||
|
|
||||||
const onRenderWithEntry = (source, chunk, hash) => {
|
const onRenderWithEntry = (source, chunk, hash) => {
|
||||||
const externals = chunk.getModules().filter((m) => m.external);
|
const externals = chunk.getModules().filter(m => m.external);
|
||||||
const externalsDepsArray = JSON.stringify(externals.map((m) =>
|
const externalsDepsArray = JSON.stringify(
|
||||||
typeof m.request === "object" ? m.request.amd : m.request
|
externals.map(
|
||||||
));
|
m => (typeof m.request === "object" ? m.request.amd : m.request)
|
||||||
const externalsArguments = externals.map((m) =>
|
)
|
||||||
`__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${m.id}`)}__`
|
);
|
||||||
).join(", ");
|
const externalsArguments = externals
|
||||||
|
.map(
|
||||||
|
m => `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${m.id}`)}__`
|
||||||
|
)
|
||||||
|
.join(", ");
|
||||||
|
|
||||||
if(this.name) {
|
if (this.name) {
|
||||||
const name = mainTemplate.getAssetPath(this.name, {
|
const name = mainTemplate.getAssetPath(this.name, {
|
||||||
hash,
|
hash,
|
||||||
chunk
|
chunk
|
||||||
});
|
});
|
||||||
|
|
||||||
return new ConcatSource(
|
return new ConcatSource(
|
||||||
`define(${JSON.stringify(name)}, ${externalsDepsArray}, function(${externalsArguments}) { return `, source, "});"
|
`define(${JSON.stringify(name)}, ${externalsDepsArray}, function(${
|
||||||
|
externalsArguments
|
||||||
|
}) { return `,
|
||||||
|
source,
|
||||||
|
"});"
|
||||||
|
);
|
||||||
|
} else if (externalsArguments) {
|
||||||
|
return new ConcatSource(
|
||||||
|
`define(${externalsDepsArray}, function(${
|
||||||
|
externalsArguments
|
||||||
|
}) { return `,
|
||||||
|
source,
|
||||||
|
"});"
|
||||||
);
|
);
|
||||||
} else if(externalsArguments) {
|
|
||||||
return new ConcatSource(`define(${externalsDepsArray}, function(${externalsArguments}) { return `, source, "});");
|
|
||||||
} else {
|
} else {
|
||||||
return new ConcatSource("define(function() { return ", source, "});");
|
return new ConcatSource("define(function() { return ", source, "});");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for(const template of [mainTemplate, chunkTemplate]) {
|
for (const template of [mainTemplate, chunkTemplate]) {
|
||||||
template.hooks.renderWithEntry.tap("AmdMainTemplatePlugin", onRenderWithEntry);
|
template.hooks.renderWithEntry.tap(
|
||||||
|
"AmdMainTemplatePlugin",
|
||||||
|
onRenderWithEntry
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
mainTemplate.hooks.globalHashPaths.tap("AmdMainTemplatePlugin", paths => {
|
mainTemplate.hooks.globalHashPaths.tap("AmdMainTemplatePlugin", paths => {
|
||||||
if(this.name) paths.push(this.name);
|
if (this.name) paths.push(this.name);
|
||||||
return paths;
|
return paths;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,15 @@ module.exports = class AsyncDependenciesBlock extends DependenciesBlock {
|
||||||
|
|
||||||
updateHash(hash) {
|
updateHash(hash) {
|
||||||
hash.update(this.chunkName || "");
|
hash.update(this.chunkName || "");
|
||||||
hash.update(this.chunkGroup && this.chunkGroup.chunks.map(chunk => {
|
hash.update(
|
||||||
return chunk.id !== null ? chunk.id : "";
|
(this.chunkGroup &&
|
||||||
}).join(",") || "");
|
this.chunkGroup.chunks
|
||||||
|
.map(chunk => {
|
||||||
|
return chunk.id !== null ? chunk.id : "";
|
||||||
|
})
|
||||||
|
.join(",")) ||
|
||||||
|
""
|
||||||
|
);
|
||||||
super.updateHash(hash);
|
super.updateHash(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,9 @@ module.exports = class AsyncDependencyToInitialChunkError extends WebpackError {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.name = "AsyncDependencyToInitialChunkError";
|
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.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.module = module;
|
||||||
this.origin = module;
|
this.origin = module;
|
||||||
this.originLoc = loc;
|
this.originLoc = loc;
|
||||||
|
|
|
@ -10,13 +10,17 @@ const NormalModule = require("./NormalModule");
|
||||||
|
|
||||||
class AutomaticPrefetchPlugin {
|
class AutomaticPrefetchPlugin {
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compilation.tap("AutomaticPrefetchPlugin", (compilation, {
|
compiler.hooks.compilation.tap(
|
||||||
normalModuleFactory
|
"AutomaticPrefetchPlugin",
|
||||||
}) => {
|
(compilation, { normalModuleFactory }) => {
|
||||||
compilation.dependencyFactories.set(PrefetchDependency, normalModuleFactory);
|
compilation.dependencyFactories.set(
|
||||||
});
|
PrefetchDependency,
|
||||||
|
normalModuleFactory
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
let lastModules = null;
|
let lastModules = null;
|
||||||
compiler.hooks.afterCompile.tap("AutomaticPrefetchPlugin", (compilation) => {
|
compiler.hooks.afterCompile.tap("AutomaticPrefetchPlugin", compilation => {
|
||||||
lastModules = compilation.modules
|
lastModules = compilation.modules
|
||||||
.filter(m => m instanceof NormalModule)
|
.filter(m => m instanceof NormalModule)
|
||||||
.map(m => ({
|
.map(m => ({
|
||||||
|
@ -24,12 +28,23 @@ class AutomaticPrefetchPlugin {
|
||||||
request: m.request
|
request: m.request
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
compiler.hooks.make.tapAsync("AutomaticPrefetchPlugin", (compilation, callback) => {
|
compiler.hooks.make.tapAsync(
|
||||||
if(!lastModules) return callback();
|
"AutomaticPrefetchPlugin",
|
||||||
asyncLib.forEach(lastModules, (m, callback) => {
|
(compilation, callback) => {
|
||||||
compilation.prefetch(m.context || compiler.context, new PrefetchDependency(m.request), callback);
|
if (!lastModules) return callback();
|
||||||
}, callback);
|
asyncLib.forEach(
|
||||||
});
|
lastModules,
|
||||||
|
(m, callback) => {
|
||||||
|
compilation.prefetch(
|
||||||
|
m.context || compiler.context,
|
||||||
|
new PrefetchDependency(m.request),
|
||||||
|
callback
|
||||||
|
);
|
||||||
|
},
|
||||||
|
callback
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
module.exports = AutomaticPrefetchPlugin;
|
module.exports = AutomaticPrefetchPlugin;
|
||||||
|
|
|
@ -5,47 +5,57 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const ConcatSource = require("webpack-sources").ConcatSource;
|
const { ConcatSource } = require("webpack-sources");
|
||||||
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
|
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
|
||||||
const Template = require("./Template");
|
const Template = require("./Template");
|
||||||
|
|
||||||
const validateOptions = require("schema-utils");
|
const validateOptions = require("schema-utils");
|
||||||
const schema = require("../schemas/plugins/BannerPlugin.json");
|
const schema = require("../schemas/plugins/BannerPlugin.json");
|
||||||
|
|
||||||
const wrapComment = (str) => {
|
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").join("\n * ")}\n */`;
|
return `/*!\n * ${str
|
||||||
|
.replace(/\*\//g, "* /")
|
||||||
|
.split("\n")
|
||||||
|
.join("\n * ")}\n */`;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BannerPlugin {
|
class BannerPlugin {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
if(arguments.length > 1)
|
if (arguments.length > 1)
|
||||||
throw new Error("BannerPlugin only takes one argument (pass an options object)");
|
throw new Error(
|
||||||
|
"BannerPlugin only takes one argument (pass an options object)"
|
||||||
|
);
|
||||||
|
|
||||||
validateOptions(schema, options, "Banner Plugin");
|
validateOptions(schema, options, "Banner Plugin");
|
||||||
|
|
||||||
if(typeof options === "string")
|
if (typeof options === "string")
|
||||||
options = {
|
options = {
|
||||||
banner: options
|
banner: options
|
||||||
};
|
};
|
||||||
this.options = options || {};
|
this.options = options || {};
|
||||||
this.banner = this.options.raw ? options.banner : wrapComment(options.banner);
|
this.banner = this.options.raw
|
||||||
|
? options.banner
|
||||||
|
: wrapComment(options.banner);
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
const options = this.options;
|
const options = this.options;
|
||||||
const banner = this.banner;
|
const banner = this.banner;
|
||||||
const matchObject = ModuleFilenameHelpers.matchObject.bind(undefined, options);
|
const matchObject = ModuleFilenameHelpers.matchObject.bind(
|
||||||
|
undefined,
|
||||||
|
options
|
||||||
|
);
|
||||||
|
|
||||||
compiler.hooks.compilation.tap("BannerPlugin", (compilation) => {
|
compiler.hooks.compilation.tap("BannerPlugin", compilation => {
|
||||||
compilation.hooks.optimizeChunkAssets.tap("BannerPlugin", (chunks) => {
|
compilation.hooks.optimizeChunkAssets.tap("BannerPlugin", chunks => {
|
||||||
for(const chunk of chunks) {
|
for (const chunk of chunks) {
|
||||||
if(options.entryOnly && !chunk.canBeInitial()) {
|
if (options.entryOnly && !chunk.canBeInitial()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const file of chunk.files) {
|
for (const file of chunk.files) {
|
||||||
if(!matchObject(file)) {
|
if (!matchObject(file)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,14 +65,14 @@ class BannerPlugin {
|
||||||
const hash = compilation.hash;
|
const hash = compilation.hash;
|
||||||
const querySplit = filename.indexOf("?");
|
const querySplit = filename.indexOf("?");
|
||||||
|
|
||||||
if(querySplit >= 0) {
|
if (querySplit >= 0) {
|
||||||
query = filename.substr(querySplit);
|
query = filename.substr(querySplit);
|
||||||
filename = filename.substr(0, querySplit);
|
filename = filename.substr(0, querySplit);
|
||||||
}
|
}
|
||||||
|
|
||||||
const lastSlashIndex = filename.lastIndexOf("/");
|
const lastSlashIndex = filename.lastIndexOf("/");
|
||||||
|
|
||||||
if(lastSlashIndex === -1) {
|
if (lastSlashIndex === -1) {
|
||||||
basename = filename;
|
basename = filename;
|
||||||
} else {
|
} else {
|
||||||
basename = filename.substr(lastSlashIndex + 1);
|
basename = filename.substr(lastSlashIndex + 1);
|
||||||
|
@ -73,10 +83,14 @@ class BannerPlugin {
|
||||||
chunk,
|
chunk,
|
||||||
filename,
|
filename,
|
||||||
basename,
|
basename,
|
||||||
query,
|
query
|
||||||
});
|
});
|
||||||
|
|
||||||
compilation.assets[file] = new ConcatSource(comment, "\n", compilation.assets[file]);
|
compilation.assets[file] = new ConcatSource(
|
||||||
|
comment,
|
||||||
|
"\n",
|
||||||
|
compilation.assets[file]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,7 +19,6 @@ const TypeWrapped = 10;
|
||||||
const TypeTemplateString = 11;
|
const TypeTemplateString = 11;
|
||||||
|
|
||||||
class BasicEvaluatedExpression {
|
class BasicEvaluatedExpression {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.type = TypeUnknown;
|
this.type = TypeUnknown;
|
||||||
this.range = null;
|
this.range = null;
|
||||||
|
@ -90,19 +89,23 @@ class BasicEvaluatedExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
asBool() {
|
asBool() {
|
||||||
if(this.truthy) return true;
|
if (this.truthy) return true;
|
||||||
else if(this.falsy) return false;
|
else if (this.falsy) return false;
|
||||||
else if(this.isBoolean()) return this.bool;
|
else if (this.isBoolean()) return this.bool;
|
||||||
else if(this.isNull()) return false;
|
else if (this.isNull()) return false;
|
||||||
else if(this.isString()) return this.string !== "";
|
else if (this.isString()) return this.string !== "";
|
||||||
else if(this.isNumber()) return this.number !== 0;
|
else if (this.isNumber()) return this.number !== 0;
|
||||||
else if(this.isRegExp()) return true;
|
else if (this.isRegExp()) return true;
|
||||||
else if(this.isArray()) return true;
|
else if (this.isArray()) return true;
|
||||||
else if(this.isConstArray()) return true;
|
else if (this.isConstArray()) return true;
|
||||||
else if(this.isWrapped()) return this.prefix && this.prefix.asBool() || this.postfix && this.postfix.asBool() ? true : undefined;
|
else if (this.isWrapped())
|
||||||
else if(this.isTemplateString()) {
|
return (this.prefix && this.prefix.asBool()) ||
|
||||||
for(const quasi of this.quasis) {
|
(this.postfix && this.postfix.asBool())
|
||||||
if(quasi.asBool()) return true;
|
? true
|
||||||
|
: undefined;
|
||||||
|
else if (this.isTemplateString()) {
|
||||||
|
for (const quasi of this.quasis) {
|
||||||
|
if (quasi.asBool()) return true;
|
||||||
}
|
}
|
||||||
// can't tell if string will be empty without executing
|
// can't tell if string will be empty without executing
|
||||||
}
|
}
|
||||||
|
@ -158,12 +161,11 @@ class BasicEvaluatedExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
addOptions(options) {
|
addOptions(options) {
|
||||||
if(!this.options) {
|
if (!this.options) {
|
||||||
this.type = TypeConditional;
|
this.type = TypeConditional;
|
||||||
this.options = [];
|
this.options = [];
|
||||||
}
|
}
|
||||||
for(const item of options)
|
for (const item of options) this.options.push(item);
|
||||||
this.options.push(item);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +203,6 @@ class BasicEvaluatedExpression {
|
||||||
this.range = range;
|
this.range = range;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = BasicEvaluatedExpression;
|
module.exports = BasicEvaluatedExpression;
|
||||||
|
|
|
@ -13,26 +13,29 @@ class CachePlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
if(Array.isArray(compiler.compilers)) {
|
if (Array.isArray(compiler.compilers)) {
|
||||||
compiler.compilers.forEach((c, idx) => {
|
compiler.compilers.forEach((c, idx) => {
|
||||||
new CachePlugin(this.cache[idx] = this.cache[idx] || {}).apply(c);
|
new CachePlugin((this.cache[idx] = this.cache[idx] || {})).apply(c);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const registerCacheToCompiler = (compiler, cache) => {
|
const registerCacheToCompiler = (compiler, cache) => {
|
||||||
compiler.hooks.thisCompilation.tap("CachePlugin", compilation => {
|
compiler.hooks.thisCompilation.tap("CachePlugin", compilation => {
|
||||||
compilation.cache = cache;
|
compilation.cache = cache;
|
||||||
compilation.hooks.childCompiler.tap("CachePlugin", (childCompiler, compilerName, compilerIndex) => {
|
compilation.hooks.childCompiler.tap(
|
||||||
if(cache) {
|
"CachePlugin",
|
||||||
let childCache;
|
(childCompiler, compilerName, compilerIndex) => {
|
||||||
if(!cache.children) cache.children = {};
|
if (cache) {
|
||||||
if(!cache.children[compilerName]) cache.children[compilerName] = [];
|
let childCache;
|
||||||
if(cache.children[compilerName][compilerIndex])
|
if (!cache.children) cache.children = {};
|
||||||
childCache = cache.children[compilerName][compilerIndex];
|
if (!cache.children[compilerName])
|
||||||
else
|
cache.children[compilerName] = [];
|
||||||
cache.children[compilerName].push(childCache = {});
|
if (cache.children[compilerName][compilerIndex])
|
||||||
registerCacheToCompiler(childCompiler, childCache);
|
childCache = cache.children[compilerName][compilerIndex];
|
||||||
|
else cache.children[compilerName].push((childCache = {}));
|
||||||
|
registerCacheToCompiler(childCompiler, childCache);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
registerCacheToCompiler(compiler, this.cache);
|
registerCacheToCompiler(compiler, this.cache);
|
||||||
|
@ -40,49 +43,52 @@ class CachePlugin {
|
||||||
this.watching = true;
|
this.watching = true;
|
||||||
});
|
});
|
||||||
compiler.hooks.run.tapAsync("CachePlugin", (compiler, callback) => {
|
compiler.hooks.run.tapAsync("CachePlugin", (compiler, callback) => {
|
||||||
if(!compiler._lastCompilationFileDependencies) return callback();
|
if (!compiler._lastCompilationFileDependencies) return callback();
|
||||||
const fs = compiler.inputFileSystem;
|
const fs = compiler.inputFileSystem;
|
||||||
const fileTs = compiler.fileTimestamps = new Map();
|
const fileTs = (compiler.fileTimestamps = new Map());
|
||||||
asyncLib.forEach(compiler._lastCompilationFileDependencies, (file, callback) => {
|
asyncLib.forEach(
|
||||||
fs.stat(file, (err, stat) => {
|
compiler._lastCompilationFileDependencies,
|
||||||
if(err) {
|
(file, callback) => {
|
||||||
if(err.code === "ENOENT") return callback();
|
fs.stat(file, (err, stat) => {
|
||||||
return callback(err);
|
if (err) {
|
||||||
|
if (err.code === "ENOENT") return callback();
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stat.mtime) this.applyMtime(+stat.mtime);
|
||||||
|
|
||||||
|
fileTs.set(file, +stat.mtime || Infinity);
|
||||||
|
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
err => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
|
||||||
|
for (const [file, ts] of fileTs) {
|
||||||
|
fileTs.set(file, ts + this.FS_ACCURACY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(stat.mtime)
|
|
||||||
this.applyMtime(+stat.mtime);
|
|
||||||
|
|
||||||
fileTs.set(file, +stat.mtime || Infinity);
|
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
});
|
|
||||||
}, err => {
|
|
||||||
if(err) return callback(err);
|
|
||||||
|
|
||||||
for(const [file, ts] of fileTs) {
|
|
||||||
fileTs.set(file, ts + this.FS_ACCURACY);
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
compiler.hooks.afterCompile.tap("CachePlugin", compilation => {
|
compiler.hooks.afterCompile.tap("CachePlugin", compilation => {
|
||||||
compilation.compiler._lastCompilationFileDependencies = compilation.fileDependencies;
|
compilation.compiler._lastCompilationFileDependencies =
|
||||||
compilation.compiler._lastCompilationContextDependencies = compilation.contextDependencies;
|
compilation.fileDependencies;
|
||||||
|
compilation.compiler._lastCompilationContextDependencies =
|
||||||
|
compilation.contextDependencies;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
applyMtime(mtime) {
|
applyMtime(mtime) {
|
||||||
if(this.FS_ACCURACY > 1 && mtime % 2 !== 0)
|
if (this.FS_ACCURACY > 1 && mtime % 2 !== 0) this.FS_ACCURACY = 1;
|
||||||
this.FS_ACCURACY = 1;
|
else if (this.FS_ACCURACY > 10 && mtime % 20 !== 0) this.FS_ACCURACY = 10;
|
||||||
else if(this.FS_ACCURACY > 10 && mtime % 20 !== 0)
|
else if (this.FS_ACCURACY > 100 && mtime % 200 !== 0)
|
||||||
this.FS_ACCURACY = 10;
|
|
||||||
else if(this.FS_ACCURACY > 100 && mtime % 200 !== 0)
|
|
||||||
this.FS_ACCURACY = 100;
|
this.FS_ACCURACY = 100;
|
||||||
else if(this.FS_ACCURACY > 1000 && mtime % 2000 !== 0)
|
else if (this.FS_ACCURACY > 1000 && mtime % 2000 !== 0)
|
||||||
this.FS_ACCURACY = 1000;
|
this.FS_ACCURACY = 1000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,24 +28,26 @@ ${modulesList}`;
|
||||||
a = a.identifier();
|
a = a.identifier();
|
||||||
b = b.identifier();
|
b = b.identifier();
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
if(a < b) return -1;
|
if (a < b) return -1;
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
if(a > b) return 1;
|
if (a > b) return 1;
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_moduleMessages(modules) {
|
_moduleMessages(modules) {
|
||||||
return modules.map((m) => {
|
return modules
|
||||||
let message = `* ${m.identifier()}`;
|
.map(m => {
|
||||||
const validReasons = m.reasons.filter((reason) => reason.module);
|
let message = `* ${m.identifier()}`;
|
||||||
|
const validReasons = m.reasons.filter(reason => reason.module);
|
||||||
|
|
||||||
if(validReasons.length > 0) {
|
if (validReasons.length > 0) {
|
||||||
message += `\n Used by ${validReasons.length} module(s), i. e.`;
|
message += `\n Used by ${validReasons.length} module(s), i. e.`;
|
||||||
message += `\n ${validReasons[0].module.identifier()}`;
|
message += `\n ${validReasons[0].module.identifier()}`;
|
||||||
}
|
}
|
||||||
return message;
|
return message;
|
||||||
}).join("\n");
|
})
|
||||||
|
.join("\n");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
165
lib/Chunk.js
165
lib/Chunk.js
|
@ -9,24 +9,25 @@ const SortableSet = require("./util/SortableSet");
|
||||||
const GraphHelpers = require("./GraphHelpers");
|
const GraphHelpers = require("./GraphHelpers");
|
||||||
let debugId = 1000;
|
let debugId = 1000;
|
||||||
const ERR_CHUNK_ENTRY = "Chunk.entry was removed. Use hasRuntime()";
|
const ERR_CHUNK_ENTRY = "Chunk.entry was removed. Use hasRuntime()";
|
||||||
const ERR_CHUNK_INITIAL = "Chunk.initial was removed. Use canBeInitial/isOnlyInitial()";
|
const ERR_CHUNK_INITIAL =
|
||||||
|
"Chunk.initial was removed. Use canBeInitial/isOnlyInitial()";
|
||||||
|
|
||||||
const sortById = (a, b) => {
|
const sortById = (a, b) => {
|
||||||
if(a.id < b.id) return -1;
|
if (a.id < b.id) return -1;
|
||||||
if(b.id < a.id) return 1;
|
if (b.id < a.id) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
const sortByIdentifier = (a, b) => {
|
const sortByIdentifier = (a, b) => {
|
||||||
if(a.identifier() > b.identifier()) return 1;
|
if (a.identifier() > b.identifier()) return 1;
|
||||||
if(a.identifier() < b.identifier()) return -1;
|
if (a.identifier() < b.identifier()) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getModulesIdent = set => {
|
const getModulesIdent = set => {
|
||||||
set.sort();
|
set.sort();
|
||||||
let str = "";
|
let str = "";
|
||||||
for(const m of set) {
|
for (const m of set) {
|
||||||
str += m.identifier() + "#";
|
str += m.identifier() + "#";
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
|
@ -36,14 +37,13 @@ const getArray = set => Array.from(set);
|
||||||
|
|
||||||
const getModulesSize = set => {
|
const getModulesSize = set => {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
for(const module of set) {
|
for (const module of set) {
|
||||||
count += module.size();
|
count += module.size();
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Chunk {
|
class Chunk {
|
||||||
|
|
||||||
constructor(name) {
|
constructor(name) {
|
||||||
this.id = null;
|
this.id = null;
|
||||||
this.ids = null;
|
this.ids = null;
|
||||||
|
@ -55,6 +55,7 @@ class Chunk {
|
||||||
this.files = [];
|
this.files = [];
|
||||||
this.rendered = false;
|
this.rendered = false;
|
||||||
this.hash = undefined;
|
this.hash = undefined;
|
||||||
|
this.contentHash = Object.create(null);
|
||||||
this.renderedHash = undefined;
|
this.renderedHash = undefined;
|
||||||
this.chunkReason = undefined;
|
this.chunkReason = undefined;
|
||||||
this.extraAsync = false;
|
this.extraAsync = false;
|
||||||
|
@ -77,7 +78,7 @@ class Chunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
hasRuntime() {
|
hasRuntime() {
|
||||||
for(const chunkGroup of this._groups) {
|
for (const chunkGroup of this._groups) {
|
||||||
// We only need to check the first one
|
// We only need to check the first one
|
||||||
return chunkGroup.isInitial() && chunkGroup.getRuntimeChunk() === this;
|
return chunkGroup.isInitial() && chunkGroup.getRuntimeChunk() === this;
|
||||||
}
|
}
|
||||||
|
@ -85,18 +86,16 @@ class Chunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
canBeInitial() {
|
canBeInitial() {
|
||||||
for(const chunkGroup of this._groups) {
|
for (const chunkGroup of this._groups) {
|
||||||
if(chunkGroup.isInitial())
|
if (chunkGroup.isInitial()) return true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
isOnlyInitial() {
|
isOnlyInitial() {
|
||||||
if(this._groups.size <= 0) return false;
|
if (this._groups.size <= 0) return false;
|
||||||
for(const chunkGroup of this._groups) {
|
for (const chunkGroup of this._groups) {
|
||||||
if(!chunkGroup.isInitial())
|
if (!chunkGroup.isInitial()) return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +105,7 @@ class Chunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
addModule(module) {
|
addModule(module) {
|
||||||
if(!this._modules.has(module)) {
|
if (!this._modules.has(module)) {
|
||||||
this._modules.add(module);
|
this._modules.add(module);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +113,7 @@ class Chunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
removeModule(module) {
|
removeModule(module) {
|
||||||
if(this._modules.delete(module)) {
|
if (this._modules.delete(module)) {
|
||||||
module.removeChunk(this);
|
module.removeChunk(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -134,15 +133,13 @@ class Chunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
addGroup(chunkGroup) {
|
addGroup(chunkGroup) {
|
||||||
if(this._groups.has(chunkGroup))
|
if (this._groups.has(chunkGroup)) return false;
|
||||||
return false;
|
|
||||||
this._groups.add(chunkGroup);
|
this._groups.add(chunkGroup);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
removeGroup(chunkGroup) {
|
removeGroup(chunkGroup) {
|
||||||
if(!this._groups.has(chunkGroup))
|
if (!this._groups.has(chunkGroup)) return false;
|
||||||
return false;
|
|
||||||
this._groups.delete(chunkGroup);
|
this._groups.delete(chunkGroup);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -162,18 +159,19 @@ class Chunk {
|
||||||
compareTo(otherChunk) {
|
compareTo(otherChunk) {
|
||||||
this._modules.sort();
|
this._modules.sort();
|
||||||
otherChunk._modules.sort();
|
otherChunk._modules.sort();
|
||||||
if(this._modules.size > otherChunk._modules.size) return -1;
|
if (this._modules.size > otherChunk._modules.size) return -1;
|
||||||
if(this._modules.size < otherChunk._modules.size) return 1;
|
if (this._modules.size < otherChunk._modules.size) return 1;
|
||||||
const a = this._modules[Symbol.iterator]();
|
const a = this._modules[Symbol.iterator]();
|
||||||
const b = otherChunk._modules[Symbol.iterator]();
|
const b = otherChunk._modules[Symbol.iterator]();
|
||||||
while(true) { // eslint-disable-line
|
// eslint-disable-next-line
|
||||||
|
while (true) {
|
||||||
const aItem = a.next();
|
const aItem = a.next();
|
||||||
const bItem = b.next();
|
const bItem = b.next();
|
||||||
if(aItem.done) return 0;
|
if (aItem.done) return 0;
|
||||||
const aModuleIdentifier = aItem.value.identifier();
|
const aModuleIdentifier = aItem.value.identifier();
|
||||||
const bModuleIdentifier = bItem.value.identifier();
|
const bModuleIdentifier = bItem.value.identifier();
|
||||||
if(aModuleIdentifier > bModuleIdentifier) return -1;
|
if (aModuleIdentifier > bModuleIdentifier) return -1;
|
||||||
if(aModuleIdentifier < bModuleIdentifier) return 1;
|
if (aModuleIdentifier < bModuleIdentifier) return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,10 +190,10 @@ class Chunk {
|
||||||
remove(reason) {
|
remove(reason) {
|
||||||
// cleanup modules
|
// cleanup modules
|
||||||
// Array.from is used here to create a clone, because removeChunk modifies this._modules
|
// Array.from is used here to create a clone, because removeChunk modifies this._modules
|
||||||
for(const module of Array.from(this._modules)) {
|
for (const module of Array.from(this._modules)) {
|
||||||
module.removeChunk(this);
|
module.removeChunk(this);
|
||||||
}
|
}
|
||||||
for(const chunkGroup of this._groups) {
|
for (const chunkGroup of this._groups) {
|
||||||
chunkGroup.removeChunk(this);
|
chunkGroup.removeChunk(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,25 +205,28 @@ class Chunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
integrate(otherChunk, reason) {
|
integrate(otherChunk, reason) {
|
||||||
if(!this.canBeIntegrated(otherChunk)) {
|
if (!this.canBeIntegrated(otherChunk)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Array.from is used here to create a clone, because moveModule modifies otherChunk._modules
|
// Array.from is used here to create a clone, because moveModule modifies otherChunk._modules
|
||||||
for(const module of Array.from(otherChunk._modules)) {
|
for (const module of Array.from(otherChunk._modules)) {
|
||||||
otherChunk.moveModule(module, this);
|
otherChunk.moveModule(module, this);
|
||||||
}
|
}
|
||||||
otherChunk._modules.clear();
|
otherChunk._modules.clear();
|
||||||
|
|
||||||
for(const chunkGroup of otherChunk._groups) {
|
for (const chunkGroup of otherChunk._groups) {
|
||||||
chunkGroup.replaceChunk(otherChunk, this);
|
chunkGroup.replaceChunk(otherChunk, this);
|
||||||
this.addGroup(chunkGroup);
|
this.addGroup(chunkGroup);
|
||||||
}
|
}
|
||||||
otherChunk._groups.clear();
|
otherChunk._groups.clear();
|
||||||
|
|
||||||
if(this.name && otherChunk.name) {
|
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;
|
this.name =
|
||||||
|
this.name.length < otherChunk.name.length
|
||||||
|
? this.name
|
||||||
|
: otherChunk.name;
|
||||||
else
|
else
|
||||||
this.name = this.name < otherChunk.name ? this.name : otherChunk.name;
|
this.name = this.name < otherChunk.name ? this.name : otherChunk.name;
|
||||||
}
|
}
|
||||||
|
@ -234,7 +235,7 @@ class Chunk {
|
||||||
}
|
}
|
||||||
|
|
||||||
split(newChunk) {
|
split(newChunk) {
|
||||||
for(const chunkGroup of this._groups) {
|
for (const chunkGroup of this._groups) {
|
||||||
chunkGroup.insertChunk(newChunk, this);
|
chunkGroup.insertChunk(newChunk, this);
|
||||||
newChunk.addGroup(chunkGroup);
|
newChunk.addGroup(chunkGroup);
|
||||||
}
|
}
|
||||||
|
@ -248,7 +249,7 @@ class Chunk {
|
||||||
hash.update(`${this.id} `);
|
hash.update(`${this.id} `);
|
||||||
hash.update(this.ids ? this.ids.join(",") : "");
|
hash.update(this.ids ? this.ids.join(",") : "");
|
||||||
hash.update(`${this.name || ""} `);
|
hash.update(`${this.name || ""} `);
|
||||||
for(const m of this._modules) {
|
for (const m of this._modules) {
|
||||||
hash.update(m.hash);
|
hash.update(m.hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,31 +257,32 @@ class Chunk {
|
||||||
canBeIntegrated(otherChunk) {
|
canBeIntegrated(otherChunk) {
|
||||||
const isAvailable = (a, b) => {
|
const isAvailable = (a, b) => {
|
||||||
const queue = new Set(b.groupsIterable);
|
const queue = new Set(b.groupsIterable);
|
||||||
for(const chunkGroup of queue) {
|
for (const chunkGroup of queue) {
|
||||||
if(a.isInGroup(chunkGroup)) continue;
|
if (a.isInGroup(chunkGroup)) continue;
|
||||||
if(chunkGroup.isInitial()) return false;
|
if (chunkGroup.isInitial()) return false;
|
||||||
for(const parent of chunkGroup.parentsIterable)
|
for (const parent of chunkGroup.parentsIterable) queue.add(parent);
|
||||||
queue.add(parent);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
if(this.hasRuntime() !== otherChunk.hasRuntime()) {
|
if (this.hasRuntime() !== otherChunk.hasRuntime()) {
|
||||||
if(this.hasRuntime()) {
|
if (this.hasRuntime()) {
|
||||||
return isAvailable(this, otherChunk);
|
return isAvailable(this, otherChunk);
|
||||||
} else if(otherChunk.hasRuntime()) {
|
} else if (otherChunk.hasRuntime()) {
|
||||||
return isAvailable(otherChunk, this);
|
return isAvailable(otherChunk, this);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(this.hasEntryModule() || otherChunk.hasEntryModule())
|
if (this.hasEntryModule() || otherChunk.hasEntryModule()) return false;
|
||||||
return false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
addMultiplierAndOverhead(size, options) {
|
addMultiplierAndOverhead(size, options) {
|
||||||
const overhead = typeof options.chunkOverhead === "number" ? options.chunkOverhead : 10000;
|
const overhead =
|
||||||
const multiplicator = this.canBeInitial() ? (options.entryChunkMultiplicator || 10) : 1;
|
typeof options.chunkOverhead === "number" ? options.chunkOverhead : 10000;
|
||||||
|
const multiplicator = this.canBeInitial()
|
||||||
|
? options.entryChunkMultiplicator || 10
|
||||||
|
: 1;
|
||||||
|
|
||||||
return size * multiplicator + overhead;
|
return size * multiplicator + overhead;
|
||||||
}
|
}
|
||||||
|
@ -295,14 +297,14 @@ class Chunk {
|
||||||
|
|
||||||
integratedSize(otherChunk, options) {
|
integratedSize(otherChunk, options) {
|
||||||
// Chunk if it's possible to integrate this chunk
|
// Chunk if it's possible to integrate this chunk
|
||||||
if(!this.canBeIntegrated(otherChunk)) {
|
if (!this.canBeIntegrated(otherChunk)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let integratedModulesSize = this.modulesSize();
|
let integratedModulesSize = this.modulesSize();
|
||||||
// only count modules that do not exist in this chunk!
|
// only count modules that do not exist in this chunk!
|
||||||
for(const otherModule of otherChunk._modules) {
|
for (const otherModule of otherChunk._modules) {
|
||||||
if(!this._modules.has(otherModule)) {
|
if (!this._modules.has(otherModule)) {
|
||||||
integratedModulesSize += otherModule.size();
|
integratedModulesSize += otherModule.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -323,18 +325,15 @@ class Chunk {
|
||||||
const queue = new Set(this.groupsIterable);
|
const queue = new Set(this.groupsIterable);
|
||||||
const chunks = new Set();
|
const chunks = new Set();
|
||||||
|
|
||||||
for(const chunkGroup of queue) {
|
for (const chunkGroup of queue) {
|
||||||
for(const chunk of chunkGroup.chunks)
|
for (const chunk of chunkGroup.chunks) initialChunks.add(chunk);
|
||||||
initialChunks.add(chunk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const chunkGroup of queue) {
|
for (const chunkGroup of queue) {
|
||||||
for(const chunk of chunkGroup.chunks) {
|
for (const chunk of chunkGroup.chunks) {
|
||||||
if(!initialChunks.has(chunk))
|
if (!initialChunks.has(chunk)) chunks.add(chunk);
|
||||||
chunks.add(chunk);
|
|
||||||
}
|
}
|
||||||
for(const child of chunkGroup.childrenIterable)
|
for (const child of chunkGroup.childrenIterable) queue.add(child);
|
||||||
queue.add(child);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return chunks;
|
return chunks;
|
||||||
|
@ -342,16 +341,22 @@ class Chunk {
|
||||||
|
|
||||||
getChunkMaps(realHash) {
|
getChunkMaps(realHash) {
|
||||||
const chunkHashMap = Object.create(null);
|
const chunkHashMap = Object.create(null);
|
||||||
|
const chunkContentHashMap = Object.create(null);
|
||||||
const chunkNameMap = Object.create(null);
|
const chunkNameMap = Object.create(null);
|
||||||
|
|
||||||
for(const chunk of this.getAllAsyncChunks()) {
|
for (const chunk of this.getAllAsyncChunks()) {
|
||||||
chunkHashMap[chunk.id] = realHash ? chunk.hash : chunk.renderedHash;
|
chunkHashMap[chunk.id] = realHash ? chunk.hash : chunk.renderedHash;
|
||||||
if(chunk.name)
|
for (const key of Object.keys(chunk.contentHash)) {
|
||||||
chunkNameMap[chunk.id] = chunk.name;
|
if (!chunkContentHashMap[key])
|
||||||
|
chunkContentHashMap[key] = Object.create(null);
|
||||||
|
chunkContentHashMap[key][chunk.id] = chunk.contentHash[key];
|
||||||
|
}
|
||||||
|
if (chunk.name) chunkNameMap[chunk.id] = chunk.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hash: chunkHashMap,
|
hash: chunkHashMap,
|
||||||
|
contentHash: chunkContentHashMap,
|
||||||
name: chunkNameMap
|
name: chunkNameMap
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -360,11 +365,11 @@ class Chunk {
|
||||||
const chunkModuleIdMap = Object.create(null);
|
const chunkModuleIdMap = Object.create(null);
|
||||||
const chunkModuleHashMap = Object.create(null);
|
const chunkModuleHashMap = Object.create(null);
|
||||||
|
|
||||||
for(const chunk of this.getAllAsyncChunks()) {
|
for (const chunk of this.getAllAsyncChunks()) {
|
||||||
let array;
|
let array;
|
||||||
for(const module of chunk.modulesIterable) {
|
for (const module of chunk.modulesIterable) {
|
||||||
if(filterFn(module)) {
|
if (filterFn(module)) {
|
||||||
if(array === undefined) {
|
if (array === undefined) {
|
||||||
array = [];
|
array = [];
|
||||||
chunkModuleIdMap[chunk.id] = array;
|
chunkModuleIdMap[chunk.id] = array;
|
||||||
}
|
}
|
||||||
|
@ -372,7 +377,7 @@ class Chunk {
|
||||||
chunkModuleHashMap[module.id] = module.renderedHash;
|
chunkModuleHashMap[module.id] = module.renderedHash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(array !== undefined) {
|
if (array !== undefined) {
|
||||||
array.sort();
|
array.sort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -387,19 +392,17 @@ class Chunk {
|
||||||
const queue = new Set(this.groupsIterable);
|
const queue = new Set(this.groupsIterable);
|
||||||
const chunksProcessed = new Set();
|
const chunksProcessed = new Set();
|
||||||
|
|
||||||
for(const chunkGroup of queue) {
|
for (const chunkGroup of queue) {
|
||||||
for(const chunk of chunkGroup.chunks) {
|
for (const chunk of chunkGroup.chunks) {
|
||||||
if(!chunksProcessed.has(chunk)) {
|
if (!chunksProcessed.has(chunk)) {
|
||||||
chunksProcessed.add(chunk);
|
chunksProcessed.add(chunk);
|
||||||
if(!filterChunkFn || filterChunkFn(chunk)) {
|
if (!filterChunkFn || filterChunkFn(chunk)) {
|
||||||
for(const module of chunk.modulesIterable)
|
for (const module of chunk.modulesIterable)
|
||||||
if(filterFn(module))
|
if (filterFn(module)) return true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(const child of chunkGroup.childrenIterable)
|
for (const child of chunkGroup.childrenIterable) queue.add(child);
|
||||||
queue.add(child);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -462,7 +465,9 @@ Object.defineProperty(Chunk.prototype, "blocks", {
|
||||||
Object.defineProperty(Chunk.prototype, "entrypoints", {
|
Object.defineProperty(Chunk.prototype, "entrypoints", {
|
||||||
configurable: false,
|
configurable: false,
|
||||||
get() {
|
get() {
|
||||||
throw new Error("Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead");
|
throw new Error(
|
||||||
|
"Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead"
|
||||||
|
);
|
||||||
},
|
},
|
||||||
set() {
|
set() {
|
||||||
throw new Error("Chunk.entrypoints: Use Chunks.addGroup instead");
|
throw new Error("Chunk.entrypoints: Use Chunks.addGroup instead");
|
||||||
|
|
|
@ -12,16 +12,16 @@ let debugId = 5000;
|
||||||
const getArray = set => Array.from(set);
|
const getArray = set => Array.from(set);
|
||||||
|
|
||||||
const sortById = (a, b) => {
|
const sortById = (a, b) => {
|
||||||
if(a.id < b.id) return -1;
|
if (a.id < b.id) return -1;
|
||||||
if(b.id < a.id) return 1;
|
if (b.id < a.id) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
const sortOrigin = (a, b) => {
|
const sortOrigin = (a, b) => {
|
||||||
const aIdent = a.module ? a.module.identifier() : "";
|
const aIdent = a.module ? a.module.identifier() : "";
|
||||||
const bIdent = b.module ? b.module.identifier() : "";
|
const bIdent = b.module ? b.module.identifier() : "";
|
||||||
if(aIdent < bIdent) return -1;
|
if (aIdent < bIdent) return -1;
|
||||||
if(aIdent > bIdent) return 1;
|
if (aIdent > bIdent) return 1;
|
||||||
return compareLocations(a.loc, b.loc);
|
return compareLocations(a.loc, b.loc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,10 +47,10 @@ class ChunkGroup {
|
||||||
|
|
||||||
unshiftChunk(chunk) {
|
unshiftChunk(chunk) {
|
||||||
const oldIdx = this.chunks.indexOf(chunk);
|
const oldIdx = this.chunks.indexOf(chunk);
|
||||||
if(oldIdx > 0) {
|
if (oldIdx > 0) {
|
||||||
this.chunks.splice(oldIdx, 1);
|
this.chunks.splice(oldIdx, 1);
|
||||||
this.chunks.unshift(chunk);
|
this.chunks.unshift(chunk);
|
||||||
} else if(oldIdx < 0) {
|
} else if (oldIdx < 0) {
|
||||||
this.chunks.unshift(chunk);
|
this.chunks.unshift(chunk);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -60,13 +60,13 @@ class ChunkGroup {
|
||||||
insertChunk(chunk, before) {
|
insertChunk(chunk, before) {
|
||||||
const oldIdx = this.chunks.indexOf(chunk);
|
const oldIdx = this.chunks.indexOf(chunk);
|
||||||
const idx = this.chunks.indexOf(before);
|
const idx = this.chunks.indexOf(before);
|
||||||
if(idx < 0) {
|
if (idx < 0) {
|
||||||
throw new Error("before chunk not found");
|
throw new Error("before chunk not found");
|
||||||
}
|
}
|
||||||
if(oldIdx >= 0 && oldIdx > idx) {
|
if (oldIdx >= 0 && oldIdx > idx) {
|
||||||
this.chunks.splice(oldIdx, 1);
|
this.chunks.splice(oldIdx, 1);
|
||||||
this.chunks.splice(idx, 0, chunk);
|
this.chunks.splice(idx, 0, chunk);
|
||||||
} else if(oldIdx < 0) {
|
} else if (oldIdx < 0) {
|
||||||
this.chunks.splice(idx, 0, chunk);
|
this.chunks.splice(idx, 0, chunk);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ class ChunkGroup {
|
||||||
|
|
||||||
pushChunk(chunk) {
|
pushChunk(chunk) {
|
||||||
const oldIdx = this.chunks.indexOf(chunk);
|
const oldIdx = this.chunks.indexOf(chunk);
|
||||||
if(oldIdx >= 0) {
|
if (oldIdx >= 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.chunks.push(chunk);
|
this.chunks.push(chunk);
|
||||||
|
@ -84,16 +84,16 @@ class ChunkGroup {
|
||||||
|
|
||||||
replaceChunk(oldChunk, newChunk) {
|
replaceChunk(oldChunk, newChunk) {
|
||||||
const oldIdx = this.chunks.indexOf(oldChunk);
|
const oldIdx = this.chunks.indexOf(oldChunk);
|
||||||
if(oldIdx < 0) return false;
|
if (oldIdx < 0) return false;
|
||||||
const newIdx = this.chunks.indexOf(newChunk);
|
const newIdx = this.chunks.indexOf(newChunk);
|
||||||
if(newIdx < 0) {
|
if (newIdx < 0) {
|
||||||
this.chunks[oldIdx] = newChunk;
|
this.chunks[oldIdx] = newChunk;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if(newIdx < oldIdx) {
|
if (newIdx < oldIdx) {
|
||||||
this.chunks.splice(oldIdx, 1);
|
this.chunks.splice(oldIdx, 1);
|
||||||
return true;
|
return true;
|
||||||
} else if(newIdx !== oldIdx) {
|
} else if (newIdx !== oldIdx) {
|
||||||
this.chunks[oldIdx] = newChunk;
|
this.chunks[oldIdx] = newChunk;
|
||||||
this.chunks.splice(newIdx, 1);
|
this.chunks.splice(newIdx, 1);
|
||||||
return true;
|
return true;
|
||||||
|
@ -102,7 +102,7 @@ class ChunkGroup {
|
||||||
|
|
||||||
removeChunk(chunk) {
|
removeChunk(chunk) {
|
||||||
const idx = this.chunks.indexOf(chunk);
|
const idx = this.chunks.indexOf(chunk);
|
||||||
if(idx >= 0) {
|
if (idx >= 0) {
|
||||||
this.chunks.splice(idx, 1);
|
this.chunks.splice(idx, 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ class ChunkGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
addChild(chunk) {
|
addChild(chunk) {
|
||||||
if(this._children.has(chunk)) {
|
if (this._children.has(chunk)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this._children.add(chunk);
|
this._children.add(chunk);
|
||||||
|
@ -134,7 +134,7 @@ class ChunkGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
removeChild(chunk) {
|
removeChild(chunk) {
|
||||||
if(!this._children.has(chunk)) {
|
if (!this._children.has(chunk)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ class ChunkGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
addParent(parentChunk) {
|
addParent(parentChunk) {
|
||||||
if(!this._parents.has(parentChunk)) {
|
if (!this._parents.has(parentChunk)) {
|
||||||
this._parents.add(parentChunk);
|
this._parents.add(parentChunk);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -157,8 +157,7 @@ class ChunkGroup {
|
||||||
|
|
||||||
setParents(newParents) {
|
setParents(newParents) {
|
||||||
this._parents.clear();
|
this._parents.clear();
|
||||||
for(const p of newParents)
|
for (const p of newParents) this._parents.add(p);
|
||||||
this._parents.add(p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getNumberOfParents() {
|
getNumberOfParents() {
|
||||||
|
@ -174,7 +173,7 @@ class ChunkGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
removeParent(chunk) {
|
removeParent(chunk) {
|
||||||
if(this._parents.delete(chunk)) {
|
if (this._parents.delete(chunk)) {
|
||||||
chunk.removeChunk(this);
|
chunk.removeChunk(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -201,7 +200,7 @@ class ChunkGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
addBlock(block) {
|
addBlock(block) {
|
||||||
if(!this._blocks.has(block)) {
|
if (!this._blocks.has(block)) {
|
||||||
this._blocks.add(block);
|
this._blocks.add(block);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -217,21 +216,20 @@ class ChunkGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
containsModule(module) {
|
containsModule(module) {
|
||||||
for(const chunk of this.chunks) {
|
for (const chunk of this.chunks) {
|
||||||
if(chunk.containsModule(module))
|
if (chunk.containsModule(module)) return true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(reason) {
|
remove(reason) {
|
||||||
// cleanup parents
|
// cleanup parents
|
||||||
for(const parentChunkGroup of this._parents) {
|
for (const parentChunkGroup of this._parents) {
|
||||||
// remove this chunk from its parents
|
// remove this chunk from its parents
|
||||||
parentChunkGroup._children.delete(this);
|
parentChunkGroup._children.delete(this);
|
||||||
|
|
||||||
// cleanup "sub chunks"
|
// cleanup "sub chunks"
|
||||||
for(const chunkGroup of this._children) {
|
for (const chunkGroup of this._children) {
|
||||||
/**
|
/**
|
||||||
* remove this chunk as "intermediary" and connect
|
* remove this chunk as "intermediary" and connect
|
||||||
* it "sub chunks" and parents directly
|
* it "sub chunks" and parents directly
|
||||||
|
@ -247,20 +245,20 @@ class ChunkGroup {
|
||||||
* we need to iterate again over the children
|
* we need to iterate again over the children
|
||||||
* to remove this from the childs parents.
|
* to remove this from the childs parents.
|
||||||
* This can not be done in the above loop
|
* This can not be done in the above loop
|
||||||
* as it is not garuanteed that `this._parents` contains anything.
|
* as it is not guaranteed that `this._parents` contains anything.
|
||||||
*/
|
*/
|
||||||
for(const chunkGroup of this._children) {
|
for (const chunkGroup of this._children) {
|
||||||
// remove this as parent of every "sub chunk"
|
// remove this as parent of every "sub chunk"
|
||||||
chunkGroup._parents.delete(this);
|
chunkGroup._parents.delete(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleanup blocks
|
// cleanup blocks
|
||||||
for(const block of this._blocks) {
|
for (const block of this._blocks) {
|
||||||
block.chunkGroup = null;
|
block.chunkGroup = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove chunks
|
// remove chunks
|
||||||
for(const chunk of this.chunks) {
|
for (const chunk of this.chunks) {
|
||||||
chunk.removeGroup(this);
|
chunk.removeGroup(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -273,13 +271,21 @@ class ChunkGroup {
|
||||||
|
|
||||||
checkConstraints() {
|
checkConstraints() {
|
||||||
const chunk = this;
|
const chunk = this;
|
||||||
for(const child of chunk._children) {
|
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}`);
|
throw new Error(
|
||||||
|
`checkConstraints: child missing parent ${chunk.debugId} -> ${
|
||||||
|
child.debugId
|
||||||
|
}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
for(const parentChunk of chunk._parents) {
|
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}`);
|
throw new Error(
|
||||||
|
`checkConstraints: parent missing child ${parentChunk.debugId} <- ${
|
||||||
|
chunk.debugId
|
||||||
|
}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,7 @@
|
||||||
*/
|
*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const Tapable = require("tapable").Tapable;
|
const { Tapable, SyncWaterfallHook, SyncHook } = require("tapable");
|
||||||
const SyncWaterfallHook = require("tapable").SyncWaterfallHook;
|
|
||||||
const SyncHook = require("tapable").SyncHook;
|
|
||||||
|
|
||||||
module.exports = class ChunkTemplate extends Tapable {
|
module.exports = class ChunkTemplate extends Tapable {
|
||||||
constructor(outputOptions) {
|
constructor(outputOptions) {
|
||||||
|
@ -14,11 +12,21 @@ module.exports = class ChunkTemplate extends Tapable {
|
||||||
this.outputOptions = outputOptions || {};
|
this.outputOptions = outputOptions || {};
|
||||||
this.hooks = {
|
this.hooks = {
|
||||||
renderManifest: new SyncWaterfallHook(["result", "options"]),
|
renderManifest: new SyncWaterfallHook(["result", "options"]),
|
||||||
modules: new SyncWaterfallHook(["source", "chunk", "moduleTemplate", "dependencyTemplates"]),
|
modules: new SyncWaterfallHook([
|
||||||
render: new SyncWaterfallHook(["source", "chunk", "moduleTemplate", "dependencyTemplates"]),
|
"source",
|
||||||
|
"chunk",
|
||||||
|
"moduleTemplate",
|
||||||
|
"dependencyTemplates"
|
||||||
|
]),
|
||||||
|
render: new SyncWaterfallHook([
|
||||||
|
"source",
|
||||||
|
"chunk",
|
||||||
|
"moduleTemplate",
|
||||||
|
"dependencyTemplates"
|
||||||
|
]),
|
||||||
renderWithEntry: new SyncWaterfallHook(["source", "chunk"]),
|
renderWithEntry: new SyncWaterfallHook(["source", "chunk"]),
|
||||||
hash: new SyncHook(["hash"]),
|
hash: new SyncHook(["hash"]),
|
||||||
hashForChunk: new SyncHook(["hash", "chunk"]),
|
hashForChunk: new SyncHook(["hash", "chunk"])
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,37 +9,55 @@ const ConstDependency = require("./dependencies/ConstDependency");
|
||||||
const NullFactory = require("./NullFactory");
|
const NullFactory = require("./NullFactory");
|
||||||
|
|
||||||
class CompatibilityPlugin {
|
class CompatibilityPlugin {
|
||||||
|
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compilation.tap("CompatibilityPlugin", (compilation, {
|
compiler.hooks.compilation.tap(
|
||||||
normalModuleFactory
|
"CompatibilityPlugin",
|
||||||
}) => {
|
(compilation, { normalModuleFactory }) => {
|
||||||
compilation.dependencyFactories.set(ConstDependency, new NullFactory());
|
compilation.dependencyFactories.set(ConstDependency, new NullFactory());
|
||||||
compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template());
|
compilation.dependencyTemplates.set(
|
||||||
|
ConstDependency,
|
||||||
|
new ConstDependency.Template()
|
||||||
|
);
|
||||||
|
|
||||||
normalModuleFactory.hooks.parser.for("javascript/auto").tap("CompatibilityPlugin", (parser, parserOptions) => {
|
normalModuleFactory.hooks.parser
|
||||||
|
.for("javascript/auto")
|
||||||
|
.tap("CompatibilityPlugin", (parser, parserOptions) => {
|
||||||
|
if (
|
||||||
|
typeof parserOptions.browserify !== "undefined" &&
|
||||||
|
!parserOptions.browserify
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
if(typeof parserOptions.browserify !== "undefined" && !parserOptions.browserify)
|
parser.hooks.call
|
||||||
return;
|
.for("require")
|
||||||
|
.tap("CompatibilityPlugin", expr => {
|
||||||
parser.hooks.call.for("require").tap("CompatibilityPlugin", (expr) => {
|
// support for browserify style require delegator: "require(o, !0)"
|
||||||
// support for browserify style require delegator: "require(o, !0)"
|
if (expr.arguments.length !== 2) return;
|
||||||
if(expr.arguments.length !== 2) return;
|
const second = parser.evaluateExpression(expr.arguments[1]);
|
||||||
const second = parser.evaluateExpression(expr.arguments[1]);
|
if (!second.isBoolean()) return;
|
||||||
if(!second.isBoolean()) return;
|
if (second.asBool() !== true) return;
|
||||||
if(second.asBool() !== true) return;
|
const dep = new ConstDependency("require", expr.callee.range);
|
||||||
const dep = new ConstDependency("require", expr.callee.range);
|
dep.loc = expr.loc;
|
||||||
dep.loc = expr.loc;
|
if (parser.state.current.dependencies.length > 1) {
|
||||||
if(parser.state.current.dependencies.length > 1) {
|
const last =
|
||||||
const last = parser.state.current.dependencies[parser.state.current.dependencies.length - 1];
|
parser.state.current.dependencies[
|
||||||
if(last.critical && last.options && last.options.request === "." && last.userRequest === "." && last.options.recursive)
|
parser.state.current.dependencies.length - 1
|
||||||
parser.state.current.dependencies.pop();
|
];
|
||||||
}
|
if (
|
||||||
parser.state.current.addDependency(dep);
|
last.critical &&
|
||||||
return true;
|
last.options &&
|
||||||
});
|
last.options.request === "." &&
|
||||||
});
|
last.userRequest === "." &&
|
||||||
});
|
last.options.recursive
|
||||||
|
)
|
||||||
|
parser.state.current.dependencies.pop();
|
||||||
|
}
|
||||||
|
parser.state.current.addDependency(dep);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
module.exports = CompatibilityPlugin;
|
module.exports = CompatibilityPlugin;
|
||||||
|
|
1176
lib/Compilation.js
1176
lib/Compilation.js
File diff suppressed because it is too large
Load Diff
337
lib/Compiler.js
337
lib/Compiler.js
|
@ -7,11 +7,13 @@
|
||||||
const asyncLib = require("neo-async");
|
const asyncLib = require("neo-async");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const util = require("util");
|
const util = require("util");
|
||||||
const Tapable = require("tapable").Tapable;
|
const {
|
||||||
const SyncHook = require("tapable").SyncHook;
|
Tapable,
|
||||||
const SyncBailHook = require("tapable").SyncBailHook;
|
SyncHook,
|
||||||
const AsyncParallelHook = require("tapable").AsyncParallelHook;
|
SyncBailHook,
|
||||||
const AsyncSeriesHook = require("tapable").AsyncSeriesHook;
|
AsyncParallelHook,
|
||||||
|
AsyncSeriesHook
|
||||||
|
} = require("tapable");
|
||||||
|
|
||||||
const Compilation = require("./Compilation");
|
const Compilation = require("./Compilation");
|
||||||
const Stats = require("./Stats");
|
const Stats = require("./Stats");
|
||||||
|
@ -21,7 +23,8 @@ const ContextModuleFactory = require("./ContextModuleFactory");
|
||||||
const ResolverFactory = require("./ResolverFactory");
|
const ResolverFactory = require("./ResolverFactory");
|
||||||
|
|
||||||
const RequestShortener = require("./RequestShortener");
|
const RequestShortener = require("./RequestShortener");
|
||||||
const makePathsRelative = require("./util/identifier").makePathsRelative;
|
const { makePathsRelative } = require("./util/identifier");
|
||||||
|
const ConcurrentCompilationError = require("./ConcurrentCompilationError");
|
||||||
|
|
||||||
class Compiler extends Tapable {
|
class Compiler extends Tapable {
|
||||||
constructor(context) {
|
constructor(context) {
|
||||||
|
@ -53,10 +56,10 @@ class Compiler extends Tapable {
|
||||||
afterEnvironment: new SyncHook([]),
|
afterEnvironment: new SyncHook([]),
|
||||||
afterPlugins: new SyncHook(["compiler"]),
|
afterPlugins: new SyncHook(["compiler"]),
|
||||||
afterResolvers: new SyncHook(["compiler"]),
|
afterResolvers: new SyncHook(["compiler"]),
|
||||||
entryOption: new SyncBailHook(["context", "entry"]),
|
entryOption: new SyncBailHook(["context", "entry"])
|
||||||
};
|
};
|
||||||
this._pluginCompat.tap("Compiler", options => {
|
this._pluginCompat.tap("Compiler", options => {
|
||||||
switch(options.name) {
|
switch (options.name) {
|
||||||
case "additional-pass":
|
case "additional-pass":
|
||||||
case "before-run":
|
case "before-run":
|
||||||
case "run":
|
case "run":
|
||||||
|
@ -87,64 +90,40 @@ class Compiler extends Tapable {
|
||||||
// TODO remove in webpack 5
|
// TODO remove in webpack 5
|
||||||
this.resolvers = {
|
this.resolvers = {
|
||||||
normal: {
|
normal: {
|
||||||
plugins: util.deprecate(
|
plugins: util.deprecate((hook, fn) => {
|
||||||
(hook, fn) => {
|
this.resolverFactory.plugin("resolver normal", resolver => {
|
||||||
this.resolverFactory.plugin("resolver normal", resolver => {
|
resolver.plugin(hook, fn);
|
||||||
resolver.plugin(hook, fn);
|
});
|
||||||
});
|
}, "webpack: Using compiler.resolvers.normal is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver normal", resolver => {\n resolver.plugin(/* ... */);\n}); instead.'),
|
||||||
},
|
apply: util.deprecate((...args) => {
|
||||||
"webpack: Using compiler.resolvers.normal is deprecated.\n" +
|
this.resolverFactory.plugin("resolver normal", resolver => {
|
||||||
"Use compiler.resolverFactory.plugin(\"resolver normal\", resolver => {\n resolver.plugin(/* ... */);\n}); instead."
|
resolver.apply(...args);
|
||||||
),
|
});
|
||||||
apply: util.deprecate(
|
}, "webpack: Using compiler.resolvers.normal is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver normal", resolver => {\n resolver.apply(/* ... */);\n}); instead.')
|
||||||
(...args) => {
|
|
||||||
this.resolverFactory.plugin("resolver normal", resolver => {
|
|
||||||
resolver.apply(...args);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
"webpack: Using compiler.resolvers.normal is deprecated.\n" +
|
|
||||||
"Use compiler.resolverFactory.plugin(\"resolver normal\", resolver => {\n resolver.apply(/* ... */);\n}); instead."
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
loader: {
|
loader: {
|
||||||
plugins: util.deprecate(
|
plugins: util.deprecate((hook, fn) => {
|
||||||
(hook, fn) => {
|
this.resolverFactory.plugin("resolver loader", resolver => {
|
||||||
this.resolverFactory.plugin("resolver loader", resolver => {
|
resolver.plugin(hook, fn);
|
||||||
resolver.plugin(hook, fn);
|
});
|
||||||
});
|
}, "webpack: Using compiler.resolvers.loader is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver loader", resolver => {\n resolver.plugin(/* ... */);\n}); instead.'),
|
||||||
},
|
apply: util.deprecate((...args) => {
|
||||||
"webpack: Using compiler.resolvers.loader is deprecated.\n" +
|
this.resolverFactory.plugin("resolver loader", resolver => {
|
||||||
"Use compiler.resolverFactory.plugin(\"resolver loader\", resolver => {\n resolver.plugin(/* ... */);\n}); instead."
|
resolver.apply(...args);
|
||||||
),
|
});
|
||||||
apply: util.deprecate(
|
}, "webpack: Using compiler.resolvers.loader is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver loader", resolver => {\n resolver.apply(/* ... */);\n}); instead.')
|
||||||
(...args) => {
|
|
||||||
this.resolverFactory.plugin("resolver loader", resolver => {
|
|
||||||
resolver.apply(...args);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
"webpack: Using compiler.resolvers.loader is deprecated.\n" +
|
|
||||||
"Use compiler.resolverFactory.plugin(\"resolver loader\", resolver => {\n resolver.apply(/* ... */);\n}); instead."
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
context: {
|
context: {
|
||||||
plugins: util.deprecate(
|
plugins: util.deprecate((hook, fn) => {
|
||||||
(hook, fn) => {
|
this.resolverFactory.plugin("resolver context", resolver => {
|
||||||
this.resolverFactory.plugin("resolver context", resolver => {
|
resolver.plugin(hook, fn);
|
||||||
resolver.plugin(hook, fn);
|
});
|
||||||
});
|
}, "webpack: Using compiler.resolvers.context is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver context", resolver => {\n resolver.plugin(/* ... */);\n}); instead.'),
|
||||||
},
|
apply: util.deprecate((...args) => {
|
||||||
"webpack: Using compiler.resolvers.context is deprecated.\n" +
|
this.resolverFactory.plugin("resolver context", resolver => {
|
||||||
"Use compiler.resolverFactory.plugin(\"resolver context\", resolver => {\n resolver.plugin(/* ... */);\n}); instead."
|
resolver.apply(...args);
|
||||||
),
|
});
|
||||||
apply: util.deprecate(
|
}, "webpack: Using compiler.resolvers.context is deprecated.\n" + 'Use compiler.resolverFactory.plugin("resolver context", resolver => {\n resolver.apply(/* ... */);\n}); instead.')
|
||||||
(...args) => {
|
|
||||||
this.resolverFactory.plugin("resolver context", resolver => {
|
|
||||||
resolver.apply(...args);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
"webpack: Using compiler.resolvers.context is deprecated.\n" +
|
|
||||||
"Use compiler.resolverFactory.plugin(\"resolver context\", resolver => {\n resolver.apply(/* ... */);\n}); instead."
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -153,45 +132,60 @@ class Compiler extends Tapable {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
|
||||||
this.requestShortener = new RequestShortener(context);
|
this.requestShortener = new RequestShortener(context);
|
||||||
|
|
||||||
|
this.running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
watch(watchOptions, handler) {
|
watch(watchOptions, handler) {
|
||||||
|
if (this.running) return handler(new ConcurrentCompilationError());
|
||||||
|
|
||||||
|
this.running = true;
|
||||||
this.fileTimestamps = new Map();
|
this.fileTimestamps = new Map();
|
||||||
this.contextTimestamps = new Map();
|
this.contextTimestamps = new Map();
|
||||||
return new Watching(this, watchOptions, handler);
|
return new Watching(this, watchOptions, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
run(callback) {
|
run(callback) {
|
||||||
|
if (this.running) return callback(new ConcurrentCompilationError());
|
||||||
|
|
||||||
|
const finalCallback = (err, stats) => {
|
||||||
|
this.running = false;
|
||||||
|
|
||||||
|
if (callback !== undefined) return callback(err, stats);
|
||||||
|
};
|
||||||
|
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
|
|
||||||
const onCompiled = (err, compilation) => {
|
this.running = true;
|
||||||
if(err) return callback(err);
|
|
||||||
|
|
||||||
if(this.hooks.shouldEmit.call(compilation) === false) {
|
const onCompiled = (err, compilation) => {
|
||||||
|
if (err) return finalCallback(err);
|
||||||
|
|
||||||
|
if (this.hooks.shouldEmit.call(compilation) === false) {
|
||||||
const stats = new Stats(compilation);
|
const stats = new Stats(compilation);
|
||||||
stats.startTime = startTime;
|
stats.startTime = startTime;
|
||||||
stats.endTime = Date.now();
|
stats.endTime = Date.now();
|
||||||
this.hooks.done.callAsync(stats, err => {
|
this.hooks.done.callAsync(stats, err => {
|
||||||
if(err) return callback(err);
|
if (err) return finalCallback(err);
|
||||||
return callback(null, stats);
|
return finalCallback(null, stats);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emitAssets(compilation, err => {
|
this.emitAssets(compilation, err => {
|
||||||
if(err) return callback(err);
|
if (err) return finalCallback(err);
|
||||||
|
|
||||||
if(compilation.hooks.needAdditionalPass.call()) {
|
if (compilation.hooks.needAdditionalPass.call()) {
|
||||||
compilation.needAdditionalPass = true;
|
compilation.needAdditionalPass = true;
|
||||||
|
|
||||||
const stats = new Stats(compilation);
|
const stats = new Stats(compilation);
|
||||||
stats.startTime = startTime;
|
stats.startTime = startTime;
|
||||||
stats.endTime = Date.now();
|
stats.endTime = Date.now();
|
||||||
this.hooks.done.callAsync(stats, err => {
|
this.hooks.done.callAsync(stats, err => {
|
||||||
if(err) return callback(err);
|
if (err) return finalCallback(err);
|
||||||
|
|
||||||
this.hooks.additionalPass.callAsync(err => {
|
this.hooks.additionalPass.callAsync(err => {
|
||||||
if(err) return callback(err);
|
if (err) return finalCallback(err);
|
||||||
this.compile(onCompiled);
|
this.compile(onCompiled);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -199,27 +193,27 @@ class Compiler extends Tapable {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emitRecords(err => {
|
this.emitRecords(err => {
|
||||||
if(err) return callback(err);
|
if (err) return finalCallback(err);
|
||||||
|
|
||||||
const stats = new Stats(compilation);
|
const stats = new Stats(compilation);
|
||||||
stats.startTime = startTime;
|
stats.startTime = startTime;
|
||||||
stats.endTime = Date.now();
|
stats.endTime = Date.now();
|
||||||
this.hooks.done.callAsync(stats, err => {
|
this.hooks.done.callAsync(stats, err => {
|
||||||
if(err) return callback(err);
|
if (err) return finalCallback(err);
|
||||||
return callback(null, stats);
|
return finalCallback(null, stats);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.hooks.beforeRun.callAsync(this, err => {
|
this.hooks.beforeRun.callAsync(this, err => {
|
||||||
if(err) return callback(err);
|
if (err) return finalCallback(err);
|
||||||
|
|
||||||
this.hooks.run.callAsync(this, err => {
|
this.hooks.run.callAsync(this, err => {
|
||||||
if(err) return callback(err);
|
if (err) return finalCallback(err);
|
||||||
|
|
||||||
this.readRecords(err => {
|
this.readRecords(err => {
|
||||||
if(err) return callback(err);
|
if (err) return finalCallback(err);
|
||||||
|
|
||||||
this.compile(onCompiled);
|
this.compile(onCompiled);
|
||||||
});
|
});
|
||||||
|
@ -229,14 +223,17 @@ class Compiler extends Tapable {
|
||||||
|
|
||||||
runAsChild(callback) {
|
runAsChild(callback) {
|
||||||
this.compile((err, compilation) => {
|
this.compile((err, compilation) => {
|
||||||
if(err) return callback(err);
|
if (err) return callback(err);
|
||||||
|
|
||||||
this.parentCompilation.children.push(compilation);
|
this.parentCompilation.children.push(compilation);
|
||||||
for(const name of Object.keys(compilation.assets)) {
|
for (const name of Object.keys(compilation.assets)) {
|
||||||
this.parentCompilation.assets[name] = compilation.assets[name];
|
this.parentCompilation.assets[name] = compilation.assets[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
const entries = Array.from(compilation.entrypoints.values(), ep => ep.chunks).reduce((array, chunks) => {
|
const entries = Array.from(
|
||||||
|
compilation.entrypoints.values(),
|
||||||
|
ep => ep.chunks
|
||||||
|
).reduce((array, chunks) => {
|
||||||
return array.concat(chunks);
|
return array.concat(chunks);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@ -245,101 +242,114 @@ class Compiler extends Tapable {
|
||||||
}
|
}
|
||||||
|
|
||||||
purgeInputFileSystem() {
|
purgeInputFileSystem() {
|
||||||
if(this.inputFileSystem && this.inputFileSystem.purge)
|
if (this.inputFileSystem && this.inputFileSystem.purge)
|
||||||
this.inputFileSystem.purge();
|
this.inputFileSystem.purge();
|
||||||
}
|
}
|
||||||
|
|
||||||
emitAssets(compilation, callback) {
|
emitAssets(compilation, callback) {
|
||||||
let outputPath;
|
let outputPath;
|
||||||
|
|
||||||
const emitFiles = (err) => {
|
const emitFiles = err => {
|
||||||
if(err) return callback(err);
|
if (err) return callback(err);
|
||||||
|
|
||||||
asyncLib.forEach(compilation.assets, (source, file, callback) => {
|
asyncLib.forEach(
|
||||||
|
compilation.assets,
|
||||||
|
(source, file, callback) => {
|
||||||
|
let targetFile = file;
|
||||||
|
const queryStringIdx = targetFile.indexOf("?");
|
||||||
|
if (queryStringIdx >= 0) {
|
||||||
|
targetFile = targetFile.substr(0, queryStringIdx);
|
||||||
|
}
|
||||||
|
|
||||||
let targetFile = file;
|
const writeOut = err => {
|
||||||
const queryStringIdx = targetFile.indexOf("?");
|
if (err) return callback(err);
|
||||||
if(queryStringIdx >= 0) {
|
const targetPath = this.outputFileSystem.join(
|
||||||
targetFile = targetFile.substr(0, queryStringIdx);
|
outputPath,
|
||||||
}
|
targetFile
|
||||||
|
);
|
||||||
|
if (source.existsAt === targetPath) {
|
||||||
|
source.emitted = false;
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
let content = source.source();
|
||||||
|
|
||||||
|
if (!Buffer.isBuffer(content)) {
|
||||||
|
content = Buffer.from(content, "utf8");
|
||||||
|
}
|
||||||
|
|
||||||
|
source.existsAt = targetPath;
|
||||||
|
source.emitted = true;
|
||||||
|
this.outputFileSystem.writeFile(targetPath, content, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (targetFile.match(/\/|\\/)) {
|
||||||
|
const dir = path.dirname(targetFile);
|
||||||
|
this.outputFileSystem.mkdirp(
|
||||||
|
this.outputFileSystem.join(outputPath, dir),
|
||||||
|
writeOut
|
||||||
|
);
|
||||||
|
} else writeOut();
|
||||||
|
},
|
||||||
|
err => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
|
||||||
|
this.hooks.afterEmit.callAsync(compilation, err => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
|
||||||
const writeOut = (err) => {
|
|
||||||
if(err) return callback(err);
|
|
||||||
const targetPath = this.outputFileSystem.join(outputPath, targetFile);
|
|
||||||
if(source.existsAt === targetPath) {
|
|
||||||
source.emitted = false;
|
|
||||||
return callback();
|
return callback();
|
||||||
}
|
});
|
||||||
let content = source.source();
|
}
|
||||||
|
);
|
||||||
if(!Buffer.isBuffer(content)) {
|
|
||||||
content = Buffer.from(content, "utf8");
|
|
||||||
}
|
|
||||||
|
|
||||||
source.existsAt = targetPath;
|
|
||||||
source.emitted = true;
|
|
||||||
this.outputFileSystem.writeFile(targetPath, content, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
if(targetFile.match(/\/|\\/)) {
|
|
||||||
const dir = path.dirname(targetFile);
|
|
||||||
this.outputFileSystem.mkdirp(this.outputFileSystem.join(outputPath, dir), writeOut);
|
|
||||||
} else writeOut();
|
|
||||||
|
|
||||||
}, err => {
|
|
||||||
if(err) return callback(err);
|
|
||||||
|
|
||||||
this.hooks.afterEmit.callAsync(compilation, err => {
|
|
||||||
if(err) return callback(err);
|
|
||||||
|
|
||||||
return callback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.hooks.emit.callAsync(compilation, err => {
|
this.hooks.emit.callAsync(compilation, err => {
|
||||||
if(err) return callback(err);
|
if (err) return callback(err);
|
||||||
outputPath = compilation.getPath(this.outputPath);
|
outputPath = compilation.getPath(this.outputPath);
|
||||||
this.outputFileSystem.mkdirp(outputPath, emitFiles);
|
this.outputFileSystem.mkdirp(outputPath, emitFiles);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
emitRecords(callback) {
|
emitRecords(callback) {
|
||||||
if(!this.recordsOutputPath) return callback();
|
if (!this.recordsOutputPath) return callback();
|
||||||
const idx1 = this.recordsOutputPath.lastIndexOf("/");
|
const idx1 = this.recordsOutputPath.lastIndexOf("/");
|
||||||
const idx2 = this.recordsOutputPath.lastIndexOf("\\");
|
const idx2 = this.recordsOutputPath.lastIndexOf("\\");
|
||||||
let recordsOutputPathDirectory = null;
|
let recordsOutputPathDirectory = null;
|
||||||
if(idx1 > idx2) recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx1);
|
if (idx1 > idx2)
|
||||||
if(idx1 < idx2) recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx2);
|
recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx1);
|
||||||
|
if (idx1 < idx2)
|
||||||
|
recordsOutputPathDirectory = this.recordsOutputPath.substr(0, idx2);
|
||||||
|
|
||||||
const writeFile = () => {
|
const writeFile = () => {
|
||||||
this.outputFileSystem.writeFile(this.recordsOutputPath, JSON.stringify(this.records, undefined, 2), callback);
|
this.outputFileSystem.writeFile(
|
||||||
|
this.recordsOutputPath,
|
||||||
|
JSON.stringify(this.records, undefined, 2),
|
||||||
|
callback
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
if(!recordsOutputPathDirectory)
|
if (!recordsOutputPathDirectory) return writeFile();
|
||||||
return writeFile();
|
|
||||||
this.outputFileSystem.mkdirp(recordsOutputPathDirectory, err => {
|
this.outputFileSystem.mkdirp(recordsOutputPathDirectory, err => {
|
||||||
if(err) return callback(err);
|
if (err) return callback(err);
|
||||||
writeFile();
|
writeFile();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
readRecords(callback) {
|
readRecords(callback) {
|
||||||
if(!this.recordsInputPath) {
|
if (!this.recordsInputPath) {
|
||||||
this.records = {};
|
this.records = {};
|
||||||
return callback();
|
return callback();
|
||||||
}
|
}
|
||||||
this.inputFileSystem.stat(this.recordsInputPath, err => {
|
this.inputFileSystem.stat(this.recordsInputPath, err => {
|
||||||
// It doesn't exist
|
// It doesn't exist
|
||||||
// We can ignore this.
|
// We can ignore this.
|
||||||
if(err) return callback();
|
if (err) return callback();
|
||||||
|
|
||||||
this.inputFileSystem.readFile(this.recordsInputPath, (err, content) => {
|
this.inputFileSystem.readFile(this.recordsInputPath, (err, content) => {
|
||||||
if(err) return callback(err);
|
if (err) return callback(err);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.records = JSON.parse(content.toString("utf-8"));
|
this.records = JSON.parse(content.toString("utf-8"));
|
||||||
} catch(e) {
|
} catch (e) {
|
||||||
e.message = "Cannot parse records: " + e.message;
|
e.message = "Cannot parse records: " + e.message;
|
||||||
return callback(e);
|
return callback(e);
|
||||||
}
|
}
|
||||||
|
@ -349,14 +359,30 @@ class Compiler extends Tapable {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
createChildCompiler(compilation, compilerName, compilerIndex, outputOptions, plugins) {
|
createChildCompiler(
|
||||||
|
compilation,
|
||||||
|
compilerName,
|
||||||
|
compilerIndex,
|
||||||
|
outputOptions,
|
||||||
|
plugins
|
||||||
|
) {
|
||||||
const childCompiler = new Compiler(this.context);
|
const childCompiler = new Compiler(this.context);
|
||||||
if(Array.isArray(plugins)) {
|
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) {
|
for (const name in this.hooks) {
|
||||||
if(!["make", "compile", "emit", "afterEmit", "invalid", "done", "thisCompilation"].includes(name)) {
|
if (
|
||||||
if(childCompiler.hooks[name])
|
![
|
||||||
|
"make",
|
||||||
|
"compile",
|
||||||
|
"emit",
|
||||||
|
"afterEmit",
|
||||||
|
"invalid",
|
||||||
|
"done",
|
||||||
|
"thisCompilation"
|
||||||
|
].includes(name)
|
||||||
|
) {
|
||||||
|
if (childCompiler.hooks[name])
|
||||||
childCompiler.hooks[name].taps = this.hooks[name].taps.slice();
|
childCompiler.hooks[name].taps = this.hooks[name].taps.slice();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -369,20 +395,24 @@ class Compiler extends Tapable {
|
||||||
childCompiler.contextTimestamps = this.contextTimestamps;
|
childCompiler.contextTimestamps = this.contextTimestamps;
|
||||||
|
|
||||||
const relativeCompilerName = makePathsRelative(this.context, compilerName);
|
const relativeCompilerName = makePathsRelative(this.context, compilerName);
|
||||||
if(!this.records[relativeCompilerName]) this.records[relativeCompilerName] = [];
|
if (!this.records[relativeCompilerName])
|
||||||
if(this.records[relativeCompilerName][compilerIndex])
|
this.records[relativeCompilerName] = [];
|
||||||
|
if (this.records[relativeCompilerName][compilerIndex])
|
||||||
childCompiler.records = this.records[relativeCompilerName][compilerIndex];
|
childCompiler.records = this.records[relativeCompilerName][compilerIndex];
|
||||||
else
|
else this.records[relativeCompilerName].push((childCompiler.records = {}));
|
||||||
this.records[relativeCompilerName].push(childCompiler.records = {});
|
|
||||||
|
|
||||||
childCompiler.options = Object.create(this.options);
|
childCompiler.options = Object.create(this.options);
|
||||||
childCompiler.options.output = Object.create(childCompiler.options.output);
|
childCompiler.options.output = Object.create(childCompiler.options.output);
|
||||||
for(const name in outputOptions) {
|
for (const name in outputOptions) {
|
||||||
childCompiler.options.output[name] = outputOptions[name];
|
childCompiler.options.output[name] = outputOptions[name];
|
||||||
}
|
}
|
||||||
childCompiler.parentCompilation = compilation;
|
childCompiler.parentCompilation = compilation;
|
||||||
|
|
||||||
compilation.hooks.childCompiler.call(childCompiler, compilerName, compilerIndex);
|
compilation.hooks.childCompiler.call(
|
||||||
|
childCompiler,
|
||||||
|
compilerName,
|
||||||
|
compilerIndex
|
||||||
|
);
|
||||||
|
|
||||||
return childCompiler;
|
return childCompiler;
|
||||||
}
|
}
|
||||||
|
@ -408,13 +438,20 @@ class Compiler extends Tapable {
|
||||||
}
|
}
|
||||||
|
|
||||||
createNormalModuleFactory() {
|
createNormalModuleFactory() {
|
||||||
const normalModuleFactory = new NormalModuleFactory(this.options.context, this.resolverFactory, this.options.module || {});
|
const normalModuleFactory = new NormalModuleFactory(
|
||||||
|
this.options.context,
|
||||||
|
this.resolverFactory,
|
||||||
|
this.options.module || {}
|
||||||
|
);
|
||||||
this.hooks.normalModuleFactory.call(normalModuleFactory);
|
this.hooks.normalModuleFactory.call(normalModuleFactory);
|
||||||
return normalModuleFactory;
|
return normalModuleFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
createContextModuleFactory() {
|
createContextModuleFactory() {
|
||||||
const contextModuleFactory = new ContextModuleFactory(this.resolverFactory, this.inputFileSystem);
|
const contextModuleFactory = new ContextModuleFactory(
|
||||||
|
this.resolverFactory,
|
||||||
|
this.inputFileSystem
|
||||||
|
);
|
||||||
this.hooks.contextModuleFactory.call(contextModuleFactory);
|
this.hooks.contextModuleFactory.call(contextModuleFactory);
|
||||||
return contextModuleFactory;
|
return contextModuleFactory;
|
||||||
}
|
}
|
||||||
|
@ -431,22 +468,22 @@ class Compiler extends Tapable {
|
||||||
compile(callback) {
|
compile(callback) {
|
||||||
const params = this.newCompilationParams();
|
const params = this.newCompilationParams();
|
||||||
this.hooks.beforeCompile.callAsync(params, err => {
|
this.hooks.beforeCompile.callAsync(params, err => {
|
||||||
if(err) return callback(err);
|
if (err) return callback(err);
|
||||||
|
|
||||||
this.hooks.compile.call(params);
|
this.hooks.compile.call(params);
|
||||||
|
|
||||||
const compilation = this.newCompilation(params);
|
const compilation = this.newCompilation(params);
|
||||||
|
|
||||||
this.hooks.make.callAsync(compilation, err => {
|
this.hooks.make.callAsync(compilation, err => {
|
||||||
if(err) return callback(err);
|
if (err) return callback(err);
|
||||||
|
|
||||||
compilation.finish();
|
compilation.finish();
|
||||||
|
|
||||||
compilation.seal(err => {
|
compilation.seal(err => {
|
||||||
if(err) return callback(err);
|
if (err) return callback(err);
|
||||||
|
|
||||||
this.hooks.afterCompile.callAsync(compilation, err => {
|
this.hooks.afterCompile.callAsync(compilation, err => {
|
||||||
if(err) return callback(err);
|
if (err) return callback(err);
|
||||||
|
|
||||||
return callback(null, compilation);
|
return callback(null, compilation);
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||||
|
Author Maksim Nazarjev @acupofspirt
|
||||||
|
*/
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const WebpackError = require("./WebpackError");
|
||||||
|
|
||||||
|
module.exports = class ConcurrentCompilationError extends WebpackError {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "ConcurrentCompilationError";
|
||||||
|
this.message =
|
||||||
|
"You ran Webpack twice. Each instance only supports a single concurrent compilation at a time.";
|
||||||
|
|
||||||
|
Error.captureStackTrace(this, this.constructor);
|
||||||
|
}
|
||||||
|
};
|
|
@ -7,29 +7,27 @@ const ConstDependency = require("./dependencies/ConstDependency");
|
||||||
const NullFactory = require("./NullFactory");
|
const NullFactory = require("./NullFactory");
|
||||||
const ParserHelpers = require("./ParserHelpers");
|
const ParserHelpers = require("./ParserHelpers");
|
||||||
|
|
||||||
const getQuery = (request) => {
|
const getQuery = request => {
|
||||||
const i = request.indexOf("?");
|
const i = request.indexOf("?");
|
||||||
return i !== -1 ? request.substr(i) : "";
|
return i !== -1 ? request.substr(i) : "";
|
||||||
};
|
};
|
||||||
|
|
||||||
const collectDeclaration = (declarations, pattern) => {
|
const collectDeclaration = (declarations, pattern) => {
|
||||||
const stack = [pattern];
|
const stack = [pattern];
|
||||||
while(stack.length > 0) {
|
while (stack.length > 0) {
|
||||||
const node = stack.pop();
|
const node = stack.pop();
|
||||||
switch(node.type) {
|
switch (node.type) {
|
||||||
case "Identifier":
|
case "Identifier":
|
||||||
declarations.add(node.name);
|
declarations.add(node.name);
|
||||||
break;
|
break;
|
||||||
case "ArrayPattern":
|
case "ArrayPattern":
|
||||||
for(const element of node.elements)
|
for (const element of node.elements) if (element) stack.push(element);
|
||||||
if(element) stack.push(element);
|
|
||||||
break;
|
break;
|
||||||
case "AssignmentPattern":
|
case "AssignmentPattern":
|
||||||
stack.push(node.left);
|
stack.push(node.left);
|
||||||
break;
|
break;
|
||||||
case "ObjectPattern":
|
case "ObjectPattern":
|
||||||
for(const property of node.properties)
|
for (const property of node.properties) stack.push(property.value);
|
||||||
stack.push(property.value);
|
|
||||||
break;
|
break;
|
||||||
case "RestElement":
|
case "RestElement":
|
||||||
stack.push(node.argument);
|
stack.push(node.argument);
|
||||||
|
@ -41,17 +39,15 @@ const collectDeclaration = (declarations, pattern) => {
|
||||||
const getHoistedDeclarations = (branch, includeFunctionDeclarations) => {
|
const getHoistedDeclarations = (branch, includeFunctionDeclarations) => {
|
||||||
const declarations = new Set();
|
const declarations = new Set();
|
||||||
const stack = [branch];
|
const stack = [branch];
|
||||||
while(stack.length > 0) {
|
while (stack.length > 0) {
|
||||||
const node = stack.pop();
|
const node = stack.pop();
|
||||||
// Some node could be `null` or `undefined`.
|
// Some node could be `null` or `undefined`.
|
||||||
if(!node)
|
if (!node) continue;
|
||||||
continue;
|
switch (node.type) {
|
||||||
switch(node.type) {
|
|
||||||
// Walk through control statements to look for hoisted declarations.
|
// Walk through control statements to look for hoisted declarations.
|
||||||
// Some branches are skipped since they do not allow declarations.
|
// Some branches are skipped since they do not allow declarations.
|
||||||
case "BlockStatement":
|
case "BlockStatement":
|
||||||
for(const stmt of node.body)
|
for (const stmt of node.body) stack.push(stmt);
|
||||||
stack.push(stmt);
|
|
||||||
break;
|
break;
|
||||||
case "IfStatement":
|
case "IfStatement":
|
||||||
stack.push(node.consequent);
|
stack.push(node.consequent);
|
||||||
|
@ -72,23 +68,21 @@ const getHoistedDeclarations = (branch, includeFunctionDeclarations) => {
|
||||||
stack.push(node.body);
|
stack.push(node.body);
|
||||||
break;
|
break;
|
||||||
case "SwitchStatement":
|
case "SwitchStatement":
|
||||||
for(const cs of node.cases)
|
for (const cs of node.cases)
|
||||||
for(const consequent of cs.consequent)
|
for (const consequent of cs.consequent) stack.push(consequent);
|
||||||
stack.push(consequent);
|
|
||||||
break;
|
break;
|
||||||
case "TryStatement":
|
case "TryStatement":
|
||||||
stack.push(node.block);
|
stack.push(node.block);
|
||||||
if(node.handler)
|
if (node.handler) stack.push(node.handler.body);
|
||||||
stack.push(node.handler.body);
|
|
||||||
stack.push(node.finalizer);
|
stack.push(node.finalizer);
|
||||||
break;
|
break;
|
||||||
case "FunctionDeclaration":
|
case "FunctionDeclaration":
|
||||||
if(includeFunctionDeclarations)
|
if (includeFunctionDeclarations)
|
||||||
collectDeclaration(declarations, node.id);
|
collectDeclaration(declarations, node.id);
|
||||||
break;
|
break;
|
||||||
case "VariableDeclaration":
|
case "VariableDeclaration":
|
||||||
if(node.kind === "var")
|
if (node.kind === "var")
|
||||||
for(const decl of node.declarations)
|
for (const decl of node.declarations)
|
||||||
collectDeclaration(declarations, decl.id);
|
collectDeclaration(declarations, decl.id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -98,118 +92,150 @@ const getHoistedDeclarations = (branch, includeFunctionDeclarations) => {
|
||||||
|
|
||||||
class ConstPlugin {
|
class ConstPlugin {
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compilation.tap("ConstPlugin", (compilation, {
|
compiler.hooks.compilation.tap(
|
||||||
normalModuleFactory
|
"ConstPlugin",
|
||||||
}) => {
|
(compilation, { normalModuleFactory }) => {
|
||||||
compilation.dependencyFactories.set(ConstDependency, new NullFactory());
|
compilation.dependencyFactories.set(ConstDependency, new NullFactory());
|
||||||
compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template());
|
compilation.dependencyTemplates.set(
|
||||||
|
ConstDependency,
|
||||||
|
new ConstDependency.Template()
|
||||||
|
);
|
||||||
|
|
||||||
const handler = parser => {
|
const handler = parser => {
|
||||||
parser.hooks.statementIf.tap("ConstPlugin", statement => {
|
parser.hooks.statementIf.tap("ConstPlugin", statement => {
|
||||||
const param = parser.evaluateExpression(statement.test);
|
const param = parser.evaluateExpression(statement.test);
|
||||||
const bool = param.asBool();
|
const bool = param.asBool();
|
||||||
if(typeof bool === "boolean") {
|
if (typeof bool === "boolean") {
|
||||||
if(statement.test.type !== "Literal") {
|
if (statement.test.type !== "Literal") {
|
||||||
const dep = new ConstDependency(`${bool}`, param.range);
|
const dep = new ConstDependency(`${bool}`, param.range);
|
||||||
dep.loc = statement.loc;
|
dep.loc = statement.loc;
|
||||||
parser.state.current.addDependency(dep);
|
parser.state.current.addDependency(dep);
|
||||||
}
|
|
||||||
const branchToRemove = bool ? statement.alternate : statement.consequent;
|
|
||||||
if(branchToRemove) {
|
|
||||||
// Before removing the dead branch, the hoisted declarations
|
|
||||||
// must be collected.
|
|
||||||
//
|
|
||||||
// Given the following code:
|
|
||||||
//
|
|
||||||
// if (true) f() else g()
|
|
||||||
// if (false) {
|
|
||||||
// function f() {}
|
|
||||||
// const g = function g() {}
|
|
||||||
// if (someTest) {
|
|
||||||
// let a = 1
|
|
||||||
// var x, {y, z} = obj
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// …
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// the generated code is:
|
|
||||||
//
|
|
||||||
// if (true) f() else {}
|
|
||||||
// if (false) {
|
|
||||||
// var f, x, y, z; (in loose mode)
|
|
||||||
// var x, y, z; (in strict mode)
|
|
||||||
// } else {
|
|
||||||
// …
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// NOTE: When code runs in strict mode, `var` declarations
|
|
||||||
// are hoisted but `function` declarations don't.
|
|
||||||
//
|
|
||||||
let declarations;
|
|
||||||
if(parser.scope.isStrict) {
|
|
||||||
// If the code runs in strict mode, variable declarations
|
|
||||||
// using `var` must be hoisted.
|
|
||||||
declarations = getHoistedDeclarations(branchToRemove, false);
|
|
||||||
} else {
|
|
||||||
// Otherwise, collect all hoisted declaration.
|
|
||||||
declarations = getHoistedDeclarations(branchToRemove, true);
|
|
||||||
}
|
}
|
||||||
let replacement;
|
const branchToRemove = bool
|
||||||
if(declarations.length > 0) {
|
? statement.alternate
|
||||||
replacement = `{ var ${declarations.join(", ")}; }`;
|
: statement.consequent;
|
||||||
} else {
|
if (branchToRemove) {
|
||||||
replacement = "{}";
|
// Before removing the dead branch, the hoisted declarations
|
||||||
|
// must be collected.
|
||||||
|
//
|
||||||
|
// Given the following code:
|
||||||
|
//
|
||||||
|
// if (true) f() else g()
|
||||||
|
// if (false) {
|
||||||
|
// function f() {}
|
||||||
|
// const g = function g() {}
|
||||||
|
// if (someTest) {
|
||||||
|
// let a = 1
|
||||||
|
// var x, {y, z} = obj
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// …
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// the generated code is:
|
||||||
|
//
|
||||||
|
// if (true) f() else {}
|
||||||
|
// if (false) {
|
||||||
|
// var f, x, y, z; (in loose mode)
|
||||||
|
// var x, y, z; (in strict mode)
|
||||||
|
// } else {
|
||||||
|
// …
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// NOTE: When code runs in strict mode, `var` declarations
|
||||||
|
// are hoisted but `function` declarations don't.
|
||||||
|
//
|
||||||
|
let declarations;
|
||||||
|
if (parser.scope.isStrict) {
|
||||||
|
// If the code runs in strict mode, variable declarations
|
||||||
|
// using `var` must be hoisted.
|
||||||
|
declarations = getHoistedDeclarations(branchToRemove, false);
|
||||||
|
} else {
|
||||||
|
// Otherwise, collect all hoisted declaration.
|
||||||
|
declarations = getHoistedDeclarations(branchToRemove, true);
|
||||||
|
}
|
||||||
|
let replacement;
|
||||||
|
if (declarations.length > 0) {
|
||||||
|
replacement = `{ var ${declarations.join(", ")}; }`;
|
||||||
|
} else {
|
||||||
|
replacement = "{}";
|
||||||
|
}
|
||||||
|
const dep = new ConstDependency(
|
||||||
|
replacement,
|
||||||
|
branchToRemove.range
|
||||||
|
);
|
||||||
|
dep.loc = branchToRemove.loc;
|
||||||
|
parser.state.current.addDependency(dep);
|
||||||
}
|
}
|
||||||
const dep = new ConstDependency(replacement, branchToRemove.range);
|
return bool;
|
||||||
dep.loc = branchToRemove.loc;
|
|
||||||
parser.state.current.addDependency(dep);
|
|
||||||
}
|
}
|
||||||
return bool;
|
});
|
||||||
}
|
parser.hooks.expressionConditionalOperator.tap(
|
||||||
});
|
"ConstPlugin",
|
||||||
parser.hooks.expressionConditionalOperator.tap("ConstPlugin", expression => {
|
expression => {
|
||||||
const param = parser.evaluateExpression(expression.test);
|
const param = parser.evaluateExpression(expression.test);
|
||||||
const bool = param.asBool();
|
const bool = param.asBool();
|
||||||
if(typeof bool === "boolean") {
|
if (typeof bool === "boolean") {
|
||||||
if(expression.test.type !== "Literal") {
|
if (expression.test.type !== "Literal") {
|
||||||
const dep = new ConstDependency(` ${bool}`, param.range);
|
const dep = new ConstDependency(` ${bool}`, param.range);
|
||||||
dep.loc = expression.loc;
|
dep.loc = expression.loc;
|
||||||
parser.state.current.addDependency(dep);
|
parser.state.current.addDependency(dep);
|
||||||
|
}
|
||||||
|
// Expressions do not hoist.
|
||||||
|
// It is safe to remove the dead branch.
|
||||||
|
//
|
||||||
|
// Given the following code:
|
||||||
|
//
|
||||||
|
// false ? someExpression() : otherExpression();
|
||||||
|
//
|
||||||
|
// the generated code is:
|
||||||
|
//
|
||||||
|
// false ? undefined : otherExpression();
|
||||||
|
//
|
||||||
|
const branchToRemove = bool
|
||||||
|
? expression.alternate
|
||||||
|
: expression.consequent;
|
||||||
|
const dep = new ConstDependency(
|
||||||
|
"undefined",
|
||||||
|
branchToRemove.range
|
||||||
|
);
|
||||||
|
dep.loc = branchToRemove.loc;
|
||||||
|
parser.state.current.addDependency(dep);
|
||||||
|
return bool;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Expressions do not hoist.
|
);
|
||||||
// It is safe to remove the dead branch.
|
parser.hooks.evaluateIdentifier
|
||||||
//
|
.for("__resourceQuery")
|
||||||
// Given the following code:
|
.tap("ConstPlugin", expr => {
|
||||||
//
|
if (!parser.state.module) return;
|
||||||
// false ? someExpression() : otherExpression();
|
return ParserHelpers.evaluateToString(
|
||||||
//
|
getQuery(parser.state.module.resource)
|
||||||
// the generated code is:
|
)(expr);
|
||||||
//
|
});
|
||||||
// false ? undefined : otherExpression();
|
parser.hooks.expression
|
||||||
//
|
.for("__resourceQuery")
|
||||||
const branchToRemove = bool ? expression.alternate : expression.consequent;
|
.tap("ConstPlugin", () => {
|
||||||
const dep = new ConstDependency("undefined", branchToRemove.range);
|
if (!parser.state.module) return;
|
||||||
dep.loc = branchToRemove.loc;
|
parser.state.current.addVariable(
|
||||||
parser.state.current.addDependency(dep);
|
"__resourceQuery",
|
||||||
return bool;
|
JSON.stringify(getQuery(parser.state.module.resource))
|
||||||
}
|
);
|
||||||
});
|
return true;
|
||||||
parser.hooks.evaluateIdentifier.for("__resourceQuery").tap("ConstPlugin", expr => {
|
});
|
||||||
if(!parser.state.module) return;
|
};
|
||||||
return ParserHelpers.evaluateToString(getQuery(parser.state.module.resource))(expr);
|
|
||||||
});
|
|
||||||
parser.hooks.expression.for("__resourceQuery").tap("ConstPlugin", () => {
|
|
||||||
if(!parser.state.module) return;
|
|
||||||
parser.state.current.addVariable("__resourceQuery", JSON.stringify(getQuery(parser.state.module.resource)));
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
normalModuleFactory.hooks.parser.for("javascript/auto").tap("ConstPlugin", handler);
|
normalModuleFactory.hooks.parser
|
||||||
normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("ConstPlugin", handler);
|
.for("javascript/auto")
|
||||||
normalModuleFactory.hooks.parser.for("javascript/esm").tap("ConstPlugin", handler);
|
.tap("ConstPlugin", handler);
|
||||||
});
|
normalModuleFactory.hooks.parser
|
||||||
|
.for("javascript/dynamic")
|
||||||
|
.tap("ConstPlugin", handler);
|
||||||
|
normalModuleFactory.hooks.parser
|
||||||
|
.for("javascript/esm")
|
||||||
|
.tap("ConstPlugin", handler);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@ class ContextExclusionPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.contextModuleFactory.tap("ContextExclusionPlugin", (cmf) => {
|
compiler.hooks.contextModuleFactory.tap("ContextExclusionPlugin", cmf => {
|
||||||
cmf.hooks.contextModuleFiles.tap("ContextExclusionPlugin", (files) => {
|
cmf.hooks.contextModuleFiles.tap("ContextExclusionPlugin", files => {
|
||||||
return files.filter(filePath => !this.negativeMatcher.test(filePath));
|
return files.filter(filePath => !this.negativeMatcher.test(filePath));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,9 +5,8 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const util = require("util");
|
const util = require("util");
|
||||||
|
const { OriginalSource, RawSource } = require("webpack-sources");
|
||||||
const Module = require("./Module");
|
const Module = require("./Module");
|
||||||
const OriginalSource = require("webpack-sources").OriginalSource;
|
|
||||||
const RawSource = require("webpack-sources").RawSource;
|
|
||||||
const AsyncDependenciesBlock = require("./AsyncDependenciesBlock");
|
const AsyncDependenciesBlock = require("./AsyncDependenciesBlock");
|
||||||
const Template = require("./Template");
|
const Template = require("./Template");
|
||||||
|
|
||||||
|
@ -20,7 +19,7 @@ class ContextModule extends Module {
|
||||||
let resource;
|
let resource;
|
||||||
let resourceQuery;
|
let resourceQuery;
|
||||||
const queryIdx = options.resource.indexOf("?");
|
const queryIdx = options.resource.indexOf("?");
|
||||||
if(queryIdx >= 0) {
|
if (queryIdx >= 0) {
|
||||||
resource = options.resource.substr(0, queryIdx);
|
resource = options.resource.substr(0, queryIdx);
|
||||||
resourceQuery = options.resource.substr(queryIdx);
|
resourceQuery = options.resource.substr(queryIdx);
|
||||||
} else {
|
} else {
|
||||||
|
@ -36,13 +35,13 @@ class ContextModule extends Module {
|
||||||
resource: resource,
|
resource: resource,
|
||||||
resourceQuery: resourceQuery
|
resourceQuery: resourceQuery
|
||||||
});
|
});
|
||||||
if(options.resolveOptions !== undefined)
|
if (options.resolveOptions !== undefined)
|
||||||
this.resolveOptions = options.resolveOptions;
|
this.resolveOptions = options.resolveOptions;
|
||||||
|
|
||||||
// Info from Build
|
// Info from Build
|
||||||
this._contextDependencies = new Set([this.context]);
|
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");
|
throw new Error("options.mode is a required option");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,77 +52,66 @@ class ContextModule extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
contextify(context, request) {
|
contextify(context, request) {
|
||||||
return request.split("!").map(subrequest => {
|
return request
|
||||||
let rp = path.relative(context, subrequest);
|
.split("!")
|
||||||
if(path.sep === "\\")
|
.map(subrequest => {
|
||||||
rp = rp.replace(/\\/g, "/");
|
let rp = path.relative(context, subrequest);
|
||||||
if(rp.indexOf("../") !== 0)
|
if (path.sep === "\\") rp = rp.replace(/\\/g, "/");
|
||||||
rp = "./" + rp;
|
if (rp.indexOf("../") !== 0) rp = "./" + rp;
|
||||||
return rp;
|
return rp;
|
||||||
}).join("!");
|
})
|
||||||
|
.join("!");
|
||||||
}
|
}
|
||||||
|
|
||||||
identifier() {
|
identifier() {
|
||||||
let identifier = this.context;
|
let identifier = this.context;
|
||||||
if(this.options.resourceQuery)
|
if (this.options.resourceQuery)
|
||||||
identifier += ` ${this.options.resourceQuery}`;
|
identifier += ` ${this.options.resourceQuery}`;
|
||||||
if(this.options.mode)
|
if (this.options.mode) identifier += ` ${this.options.mode}`;
|
||||||
identifier += ` ${this.options.mode}`;
|
if (!this.options.recursive) identifier += " nonrecursive";
|
||||||
if(!this.options.recursive)
|
if (this.options.addon) identifier += ` ${this.options.addon}`;
|
||||||
identifier += " nonrecursive";
|
if (this.options.regExp) identifier += ` ${this.options.regExp}`;
|
||||||
if(this.options.addon)
|
if (this.options.include) identifier += ` include: ${this.options.include}`;
|
||||||
identifier += ` ${this.options.addon}`;
|
if (this.options.exclude) identifier += ` exclude: ${this.options.exclude}`;
|
||||||
if(this.options.regExp)
|
if (this.options.namespaceObject === "strict")
|
||||||
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.namespaceObject === "strict")
|
|
||||||
identifier += " strict namespace object";
|
identifier += " strict namespace object";
|
||||||
else if(this.options.namespaceObject)
|
else if (this.options.namespaceObject) identifier += " namespace object";
|
||||||
identifier += " namespace object";
|
|
||||||
|
|
||||||
return identifier;
|
return identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
readableIdentifier(requestShortener) {
|
readableIdentifier(requestShortener) {
|
||||||
let identifier = requestShortener.shorten(this.context);
|
let identifier = requestShortener.shorten(this.context);
|
||||||
if(this.options.resourceQuery)
|
if (this.options.resourceQuery)
|
||||||
identifier += ` ${this.options.resourceQuery}`;
|
identifier += ` ${this.options.resourceQuery}`;
|
||||||
if(this.options.mode)
|
if (this.options.mode) identifier += ` ${this.options.mode}`;
|
||||||
identifier += ` ${this.options.mode}`;
|
if (!this.options.recursive) identifier += " nonrecursive";
|
||||||
if(!this.options.recursive)
|
if (this.options.addon)
|
||||||
identifier += " nonrecursive";
|
|
||||||
if(this.options.addon)
|
|
||||||
identifier += ` ${requestShortener.shorten(this.options.addon)}`;
|
identifier += ` ${requestShortener.shorten(this.options.addon)}`;
|
||||||
if(this.options.regExp)
|
if (this.options.regExp)
|
||||||
identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`;
|
identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`;
|
||||||
if(this.options.include)
|
if (this.options.include)
|
||||||
identifier += ` include: ${this.prettyRegExp(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 + "")}`;
|
identifier += ` exclude: ${this.prettyRegExp(this.options.exclude + "")}`;
|
||||||
if(this.options.namespaceObject === "strict")
|
if (this.options.namespaceObject === "strict")
|
||||||
identifier += " strict namespace object";
|
identifier += " strict namespace object";
|
||||||
else if(this.options.namespaceObject)
|
else if (this.options.namespaceObject) identifier += " namespace object";
|
||||||
identifier += " namespace object";
|
|
||||||
|
|
||||||
return identifier;
|
return identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
libIdent(options) {
|
libIdent(options) {
|
||||||
let identifier = this.contextify(options.context, this.context);
|
let identifier = this.contextify(options.context, this.context);
|
||||||
if(this.options.mode)
|
if (this.options.mode) identifier += ` ${this.options.mode}`;
|
||||||
identifier += ` ${this.options.mode}`;
|
if (this.options.recursive) identifier += " recursive";
|
||||||
if(this.options.recursive)
|
if (this.options.addon)
|
||||||
identifier += " recursive";
|
|
||||||
if(this.options.addon)
|
|
||||||
identifier += ` ${this.contextify(options.context, 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 + "")}`;
|
identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`;
|
||||||
if(this.options.include)
|
if (this.options.include)
|
||||||
identifier += ` include: ${this.prettyRegExp(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 + "")}`;
|
identifier += ` exclude: ${this.prettyRegExp(this.options.exclude + "")}`;
|
||||||
|
|
||||||
return identifier;
|
return identifier;
|
||||||
|
@ -131,7 +119,7 @@ class ContextModule extends Module {
|
||||||
|
|
||||||
needRebuild(fileTimestamps, contextTimestamps) {
|
needRebuild(fileTimestamps, contextTimestamps) {
|
||||||
const ts = contextTimestamps.get(this.context);
|
const ts = contextTimestamps.get(this.context);
|
||||||
if(!ts) {
|
if (!ts) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,65 +134,74 @@ class ContextModule extends Module {
|
||||||
contextDependencies: this._contextDependencies
|
contextDependencies: this._contextDependencies
|
||||||
};
|
};
|
||||||
this.resolveDependencies(fs, this.options, (err, dependencies) => {
|
this.resolveDependencies(fs, this.options, (err, dependencies) => {
|
||||||
if(err) return callback(err);
|
if (err) return callback(err);
|
||||||
|
|
||||||
// abort if something failed
|
// abort if something failed
|
||||||
// this will create an empty context
|
// this will create an empty context
|
||||||
if(!dependencies) {
|
if (!dependencies) {
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// enhance dependencies with meta info
|
// enhance dependencies with meta info
|
||||||
for(const dep of dependencies) {
|
for (const dep of dependencies) {
|
||||||
dep.loc = dep.userRequest;
|
dep.loc = dep.userRequest;
|
||||||
dep.request = this.options.addon + dep.request;
|
dep.request = this.options.addon + dep.request;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.options.mode === "sync" || this.options.mode === "eager") {
|
if (this.options.mode === "sync" || this.options.mode === "eager") {
|
||||||
|
|
||||||
// if we have an sync or eager context
|
// if we have an sync or eager context
|
||||||
// just add all dependencies and continue
|
// just add all dependencies and continue
|
||||||
this.dependencies = dependencies;
|
this.dependencies = dependencies;
|
||||||
|
} else if (this.options.mode === "lazy-once") {
|
||||||
} else if(this.options.mode === "lazy-once") {
|
|
||||||
|
|
||||||
// for the lazy-once mode create a new async dependency block
|
// for the lazy-once mode create a new async dependency block
|
||||||
// and add that block to this context
|
// and add that block to this context
|
||||||
if(dependencies.length > 0) {
|
if (dependencies.length > 0) {
|
||||||
const block = new AsyncDependenciesBlock(this.options.chunkName, this);
|
const block = new AsyncDependenciesBlock(
|
||||||
for(const dep of dependencies) {
|
this.options.chunkName,
|
||||||
|
this
|
||||||
|
);
|
||||||
|
for (const dep of dependencies) {
|
||||||
block.addDependency(dep);
|
block.addDependency(dep);
|
||||||
}
|
}
|
||||||
this.addBlock(block);
|
this.addBlock(block);
|
||||||
}
|
}
|
||||||
|
} else if (
|
||||||
} else if(this.options.mode === "weak" || this.options.mode === "async-weak") {
|
this.options.mode === "weak" ||
|
||||||
|
this.options.mode === "async-weak"
|
||||||
|
) {
|
||||||
// we mark all dependencies as weak
|
// we mark all dependencies as weak
|
||||||
for(const dep of dependencies) {
|
for (const dep of dependencies) {
|
||||||
dep.weak = true;
|
dep.weak = true;
|
||||||
}
|
}
|
||||||
this.dependencies = dependencies;
|
this.dependencies = dependencies;
|
||||||
|
} else if (this.options.mode === "lazy") {
|
||||||
} else if(this.options.mode === "lazy") {
|
|
||||||
// if we are lazy create a new async dependency block per dependency
|
// if we are lazy create a new async dependency block per dependency
|
||||||
// and add all blocks to this context
|
// and add all blocks to this context
|
||||||
let index = 0;
|
let index = 0;
|
||||||
for(const dep of dependencies) {
|
for (const dep of dependencies) {
|
||||||
let chunkName = this.options.chunkName;
|
let chunkName = this.options.chunkName;
|
||||||
if(chunkName) {
|
if (chunkName) {
|
||||||
if(!/\[(index|request)\]/.test(chunkName))
|
if (!/\[(index|request)\]/.test(chunkName)) chunkName += "[index]";
|
||||||
chunkName += "[index]";
|
|
||||||
chunkName = chunkName.replace(/\[index\]/g, index++);
|
chunkName = chunkName.replace(/\[index\]/g, index++);
|
||||||
chunkName = chunkName.replace(/\[request\]/g, Template.toPath(dep.userRequest));
|
chunkName = chunkName.replace(
|
||||||
|
/\[request\]/g,
|
||||||
|
Template.toPath(dep.userRequest)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const block = new AsyncDependenciesBlock(chunkName, dep.module, dep.loc, dep.userRequest);
|
const block = new AsyncDependenciesBlock(
|
||||||
|
chunkName,
|
||||||
|
dep.module,
|
||||||
|
dep.loc,
|
||||||
|
dep.userRequest
|
||||||
|
);
|
||||||
block.addDependency(dep);
|
block.addDependency(dep);
|
||||||
this.addBlock(block);
|
this.addBlock(block);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
callback(new Error(`Unsupported mode "${this.options.mode}" in context`));
|
callback(
|
||||||
|
new Error(`Unsupported mode "${this.options.mode}" in context`)
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
callback();
|
callback();
|
||||||
|
@ -218,18 +215,19 @@ class ContextModule extends Module {
|
||||||
return dependencies
|
return dependencies
|
||||||
.filter(dependency => dependency.module)
|
.filter(dependency => dependency.module)
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
if(a.userRequest === b.userRequest) {
|
if (a.userRequest === b.userRequest) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return a.userRequest < b.userRequest ? -1 : 1;
|
return a.userRequest < b.userRequest ? -1 : 1;
|
||||||
}).reduce((map, dep) => {
|
})
|
||||||
|
.reduce((map, dep) => {
|
||||||
map[dep.userRequest] = dep.module.id;
|
map[dep.userRequest] = dep.module.id;
|
||||||
return map;
|
return map;
|
||||||
}, Object.create(null));
|
}, Object.create(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
getFakeMap(dependencies) {
|
getFakeMap(dependencies) {
|
||||||
if(!this.options.namespaceObject) return 1;
|
if (!this.options.namespaceObject) return 1;
|
||||||
// if we filter first we get a new array
|
// if we filter first we get a new array
|
||||||
// therefor we dont need to create a clone of dependencies explicitly
|
// therefor we dont need to create a clone of dependencies explicitly
|
||||||
// therefore the order of this is !important!
|
// therefore the order of this is !important!
|
||||||
|
@ -240,43 +238,52 @@ class ContextModule extends Module {
|
||||||
.filter(dependency => dependency.module)
|
.filter(dependency => dependency.module)
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
return b.module.id - a.module.id;
|
return b.module.id - a.module.id;
|
||||||
}).reduce((map, dep) => {
|
})
|
||||||
const exportsType = dep.module.buildMeta && dep.module.buildMeta.exportsType;
|
.reduce((map, dep) => {
|
||||||
if(!exportsType) hasNonHarmony = true;
|
const exportsType =
|
||||||
if(exportsType === "namespace") hasNamespace = true;
|
dep.module.buildMeta && dep.module.buildMeta.exportsType;
|
||||||
if(exportsType === "named") hasNamed = true;
|
if (!exportsType) hasNonHarmony = true;
|
||||||
map[dep.module.id] = {
|
if (exportsType === "namespace") hasNamespace = true;
|
||||||
namespace: 1,
|
if (exportsType === "named") hasNamed = true;
|
||||||
named: 2
|
map[dep.module.id] =
|
||||||
}[exportsType] || 0;
|
{
|
||||||
|
namespace: 1,
|
||||||
|
named: 2
|
||||||
|
}[exportsType] || 0;
|
||||||
return map;
|
return map;
|
||||||
}, Object.create(null));
|
}, Object.create(null));
|
||||||
if(!hasNamespace && hasNonHarmony && !hasNamed) return 0;
|
if (!hasNamespace && hasNonHarmony && !hasNamed) return 0;
|
||||||
if(hasNamespace && !hasNonHarmony && !hasNamed) return 1;
|
if (hasNamespace && !hasNonHarmony && !hasNamed) return 1;
|
||||||
if(!hasNamespace && !hasNonHarmony && hasNamed) return 2;
|
if (!hasNamespace && !hasNonHarmony && hasNamed) return 2;
|
||||||
if(!hasNamespace && !hasNonHarmony && !hasNamed) return 1;
|
if (!hasNamespace && !hasNonHarmony && !hasNamed) return 1;
|
||||||
return fakeMap;
|
return fakeMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFakeMapInitStatement(fakeMap) {
|
getFakeMapInitStatement(fakeMap) {
|
||||||
return typeof fakeMap === "object" ? `var fakeMap = ${JSON.stringify(fakeMap, null, "\t")};` : "";
|
return typeof fakeMap === "object"
|
||||||
|
? `var fakeMap = ${JSON.stringify(fakeMap, null, "\t")};`
|
||||||
|
: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
getReturn(type) {
|
getReturn(type) {
|
||||||
if(type === 1) return "module";
|
if (type === 1) return "module";
|
||||||
if(type === 2) return "Object.assign({/* fake namespace object */}, module, { \"default\": module })";
|
if (type === 2)
|
||||||
if(type === 0) {
|
return 'Object.assign({/* fake namespace object */}, typeof module === "object" && module, { "default": module })';
|
||||||
if(this.options.namespaceObject === "strict") {
|
if (type === 0) {
|
||||||
return "/* fake namespace object */ { \"default\": module }";
|
if (this.options.namespaceObject === "strict") {
|
||||||
|
return '/* fake namespace object */ { "default": module }';
|
||||||
} else {
|
} else {
|
||||||
return "(typeof module === \"object\" && module && module.__esModule ? module : /* fake namespace object */ { \"default\": module })";
|
return '(typeof module === "object" && module && module.__esModule ? module : Object.assign({/* fake namespace object */}, typeof module === "object" && module, { "default": module }))';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getReturnModuleObjectSource(fakeMap, fakeMapDataExpression = "fakeMap[id]") {
|
getReturnModuleObjectSource(fakeMap, fakeMapDataExpression = "fakeMap[id]") {
|
||||||
if(typeof fakeMap === "number") return `return ${this.getReturn(fakeMap)};`;
|
if (typeof fakeMap === "number")
|
||||||
return `return ${fakeMapDataExpression} === 1 ? ${this.getReturn(1)} : ${fakeMapDataExpression} ? ${this.getReturn(2)} : ${this.getReturn(0)};`;
|
return `return ${this.getReturn(fakeMap)};`;
|
||||||
|
return `return ${fakeMapDataExpression} === 1 ? ${this.getReturn(1)} : ${
|
||||||
|
fakeMapDataExpression
|
||||||
|
} ? ${this.getReturn(2)} : ${this.getReturn(0)};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSyncSource(dependencies, id) {
|
getSyncSource(dependencies, id) {
|
||||||
|
@ -365,7 +372,7 @@ function webpackAsyncContext(req) {
|
||||||
}
|
}
|
||||||
function webpackAsyncContextResolve(req) {
|
function webpackAsyncContextResolve(req) {
|
||||||
// Here Promise.resolve().then() is used instead of new Promise() to prevent
|
// Here Promise.resolve().then() is used instead of new Promise() to prevent
|
||||||
// uncatched exception popping up in devtools
|
// uncaught exception popping up in devtools
|
||||||
return Promise.resolve().then(function() {
|
return Promise.resolve().then(function() {
|
||||||
var id = map[req];
|
var id = map[req];
|
||||||
if(!(id + 1)) { // check for number or string
|
if(!(id + 1)) { // check for number or string
|
||||||
|
@ -387,12 +394,13 @@ module.exports = webpackAsyncContext;`;
|
||||||
getEagerSource(dependencies, id) {
|
getEagerSource(dependencies, id) {
|
||||||
const map = this.getUserRequestMap(dependencies);
|
const map = this.getUserRequestMap(dependencies);
|
||||||
const fakeMap = this.getFakeMap(dependencies);
|
const fakeMap = this.getFakeMap(dependencies);
|
||||||
const thenFunction = fakeMap !== 1 ?
|
const thenFunction =
|
||||||
`function(id) {
|
fakeMap !== 1
|
||||||
|
? `function(id) {
|
||||||
var module = __webpack_require__(id);
|
var module = __webpack_require__(id);
|
||||||
${this.getReturnModuleObjectSource(fakeMap)}
|
${this.getReturnModuleObjectSource(fakeMap)}
|
||||||
}` :
|
}`
|
||||||
"__webpack_require__";
|
: "__webpack_require__";
|
||||||
return `var map = ${JSON.stringify(map, null, "\t")};
|
return `var map = ${JSON.stringify(map, null, "\t")};
|
||||||
${this.getFakeMapInitStatement(fakeMap)}
|
${this.getFakeMapInitStatement(fakeMap)}
|
||||||
|
|
||||||
|
@ -401,7 +409,7 @@ function webpackAsyncContext(req) {
|
||||||
}
|
}
|
||||||
function webpackAsyncContextResolve(req) {
|
function webpackAsyncContextResolve(req) {
|
||||||
// Here Promise.resolve().then() is used instead of new Promise() to prevent
|
// Here Promise.resolve().then() is used instead of new Promise() to prevent
|
||||||
// uncatched exception popping up in devtools
|
// uncaught exception popping up in devtools
|
||||||
return Promise.resolve().then(function() {
|
return Promise.resolve().then(function() {
|
||||||
var id = map[req];
|
var id = map[req];
|
||||||
if(!(id + 1)) { // check for number or string
|
if(!(id + 1)) { // check for number or string
|
||||||
|
@ -427,12 +435,13 @@ module.exports = webpackAsyncContext;`;
|
||||||
});
|
});
|
||||||
const map = this.getUserRequestMap(dependencies);
|
const map = this.getUserRequestMap(dependencies);
|
||||||
const fakeMap = this.getFakeMap(dependencies);
|
const fakeMap = this.getFakeMap(dependencies);
|
||||||
const thenFunction = fakeMap !== 1 ?
|
const thenFunction =
|
||||||
`function(id) {
|
fakeMap !== 1
|
||||||
|
? `function(id) {
|
||||||
var module = __webpack_require__(id);
|
var module = __webpack_require__(id);
|
||||||
${this.getReturnModuleObjectSource(fakeMap)};
|
${this.getReturnModuleObjectSource(fakeMap)};
|
||||||
}` :
|
}`
|
||||||
"__webpack_require__";
|
: "__webpack_require__";
|
||||||
|
|
||||||
return `var map = ${JSON.stringify(map, null, "\t")};
|
return `var map = ${JSON.stringify(map, null, "\t")};
|
||||||
${this.getFakeMapInitStatement(fakeMap)}
|
${this.getFakeMapInitStatement(fakeMap)}
|
||||||
|
@ -464,32 +473,41 @@ module.exports = webpackAsyncContext;`;
|
||||||
const fakeMap = this.getFakeMap(blocks.map(b => b.dependencies[0]));
|
const fakeMap = this.getFakeMap(blocks.map(b => b.dependencies[0]));
|
||||||
const map = blocks
|
const map = blocks
|
||||||
.filter(block => block.dependencies[0].module)
|
.filter(block => block.dependencies[0].module)
|
||||||
.map((block) => ({
|
.map(block => ({
|
||||||
dependency: block.dependencies[0],
|
dependency: block.dependencies[0],
|
||||||
block: block,
|
block: block,
|
||||||
userRequest: block.dependencies[0].userRequest
|
userRequest: block.dependencies[0].userRequest
|
||||||
})).sort((a, b) => {
|
}))
|
||||||
if(a.userRequest === b.userRequest) return 0;
|
.sort((a, b) => {
|
||||||
|
if (a.userRequest === b.userRequest) return 0;
|
||||||
return a.userRequest < b.userRequest ? -1 : 1;
|
return a.userRequest < b.userRequest ? -1 : 1;
|
||||||
}).reduce((map, item) => {
|
})
|
||||||
const chunks = item.block.chunkGroup && item.block.chunkGroup.chunks || [];
|
.reduce((map, item) => {
|
||||||
if(chunks.length !== 1) {
|
const chunks =
|
||||||
|
(item.block.chunkGroup && item.block.chunkGroup.chunks) || [];
|
||||||
|
if (chunks.length !== 1) {
|
||||||
hasMultipleOrNoChunks = true;
|
hasMultipleOrNoChunks = true;
|
||||||
}
|
}
|
||||||
const arrayStart = [item.dependency.module.id];
|
const arrayStart = [item.dependency.module.id];
|
||||||
if(typeof fakeMap === "object")
|
if (typeof fakeMap === "object")
|
||||||
arrayStart.push(fakeMap[item.dependency.module.id]);
|
arrayStart.push(fakeMap[item.dependency.module.id]);
|
||||||
map[item.userRequest] = arrayStart
|
map[item.userRequest] = arrayStart.concat(
|
||||||
.concat(chunks.map(chunk => chunk.id));
|
chunks.map(chunk => chunk.id)
|
||||||
|
);
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}, Object.create(null));
|
}, Object.create(null));
|
||||||
|
|
||||||
const chunksStartPosition = typeof fakeMap === "object" ? 2 : 1;
|
const chunksStartPosition = typeof fakeMap === "object" ? 2 : 1;
|
||||||
const requestPrefix = hasMultipleOrNoChunks ?
|
const requestPrefix = hasMultipleOrNoChunks
|
||||||
`Promise.all(ids.slice(${chunksStartPosition}).map(__webpack_require__.e))` :
|
? `Promise.all(ids.slice(${
|
||||||
`__webpack_require__.e(ids[${chunksStartPosition}])`;
|
chunksStartPosition
|
||||||
const returnModuleObject = this.getReturnModuleObjectSource(fakeMap, "ids[1]");
|
}).map(__webpack_require__.e))`
|
||||||
|
: `__webpack_require__.e(ids[${chunksStartPosition}])`;
|
||||||
|
const returnModuleObject = this.getReturnModuleObjectSource(
|
||||||
|
fakeMap,
|
||||||
|
"ids[1]"
|
||||||
|
);
|
||||||
|
|
||||||
return `var map = ${JSON.stringify(map, null, "\t")};
|
return `var map = ${JSON.stringify(map, null, "\t")};
|
||||||
function webpackAsyncContext(req) {
|
function webpackAsyncContext(req) {
|
||||||
|
@ -528,7 +546,7 @@ webpackEmptyContext.id = ${JSON.stringify(id)};`;
|
||||||
getSourceForEmptyAsyncContext(id) {
|
getSourceForEmptyAsyncContext(id) {
|
||||||
return `function webpackEmptyAsyncContext(req) {
|
return `function webpackEmptyAsyncContext(req) {
|
||||||
// Here Promise.resolve().then() is used instead of new Promise() to prevent
|
// Here Promise.resolve().then() is used instead of new Promise() to prevent
|
||||||
// uncatched exception popping up in devtools
|
// uncaught exception popping up in devtools
|
||||||
return Promise.resolve().then(function() {
|
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';
|
e.code = 'MODULE_NOT_FOUND';
|
||||||
|
@ -542,44 +560,49 @@ webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSourceString(asyncMode, runtimeTemplate) {
|
getSourceString(asyncMode, runtimeTemplate) {
|
||||||
if(asyncMode === "lazy") {
|
if (asyncMode === "lazy") {
|
||||||
if(this.blocks && this.blocks.length > 0) {
|
if (this.blocks && this.blocks.length > 0) {
|
||||||
return this.getLazySource(this.blocks, this.id);
|
return this.getLazySource(this.blocks, this.id);
|
||||||
}
|
}
|
||||||
return this.getSourceForEmptyAsyncContext(this.id);
|
return this.getSourceForEmptyAsyncContext(this.id);
|
||||||
}
|
}
|
||||||
if(asyncMode === "eager") {
|
if (asyncMode === "eager") {
|
||||||
if(this.dependencies && this.dependencies.length > 0) {
|
if (this.dependencies && this.dependencies.length > 0) {
|
||||||
return this.getEagerSource(this.dependencies, this.id);
|
return this.getEagerSource(this.dependencies, this.id);
|
||||||
}
|
}
|
||||||
return this.getSourceForEmptyAsyncContext(this.id);
|
return this.getSourceForEmptyAsyncContext(this.id);
|
||||||
}
|
}
|
||||||
if(asyncMode === "lazy-once") {
|
if (asyncMode === "lazy-once") {
|
||||||
const block = this.blocks[0];
|
const block = this.blocks[0];
|
||||||
if(block) {
|
if (block) {
|
||||||
return this.getLazyOnceSource(block, block.dependencies, this.id, runtimeTemplate);
|
return this.getLazyOnceSource(
|
||||||
|
block,
|
||||||
|
block.dependencies,
|
||||||
|
this.id,
|
||||||
|
runtimeTemplate
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return this.getSourceForEmptyAsyncContext(this.id);
|
return this.getSourceForEmptyAsyncContext(this.id);
|
||||||
}
|
}
|
||||||
if(asyncMode === "async-weak") {
|
if (asyncMode === "async-weak") {
|
||||||
if(this.dependencies && this.dependencies.length > 0) {
|
if (this.dependencies && this.dependencies.length > 0) {
|
||||||
return this.getAsyncWeakSource(this.dependencies, this.id);
|
return this.getAsyncWeakSource(this.dependencies, this.id);
|
||||||
}
|
}
|
||||||
return this.getSourceForEmptyAsyncContext(this.id);
|
return this.getSourceForEmptyAsyncContext(this.id);
|
||||||
}
|
}
|
||||||
if(asyncMode === "weak") {
|
if (asyncMode === "weak") {
|
||||||
if(this.dependencies && this.dependencies.length > 0) {
|
if (this.dependencies && this.dependencies.length > 0) {
|
||||||
return this.getWeakSyncSource(this.dependencies, this.id);
|
return this.getWeakSyncSource(this.dependencies, this.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(this.dependencies && this.dependencies.length > 0) {
|
if (this.dependencies && this.dependencies.length > 0) {
|
||||||
return this.getSyncSource(this.dependencies, this.id);
|
return this.getSyncSource(this.dependencies, this.id);
|
||||||
}
|
}
|
||||||
return this.getSourceForEmptyContext(this.id);
|
return this.getSourceForEmptyContext(this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSource(sourceString) {
|
getSource(sourceString) {
|
||||||
if(this.useSourceMap) {
|
if (this.useSourceMap) {
|
||||||
return new OriginalSource(sourceString, this.identifier());
|
return new OriginalSource(sourceString, this.identifier());
|
||||||
}
|
}
|
||||||
return new RawSource(sourceString);
|
return new RawSource(sourceString);
|
||||||
|
@ -596,8 +619,10 @@ webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`;
|
||||||
const initialSize = 160;
|
const initialSize = 160;
|
||||||
|
|
||||||
// if we dont have dependencies we stop here.
|
// if we dont have dependencies we stop here.
|
||||||
return this.dependencies
|
return this.dependencies.reduce(
|
||||||
.reduce((size, dependency) => size + 5 + dependency.userRequest.length, initialSize);
|
(size, dependency) => size + 5 + dependency.userRequest.length,
|
||||||
|
initialSize
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,11 @@
|
||||||
const asyncLib = require("neo-async");
|
const asyncLib = require("neo-async");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
const Tapable = require("tapable").Tapable;
|
const {
|
||||||
const AsyncSeriesWaterfallHook = require("tapable").AsyncSeriesWaterfallHook;
|
Tapable,
|
||||||
const SyncWaterfallHook = require("tapable").SyncWaterfallHook;
|
AsyncSeriesWaterfallHook,
|
||||||
|
SyncWaterfallHook
|
||||||
|
} = require("tapable");
|
||||||
const ContextModule = require("./ContextModule");
|
const ContextModule = require("./ContextModule");
|
||||||
const ContextElementDependency = require("./dependencies/ContextElementDependency");
|
const ContextElementDependency = require("./dependencies/ContextElementDependency");
|
||||||
|
|
||||||
|
@ -25,7 +27,7 @@ module.exports = class ContextModuleFactory extends Tapable {
|
||||||
alternatives: new AsyncSeriesWaterfallHook(["modules"])
|
alternatives: new AsyncSeriesWaterfallHook(["modules"])
|
||||||
};
|
};
|
||||||
this._pluginCompat.tap("ContextModuleFactory", options => {
|
this._pluginCompat.tap("ContextModuleFactory", options => {
|
||||||
switch(options.name) {
|
switch (options.name) {
|
||||||
case "before-resolve":
|
case "before-resolve":
|
||||||
case "after-resolve":
|
case "after-resolve":
|
||||||
case "alternatives":
|
case "alternatives":
|
||||||
|
@ -41,72 +43,120 @@ module.exports = class ContextModuleFactory extends Tapable {
|
||||||
const dependencies = data.dependencies;
|
const dependencies = data.dependencies;
|
||||||
const resolveOptions = data.resolveOptions;
|
const resolveOptions = data.resolveOptions;
|
||||||
const dependency = dependencies[0];
|
const dependency = dependencies[0];
|
||||||
this.hooks.beforeResolve.callAsync(Object.assign({
|
this.hooks.beforeResolve.callAsync(
|
||||||
context: context,
|
Object.assign(
|
||||||
dependencies: dependencies,
|
{
|
||||||
resolveOptions
|
context: context,
|
||||||
}, dependency.options), (err, beforeResolveResult) => {
|
dependencies: dependencies,
|
||||||
if(err) return callback(err);
|
resolveOptions
|
||||||
|
|
||||||
// Ignored
|
|
||||||
if(!beforeResolveResult) return callback();
|
|
||||||
|
|
||||||
const context = beforeResolveResult.context;
|
|
||||||
const request = beforeResolveResult.request;
|
|
||||||
const resolveOptions = beforeResolveResult.resolveOptions;
|
|
||||||
|
|
||||||
let loaders, resource, loadersPrefix = "";
|
|
||||||
const idx = request.lastIndexOf("!");
|
|
||||||
if(idx >= 0) {
|
|
||||||
loaders = request.substr(0, idx + 1);
|
|
||||||
let i;
|
|
||||||
for(i = 0; i < loaders.length && loaders[i] === "!"; i++) {
|
|
||||||
loadersPrefix += "!";
|
|
||||||
}
|
|
||||||
loaders = loaders.substr(i).replace(/!+$/, "").replace(/!!+/g, "!");
|
|
||||||
if(loaders === "") loaders = [];
|
|
||||||
else loaders = loaders.split("!");
|
|
||||||
resource = request.substr(idx + 1);
|
|
||||||
} else {
|
|
||||||
loaders = [];
|
|
||||||
resource = request;
|
|
||||||
}
|
|
||||||
|
|
||||||
const contextResolver = this.resolverFactory.get("context", resolveOptions || EMPTY_RESOLVE_OPTIONS);
|
|
||||||
const loaderResolver = this.resolverFactory.get("loader", EMPTY_RESOLVE_OPTIONS);
|
|
||||||
|
|
||||||
asyncLib.parallel([
|
|
||||||
callback => {
|
|
||||||
contextResolver.resolve({}, context, resource, {}, (err, result) => {
|
|
||||||
if(err) return callback(err);
|
|
||||||
callback(null, result);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
callback => {
|
dependency.options
|
||||||
asyncLib.map(loaders, (loader, callback) => {
|
),
|
||||||
loaderResolver.resolve({}, context, loader, {}, (err, result) => {
|
(err, beforeResolveResult) => {
|
||||||
if(err) return callback(err);
|
if (err) return callback(err);
|
||||||
callback(null, result);
|
|
||||||
});
|
// Ignored
|
||||||
}, callback);
|
if (!beforeResolveResult) return callback();
|
||||||
|
|
||||||
|
const context = beforeResolveResult.context;
|
||||||
|
const request = beforeResolveResult.request;
|
||||||
|
const resolveOptions = beforeResolveResult.resolveOptions;
|
||||||
|
|
||||||
|
let loaders,
|
||||||
|
resource,
|
||||||
|
loadersPrefix = "";
|
||||||
|
const idx = request.lastIndexOf("!");
|
||||||
|
if (idx >= 0) {
|
||||||
|
loaders = request.substr(0, idx + 1);
|
||||||
|
let i;
|
||||||
|
for (i = 0; i < loaders.length && loaders[i] === "!"; i++) {
|
||||||
|
loadersPrefix += "!";
|
||||||
|
}
|
||||||
|
loaders = loaders
|
||||||
|
.substr(i)
|
||||||
|
.replace(/!+$/, "")
|
||||||
|
.replace(/!!+/g, "!");
|
||||||
|
if (loaders === "") loaders = [];
|
||||||
|
else loaders = loaders.split("!");
|
||||||
|
resource = request.substr(idx + 1);
|
||||||
|
} else {
|
||||||
|
loaders = [];
|
||||||
|
resource = request;
|
||||||
}
|
}
|
||||||
], (err, result) => {
|
|
||||||
if(err) return callback(err);
|
|
||||||
|
|
||||||
this.hooks.afterResolve.callAsync(Object.assign({
|
const contextResolver = this.resolverFactory.get(
|
||||||
addon: loadersPrefix + result[1].join("!") + (result[1].length > 0 ? "!" : ""),
|
"context",
|
||||||
resource: result[0],
|
resolveOptions || EMPTY_RESOLVE_OPTIONS
|
||||||
resolveDependencies: this.resolveDependencies.bind(this)
|
);
|
||||||
}, beforeResolveResult), (err, result) => {
|
const loaderResolver = this.resolverFactory.get(
|
||||||
if(err) return callback(err);
|
"loader",
|
||||||
|
EMPTY_RESOLVE_OPTIONS
|
||||||
|
);
|
||||||
|
|
||||||
// Ignored
|
asyncLib.parallel(
|
||||||
if(!result) return callback();
|
[
|
||||||
|
callback => {
|
||||||
|
contextResolver.resolve(
|
||||||
|
{},
|
||||||
|
context,
|
||||||
|
resource,
|
||||||
|
{},
|
||||||
|
(err, result) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
callback(null, result);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
callback => {
|
||||||
|
asyncLib.map(
|
||||||
|
loaders,
|
||||||
|
(loader, callback) => {
|
||||||
|
loaderResolver.resolve(
|
||||||
|
{},
|
||||||
|
context,
|
||||||
|
loader,
|
||||||
|
{},
|
||||||
|
(err, result) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
callback(null, result);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
callback
|
||||||
|
);
|
||||||
|
}
|
||||||
|
],
|
||||||
|
(err, result) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
|
||||||
return callback(null, new ContextModule(result.resolveDependencies, result));
|
this.hooks.afterResolve.callAsync(
|
||||||
});
|
Object.assign(
|
||||||
});
|
{
|
||||||
});
|
addon:
|
||||||
|
loadersPrefix +
|
||||||
|
result[1].join("!") +
|
||||||
|
(result[1].length > 0 ? "!" : ""),
|
||||||
|
resource: result[0],
|
||||||
|
resolveDependencies: this.resolveDependencies.bind(this)
|
||||||
|
},
|
||||||
|
beforeResolveResult
|
||||||
|
),
|
||||||
|
(err, result) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
|
||||||
|
// Ignored
|
||||||
|
if (!result) return callback();
|
||||||
|
|
||||||
|
return callback(
|
||||||
|
null,
|
||||||
|
new ContextModule(result.resolveDependencies, result)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveDependencies(fs, options, callback) {
|
resolveDependencies(fs, options, callback) {
|
||||||
|
@ -117,63 +167,76 @@ module.exports = class ContextModuleFactory extends Tapable {
|
||||||
let regExp = options.regExp;
|
let regExp = options.regExp;
|
||||||
let include = options.include;
|
let include = options.include;
|
||||||
let exclude = options.exclude;
|
let exclude = options.exclude;
|
||||||
if(!regExp || !resource)
|
if (!regExp || !resource) return callback(null, []);
|
||||||
return callback(null, []);
|
|
||||||
|
|
||||||
const addDirectory = (directory, callback) => {
|
const addDirectory = (directory, callback) => {
|
||||||
fs.readdir(directory, (err, files) => {
|
fs.readdir(directory, (err, files) => {
|
||||||
if(err) return callback(err);
|
if (err) return callback(err);
|
||||||
files = cmf.hooks.contextModuleFiles.call(files);
|
files = cmf.hooks.contextModuleFiles.call(files);
|
||||||
if(!files || files.length === 0) return callback(null, []);
|
if (!files || files.length === 0) return callback(null, []);
|
||||||
asyncLib.map(files.filter(p => p.indexOf(".") !== 0), (seqment, callback) => {
|
asyncLib.map(
|
||||||
|
files.filter(p => p.indexOf(".") !== 0),
|
||||||
|
(segment, callback) => {
|
||||||
|
const subResource = path.join(directory, segment);
|
||||||
|
|
||||||
const subResource = path.join(directory, seqment);
|
if (!exclude || !subResource.match(exclude)) {
|
||||||
|
fs.stat(subResource, (err, stat) => {
|
||||||
if(!exclude || !subResource.match(exclude)) {
|
if (err) {
|
||||||
fs.stat(subResource, (err, stat) => {
|
if (err.code === "ENOENT") {
|
||||||
if(err) {
|
// ENOENT is ok here because the file may have been deleted between
|
||||||
if(err.code === "ENOENT") {
|
// the readdir and stat calls.
|
||||||
// ENOENT is ok here because the file may have been deleted between
|
return callback();
|
||||||
// the readdir and stat calls.
|
} else {
|
||||||
return callback();
|
return callback(err);
|
||||||
} else {
|
}
|
||||||
return callback(err);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(stat.isDirectory()) {
|
if (stat.isDirectory()) {
|
||||||
|
if (!recursive) return callback();
|
||||||
|
addDirectory.call(this, subResource, callback);
|
||||||
|
} else if (
|
||||||
|
stat.isFile() &&
|
||||||
|
(!include || subResource.match(include))
|
||||||
|
) {
|
||||||
|
const obj = {
|
||||||
|
context: resource,
|
||||||
|
request:
|
||||||
|
"." +
|
||||||
|
subResource.substr(resource.length).replace(/\\/g, "/")
|
||||||
|
};
|
||||||
|
|
||||||
if(!recursive) return callback();
|
this.hooks.alternatives.callAsync(
|
||||||
addDirectory.call(this, subResource, callback);
|
[obj],
|
||||||
|
(err, alternatives) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
alternatives = alternatives
|
||||||
|
.filter(obj => regExp.test(obj.request))
|
||||||
|
.map(obj => {
|
||||||
|
const dep = new ContextElementDependency(
|
||||||
|
obj.request + resourceQuery,
|
||||||
|
obj.request
|
||||||
|
);
|
||||||
|
dep.optional = true;
|
||||||
|
return dep;
|
||||||
|
});
|
||||||
|
callback(null, alternatives);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else callback();
|
||||||
|
});
|
||||||
|
} else callback();
|
||||||
|
},
|
||||||
|
(err, result) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
|
||||||
} else if(stat.isFile() && (!include || subResource.match(include))) {
|
if (!result) return callback(null, []);
|
||||||
|
|
||||||
const obj = {
|
callback(
|
||||||
context: resource,
|
null,
|
||||||
request: "." + subResource.substr(resource.length).replace(/\\/g, "/")
|
result.filter(Boolean).reduce((a, i) => a.concat(i), [])
|
||||||
};
|
);
|
||||||
|
}
|
||||||
this.hooks.alternatives.callAsync([obj], (err, alternatives) => {
|
);
|
||||||
if(err) return callback(err);
|
|
||||||
alternatives = alternatives.filter(obj => regExp.test(obj.request)).map(obj => {
|
|
||||||
const dep = new ContextElementDependency(obj.request + resourceQuery, obj.request);
|
|
||||||
dep.optional = true;
|
|
||||||
return dep;
|
|
||||||
});
|
|
||||||
callback(null, alternatives);
|
|
||||||
});
|
|
||||||
|
|
||||||
} else callback();
|
|
||||||
|
|
||||||
});
|
|
||||||
} else callback();
|
|
||||||
}, (err, result) => {
|
|
||||||
if(err) return callback(err);
|
|
||||||
|
|
||||||
if(!result) return callback(null, []);
|
|
||||||
|
|
||||||
callback(null, result.filter(Boolean).reduce((a, i) => a.concat(i), []));
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -8,26 +8,37 @@ const path = require("path");
|
||||||
const ContextElementDependency = require("./dependencies/ContextElementDependency");
|
const ContextElementDependency = require("./dependencies/ContextElementDependency");
|
||||||
|
|
||||||
class ContextReplacementPlugin {
|
class ContextReplacementPlugin {
|
||||||
constructor(resourceRegExp, newContentResource, newContentRecursive, newContentRegExp) {
|
constructor(
|
||||||
|
resourceRegExp,
|
||||||
|
newContentResource,
|
||||||
|
newContentRecursive,
|
||||||
|
newContentRegExp
|
||||||
|
) {
|
||||||
this.resourceRegExp = resourceRegExp;
|
this.resourceRegExp = resourceRegExp;
|
||||||
|
|
||||||
if(typeof newContentResource === "function") {
|
if (typeof newContentResource === "function") {
|
||||||
this.newContentCallback = newContentResource;
|
this.newContentCallback = newContentResource;
|
||||||
} else if(typeof newContentResource === "string" && typeof newContentRecursive === "object") {
|
} else if (
|
||||||
|
typeof newContentResource === "string" &&
|
||||||
|
typeof newContentRecursive === "object"
|
||||||
|
) {
|
||||||
this.newContentResource = newContentResource;
|
this.newContentResource = newContentResource;
|
||||||
this.newContentCreateContextMap = (fs, callback) => {
|
this.newContentCreateContextMap = (fs, callback) => {
|
||||||
callback(null, newContentRecursive);
|
callback(null, newContentRecursive);
|
||||||
};
|
};
|
||||||
} else if(typeof newContentResource === "string" && typeof newContentRecursive === "function") {
|
} else if (
|
||||||
|
typeof newContentResource === "string" &&
|
||||||
|
typeof newContentRecursive === "function"
|
||||||
|
) {
|
||||||
this.newContentResource = newContentResource;
|
this.newContentResource = newContentResource;
|
||||||
this.newContentCreateContextMap = newContentRecursive;
|
this.newContentCreateContextMap = newContentRecursive;
|
||||||
} else {
|
} else {
|
||||||
if(typeof newContentResource !== "string") {
|
if (typeof newContentResource !== "string") {
|
||||||
newContentRegExp = newContentRecursive;
|
newContentRegExp = newContentRecursive;
|
||||||
newContentRecursive = newContentResource;
|
newContentRecursive = newContentResource;
|
||||||
newContentResource = undefined;
|
newContentResource = undefined;
|
||||||
}
|
}
|
||||||
if(typeof newContentRecursive !== "boolean") {
|
if (typeof newContentRecursive !== "boolean") {
|
||||||
newContentRegExp = newContentRecursive;
|
newContentRegExp = newContentRecursive;
|
||||||
newContentRecursive = undefined;
|
newContentRecursive = undefined;
|
||||||
}
|
}
|
||||||
|
@ -45,48 +56,48 @@ class ContextReplacementPlugin {
|
||||||
const newContentRegExp = this.newContentRegExp;
|
const newContentRegExp = this.newContentRegExp;
|
||||||
const newContentCreateContextMap = this.newContentCreateContextMap;
|
const newContentCreateContextMap = this.newContentCreateContextMap;
|
||||||
|
|
||||||
compiler.hooks.contextModuleFactory.tap("ContextReplacementPlugin", (cmf) => {
|
compiler.hooks.contextModuleFactory.tap("ContextReplacementPlugin", cmf => {
|
||||||
cmf.hooks.beforeResolve.tap("ContextReplacementPlugin", (result) => {
|
cmf.hooks.beforeResolve.tap("ContextReplacementPlugin", result => {
|
||||||
if(!result) return;
|
if (!result) return;
|
||||||
if(resourceRegExp.test(result.request)) {
|
if (resourceRegExp.test(result.request)) {
|
||||||
if(typeof newContentResource !== "undefined")
|
if (typeof newContentResource !== "undefined")
|
||||||
result.request = newContentResource;
|
result.request = newContentResource;
|
||||||
if(typeof newContentRecursive !== "undefined")
|
if (typeof newContentRecursive !== "undefined")
|
||||||
result.recursive = newContentRecursive;
|
result.recursive = newContentRecursive;
|
||||||
if(typeof newContentRegExp !== "undefined")
|
if (typeof newContentRegExp !== "undefined")
|
||||||
result.regExp = newContentRegExp;
|
result.regExp = newContentRegExp;
|
||||||
if(typeof newContentCallback === "function") {
|
if (typeof newContentCallback === "function") {
|
||||||
newContentCallback(result);
|
newContentCallback(result);
|
||||||
} else {
|
} else {
|
||||||
for(const d of result.dependencies) {
|
for (const d of result.dependencies) {
|
||||||
if(d.critical)
|
if (d.critical) d.critical = false;
|
||||||
d.critical = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
cmf.hooks.afterResolve.tap("ContextReplacementPlugin", (result) => {
|
cmf.hooks.afterResolve.tap("ContextReplacementPlugin", result => {
|
||||||
if(!result) return;
|
if (!result) return;
|
||||||
if(resourceRegExp.test(result.resource)) {
|
if (resourceRegExp.test(result.resource)) {
|
||||||
if(typeof newContentResource !== "undefined")
|
if (typeof newContentResource !== "undefined")
|
||||||
result.resource = path.resolve(result.resource, newContentResource);
|
result.resource = path.resolve(result.resource, newContentResource);
|
||||||
if(typeof newContentRecursive !== "undefined")
|
if (typeof newContentRecursive !== "undefined")
|
||||||
result.recursive = newContentRecursive;
|
result.recursive = newContentRecursive;
|
||||||
if(typeof newContentRegExp !== "undefined")
|
if (typeof newContentRegExp !== "undefined")
|
||||||
result.regExp = newContentRegExp;
|
result.regExp = newContentRegExp;
|
||||||
if(typeof newContentCreateContextMap === "function")
|
if (typeof newContentCreateContextMap === "function")
|
||||||
result.resolveDependencies = createResolveDependenciesFromContextMap(newContentCreateContextMap);
|
result.resolveDependencies = createResolveDependenciesFromContextMap(
|
||||||
if(typeof newContentCallback === "function") {
|
newContentCreateContextMap
|
||||||
|
);
|
||||||
|
if (typeof newContentCallback === "function") {
|
||||||
const origResource = result.resource;
|
const origResource = result.resource;
|
||||||
newContentCallback(result);
|
newContentCallback(result);
|
||||||
if(result.resource !== origResource) {
|
if (result.resource !== origResource) {
|
||||||
result.resource = path.resolve(origResource, result.resource);
|
result.resource = path.resolve(origResource, result.resource);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(const d of result.dependencies) {
|
for (const d of result.dependencies) {
|
||||||
if(d.critical)
|
if (d.critical) d.critical = false;
|
||||||
d.critical = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,12 +107,15 @@ class ContextReplacementPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const createResolveDependenciesFromContextMap = (createContextMap) => {
|
const createResolveDependenciesFromContextMap = createContextMap => {
|
||||||
const resolveDependenciesFromContextMap = (fs, options, callback) => {
|
const resolveDependenciesFromContextMap = (fs, options, callback) => {
|
||||||
createContextMap(fs, (err, map) => {
|
createContextMap(fs, (err, map) => {
|
||||||
if(err) return callback(err);
|
if (err) return callback(err);
|
||||||
const dependencies = Object.keys(map).map((key) => {
|
const dependencies = Object.keys(map).map(key => {
|
||||||
return new ContextElementDependency(map[key] + options.resourceQuery, key);
|
return new ContextElementDependency(
|
||||||
|
map[key] + options.resourceQuery,
|
||||||
|
key
|
||||||
|
);
|
||||||
});
|
});
|
||||||
callback(null, dependencies);
|
callback(null, dependencies);
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,18 +10,25 @@ const ParserHelpers = require("./ParserHelpers");
|
||||||
const NullFactory = require("./NullFactory");
|
const NullFactory = require("./NullFactory");
|
||||||
|
|
||||||
const stringifyObj = obj => {
|
const stringifyObj = obj => {
|
||||||
return "Object({" + Object.keys(obj).map((key) => {
|
return (
|
||||||
const code = obj[key];
|
"Object({" +
|
||||||
return JSON.stringify(key) + ":" + toCode(code);
|
Object.keys(obj)
|
||||||
}).join(",") + "})";
|
.map(key => {
|
||||||
|
const code = obj[key];
|
||||||
|
return JSON.stringify(key) + ":" + toCode(code);
|
||||||
|
})
|
||||||
|
.join(",") +
|
||||||
|
"})"
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const toCode = code => {
|
const toCode = code => {
|
||||||
if(code === null) return "null";
|
if (code === null) return "null";
|
||||||
else if(code === undefined) return "undefined";
|
else if (code === undefined) return "undefined";
|
||||||
else if(code instanceof RegExp && code.toString) return code.toString();
|
else if (code instanceof RegExp && code.toString) return code.toString();
|
||||||
else if(typeof code === "function" && code.toString) return "(" + code.toString() + ")";
|
else if (typeof code === "function" && code.toString)
|
||||||
else if(typeof code === "object") return stringifyObj(code);
|
return "(" + code.toString() + ")";
|
||||||
|
else if (typeof code === "object") return stringifyObj(code);
|
||||||
else return code + "";
|
else return code + "";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,100 +39,159 @@ class DefinePlugin {
|
||||||
|
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
const definitions = this.definitions;
|
const definitions = this.definitions;
|
||||||
compiler.hooks.compilation.tap("DefinePlugin", (compilation, {
|
compiler.hooks.compilation.tap(
|
||||||
normalModuleFactory
|
"DefinePlugin",
|
||||||
}) => {
|
(compilation, { normalModuleFactory }) => {
|
||||||
compilation.dependencyFactories.set(ConstDependency, new NullFactory());
|
compilation.dependencyFactories.set(ConstDependency, new NullFactory());
|
||||||
compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template());
|
compilation.dependencyTemplates.set(
|
||||||
|
ConstDependency,
|
||||||
|
new ConstDependency.Template()
|
||||||
|
);
|
||||||
|
|
||||||
const handler = (parser) => {
|
const handler = parser => {
|
||||||
const walkDefinitions = (definitions, prefix) => {
|
const walkDefinitions = (definitions, prefix) => {
|
||||||
Object.keys(definitions).forEach((key) => {
|
Object.keys(definitions).forEach(key => {
|
||||||
const code = definitions[key];
|
const code = definitions[key];
|
||||||
if(code && typeof code === "object" && !(code instanceof RegExp)) {
|
if (
|
||||||
walkDefinitions(code, prefix + key + ".");
|
code &&
|
||||||
applyObjectDefine(prefix + key, code);
|
typeof code === "object" &&
|
||||||
return;
|
!(code instanceof RegExp)
|
||||||
|
) {
|
||||||
|
walkDefinitions(code, prefix + key + ".");
|
||||||
|
applyObjectDefine(prefix + key, code);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
applyDefineKey(prefix, key);
|
||||||
|
applyDefine(prefix + key, code);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const applyDefineKey = (prefix, key) => {
|
||||||
|
const splittedKey = key.split(".");
|
||||||
|
splittedKey.slice(1).forEach((_, i) => {
|
||||||
|
const fullKey = prefix + splittedKey.slice(0, i + 1).join(".");
|
||||||
|
parser.hooks.canRename
|
||||||
|
.for(fullKey)
|
||||||
|
.tap("DefinePlugin", ParserHelpers.approve);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const applyDefine = (key, code) => {
|
||||||
|
const isTypeof = /^typeof\s+/.test(key);
|
||||||
|
if (isTypeof) key = key.replace(/^typeof\s+/, "");
|
||||||
|
let recurse = false;
|
||||||
|
let recurseTypeof = false;
|
||||||
|
code = toCode(code);
|
||||||
|
if (!isTypeof) {
|
||||||
|
parser.hooks.canRename
|
||||||
|
.for(key)
|
||||||
|
.tap("DefinePlugin", ParserHelpers.approve);
|
||||||
|
parser.hooks.evaluateIdentifier
|
||||||
|
.for(key)
|
||||||
|
.tap("DefinePlugin", expr => {
|
||||||
|
/**
|
||||||
|
* this is needed in case there is a recursion in the DefinePlugin
|
||||||
|
* to prevent an endless recursion
|
||||||
|
* e.g.: new DefinePlugin({
|
||||||
|
* "a": "b",
|
||||||
|
* "b": "a"
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
if (recurse) return;
|
||||||
|
recurse = true;
|
||||||
|
const res = parser.evaluate(code);
|
||||||
|
recurse = false;
|
||||||
|
res.setRange(expr.range);
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
parser.hooks.expression
|
||||||
|
.for(key)
|
||||||
|
.tap(
|
||||||
|
"DefinePlugin",
|
||||||
|
/__webpack_require__/.test(code)
|
||||||
|
? ParserHelpers.toConstantDependencyWithWebpackRequire(
|
||||||
|
parser,
|
||||||
|
code
|
||||||
|
)
|
||||||
|
: ParserHelpers.toConstantDependency(parser, code)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
applyDefineKey(prefix, key);
|
const typeofCode = isTypeof ? code : "typeof (" + code + ")";
|
||||||
applyDefine(prefix + key, code);
|
parser.hooks.evaluateTypeof.for(key).tap("DefinePlugin", expr => {
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const applyDefineKey = (prefix, key) => {
|
|
||||||
const splittedKey = key.split(".");
|
|
||||||
splittedKey.slice(1).forEach((_, i) => {
|
|
||||||
const fullKey = prefix + splittedKey.slice(0, i + 1).join(".");
|
|
||||||
parser.hooks.canRename.for(fullKey).tap("DefinePlugin", ParserHelpers.approve);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const applyDefine = (key, code) => {
|
|
||||||
const isTypeof = /^typeof\s+/.test(key);
|
|
||||||
if(isTypeof) key = key.replace(/^typeof\s+/, "");
|
|
||||||
let recurse = false;
|
|
||||||
let recurseTypeof = false;
|
|
||||||
code = toCode(code);
|
|
||||||
if(!isTypeof) {
|
|
||||||
parser.hooks.canRename.for(key).tap("DefinePlugin", ParserHelpers.approve);
|
|
||||||
parser.hooks.evaluateIdentifier.for(key).tap("DefinePlugin", (expr) => {
|
|
||||||
/**
|
/**
|
||||||
* this is needed in case there is a recursion in the DefinePlugin
|
* this is needed in case there is a recursion in the DefinePlugin
|
||||||
* to prevent an endless recursion
|
* to prevent an endless recursion
|
||||||
* e.g.: new DefinePlugin({
|
* e.g.: new DefinePlugin({
|
||||||
* "a": "b",
|
* "typeof a": "typeof b",
|
||||||
* "b": "a"
|
* "typeof b": "typeof a"
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
if(recurse) return;
|
if (recurseTypeof) return;
|
||||||
recurse = true;
|
recurseTypeof = true;
|
||||||
const res = parser.evaluate(code);
|
const res = parser.evaluate(typeofCode);
|
||||||
recurse = false;
|
recurseTypeof = false;
|
||||||
res.setRange(expr.range);
|
res.setRange(expr.range);
|
||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
parser.hooks.expression.for(key).tap("DefinePlugin", /__webpack_require__/.test(code) ? ParserHelpers.toConstantDependencyWithWebpackRequire(parser, code) : ParserHelpers.toConstantDependency(parser, code));
|
parser.hooks.typeof.for(key).tap("DefinePlugin", expr => {
|
||||||
}
|
const res = parser.evaluate(typeofCode);
|
||||||
const typeofCode = isTypeof ? code : "typeof (" + code + ")";
|
if (!res.isString()) return;
|
||||||
parser.hooks.evaluateTypeof.for(key).tap("DefinePlugin", (expr) => {
|
return ParserHelpers.toConstantDependency(
|
||||||
/**
|
parser,
|
||||||
* this is needed in case there is a recursion in the DefinePlugin
|
JSON.stringify(res.string)
|
||||||
* to prevent an endless recursion
|
).bind(parser)(expr);
|
||||||
* e.g.: new DefinePlugin({
|
});
|
||||||
* "typeof a": "tyepof b",
|
};
|
||||||
* "typeof b": "typeof a"
|
|
||||||
* });
|
const applyObjectDefine = (key, obj) => {
|
||||||
*/
|
const code = stringifyObj(obj);
|
||||||
if(recurseTypeof) return;
|
parser.hooks.canRename
|
||||||
recurseTypeof = true;
|
.for(key)
|
||||||
const res = parser.evaluate(typeofCode);
|
.tap("DefinePlugin", ParserHelpers.approve);
|
||||||
recurseTypeof = false;
|
parser.hooks.evaluateIdentifier
|
||||||
res.setRange(expr.range);
|
.for(key)
|
||||||
return res;
|
.tap("DefinePlugin", expr =>
|
||||||
});
|
new BasicEvaluatedExpression().setTruthy().setRange(expr.range)
|
||||||
parser.hooks.typeof.for(key).tap("DefinePlugin", (expr) => {
|
);
|
||||||
const res = parser.evaluate(typeofCode);
|
parser.hooks.evaluateTypeof
|
||||||
if(!res.isString()) return;
|
.for(key)
|
||||||
return ParserHelpers.toConstantDependency(parser, JSON.stringify(res.string)).bind(parser)(expr);
|
.tap("DefinePlugin", ParserHelpers.evaluateToString("object"));
|
||||||
});
|
parser.hooks.expression
|
||||||
|
.for(key)
|
||||||
|
.tap(
|
||||||
|
"DefinePlugin",
|
||||||
|
/__webpack_require__/.test(code)
|
||||||
|
? ParserHelpers.toConstantDependencyWithWebpackRequire(
|
||||||
|
parser,
|
||||||
|
code
|
||||||
|
)
|
||||||
|
: ParserHelpers.toConstantDependency(parser, code)
|
||||||
|
);
|
||||||
|
parser.hooks.typeof
|
||||||
|
.for(key)
|
||||||
|
.tap(
|
||||||
|
"DefinePlugin",
|
||||||
|
ParserHelpers.toConstantDependency(
|
||||||
|
parser,
|
||||||
|
JSON.stringify("object")
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
walkDefinitions(definitions, "");
|
||||||
};
|
};
|
||||||
|
|
||||||
const applyObjectDefine = (key, obj) => {
|
normalModuleFactory.hooks.parser
|
||||||
const code = stringifyObj(obj);
|
.for("javascript/auto")
|
||||||
parser.hooks.canRename.for(key).tap("DefinePlugin", ParserHelpers.approve);
|
.tap("DefinePlugin", handler);
|
||||||
parser.hooks.evaluateIdentifier.for(key).tap("DefinePlugin", (expr) => new BasicEvaluatedExpression().setTruthy().setRange(expr.range));
|
normalModuleFactory.hooks.parser
|
||||||
parser.hooks.evaluateTypeof.for(key).tap("DefinePlugin", ParserHelpers.evaluateToString("object"));
|
.for("javascript/dynamic")
|
||||||
parser.hooks.expression.for(key).tap("DefinePlugin", /__webpack_require__/.test(code) ? ParserHelpers.toConstantDependencyWithWebpackRequire(parser, code) : ParserHelpers.toConstantDependency(parser, code));
|
.tap("DefinePlugin", handler);
|
||||||
parser.hooks.typeof.for(key).tap("DefinePlugin", ParserHelpers.toConstantDependency(parser, JSON.stringify("object")));
|
normalModuleFactory.hooks.parser
|
||||||
};
|
.for("javascript/esm")
|
||||||
|
.tap("DefinePlugin", handler);
|
||||||
walkDefinitions(definitions, "");
|
}
|
||||||
};
|
);
|
||||||
|
|
||||||
normalModuleFactory.hooks.parser.for("javascript/auto").tap("DefinePlugin", handler);
|
|
||||||
normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("DefinePlugin", handler);
|
|
||||||
normalModuleFactory.hooks.parser.for("javascript/esm").tap("DefinePlugin", handler);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
module.exports = DefinePlugin;
|
module.exports = DefinePlugin;
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
*/
|
*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const { OriginalSource, RawSource } = require("webpack-sources");
|
||||||
|
|
||||||
const Module = require("./Module");
|
const Module = require("./Module");
|
||||||
const OriginalSource = require("webpack-sources").OriginalSource;
|
|
||||||
const RawSource = require("webpack-sources").RawSource;
|
|
||||||
const WebpackMissingModule = require("./dependencies/WebpackMissingModule");
|
const WebpackMissingModule = require("./dependencies/WebpackMissingModule");
|
||||||
const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency");
|
const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency");
|
||||||
const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency");
|
const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency");
|
||||||
|
@ -25,11 +25,15 @@ class DelegatedModule extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
libIdent(options) {
|
libIdent(options) {
|
||||||
return typeof this.originalRequest === "string" ? this.originalRequest : this.originalRequest.libIdent(options);
|
return typeof this.originalRequest === "string"
|
||||||
|
? this.originalRequest
|
||||||
|
: this.originalRequest.libIdent(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
identifier() {
|
identifier() {
|
||||||
return `delegated ${JSON.stringify(this.request)} from ${this.sourceRequest}`;
|
return `delegated ${JSON.stringify(this.request)} from ${
|
||||||
|
this.sourceRequest
|
||||||
|
}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
readableIdentifier() {
|
readableIdentifier() {
|
||||||
|
@ -45,7 +49,9 @@ class DelegatedModule extends Module {
|
||||||
this.buildMeta = Object.assign({}, this.delegateData.buildMeta);
|
this.buildMeta = Object.assign({}, this.delegateData.buildMeta);
|
||||||
this.buildInfo = {};
|
this.buildInfo = {};
|
||||||
this.addDependency(new DelegatedSourceDependency(this.sourceRequest));
|
this.addDependency(new DelegatedSourceDependency(this.sourceRequest));
|
||||||
this.addDependency(new DelegatedExportsDependency(this, this.delegateData.exports || true));
|
this.addDependency(
|
||||||
|
new DelegatedExportsDependency(this, this.delegateData.exports || true)
|
||||||
|
);
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +60,7 @@ class DelegatedModule extends Module {
|
||||||
const sourceModule = dep.module;
|
const sourceModule = dep.module;
|
||||||
let str;
|
let str;
|
||||||
|
|
||||||
if(!sourceModule) {
|
if (!sourceModule) {
|
||||||
str = WebpackMissingModule.moduleCode(this.sourceRequest);
|
str = WebpackMissingModule.moduleCode(this.sourceRequest);
|
||||||
} else {
|
} else {
|
||||||
str = `module.exports = (${runtime.moduleExports({
|
str = `module.exports = (${runtime.moduleExports({
|
||||||
|
@ -62,7 +68,7 @@ class DelegatedModule extends Module {
|
||||||
request: dep.request
|
request: dep.request
|
||||||
})})`;
|
})})`;
|
||||||
|
|
||||||
switch(this.type) {
|
switch (this.type) {
|
||||||
case "require":
|
case "require":
|
||||||
str += `(${JSON.stringify(this.request)})`;
|
str += `(${JSON.stringify(this.request)})`;
|
||||||
break;
|
break;
|
||||||
|
@ -74,7 +80,7 @@ class DelegatedModule extends Module {
|
||||||
str += ";";
|
str += ";";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.useSourceMap) {
|
if (this.useSourceMap) {
|
||||||
return new OriginalSource(str, this.identifier());
|
return new OriginalSource(str, this.identifier());
|
||||||
} else {
|
} else {
|
||||||
return new RawSource(str);
|
return new RawSource(str);
|
||||||
|
|
|
@ -20,39 +20,69 @@ class DelegatedModuleFactoryPlugin {
|
||||||
|
|
||||||
apply(normalModuleFactory) {
|
apply(normalModuleFactory) {
|
||||||
const scope = this.options.scope;
|
const scope = this.options.scope;
|
||||||
if(scope) {
|
if (scope) {
|
||||||
normalModuleFactory.hooks.factory.tap("DelegatedModuleFactoryPlugin", factory => (data, callback) => {
|
normalModuleFactory.hooks.factory.tap(
|
||||||
const dependency = data.dependencies[0];
|
"DelegatedModuleFactoryPlugin",
|
||||||
const request = dependency.request;
|
factory => (data, callback) => {
|
||||||
if(request && request.indexOf(scope + "/") === 0) {
|
const dependency = data.dependencies[0];
|
||||||
const innerRequest = "." + request.substr(scope.length);
|
const request = dependency.request;
|
||||||
let resolved;
|
if (request && request.indexOf(scope + "/") === 0) {
|
||||||
if(innerRequest in this.options.content) {
|
const innerRequest = "." + request.substr(scope.length);
|
||||||
resolved = this.options.content[innerRequest];
|
let resolved;
|
||||||
return callback(null, new DelegatedModule(this.options.source, resolved, this.options.type, innerRequest, request));
|
if (innerRequest in this.options.content) {
|
||||||
}
|
resolved = this.options.content[innerRequest];
|
||||||
for(let i = 0; i < this.options.extensions.length; i++) {
|
return callback(
|
||||||
const extension = this.options.extensions[i];
|
null,
|
||||||
const requestPlusExt = innerRequest + extension;
|
new DelegatedModule(
|
||||||
if(requestPlusExt in this.options.content) {
|
this.options.source,
|
||||||
resolved = this.options.content[requestPlusExt];
|
resolved,
|
||||||
return callback(null, new DelegatedModule(this.options.source, resolved, this.options.type, requestPlusExt, request + extension));
|
this.options.type,
|
||||||
|
innerRequest,
|
||||||
|
request
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < this.options.extensions.length; i++) {
|
||||||
|
const extension = this.options.extensions[i];
|
||||||
|
const requestPlusExt = innerRequest + extension;
|
||||||
|
if (requestPlusExt in this.options.content) {
|
||||||
|
resolved = this.options.content[requestPlusExt];
|
||||||
|
return callback(
|
||||||
|
null,
|
||||||
|
new DelegatedModule(
|
||||||
|
this.options.source,
|
||||||
|
resolved,
|
||||||
|
this.options.type,
|
||||||
|
requestPlusExt,
|
||||||
|
request + extension
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return factory(data, callback);
|
||||||
}
|
}
|
||||||
return factory(data, callback);
|
);
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
normalModuleFactory.hooks.module.tap("DelegatedModuleFactoryPlugin", module => {
|
normalModuleFactory.hooks.module.tap(
|
||||||
if(module.libIdent) {
|
"DelegatedModuleFactoryPlugin",
|
||||||
const request = module.libIdent(this.options);
|
module => {
|
||||||
if(request && request in this.options.content) {
|
if (module.libIdent) {
|
||||||
const resolved = this.options.content[request];
|
const request = module.libIdent(this.options);
|
||||||
return new DelegatedModule(this.options.source, resolved, this.options.type, request, module);
|
if (request && request in this.options.content) {
|
||||||
|
const resolved = this.options.content[request];
|
||||||
|
return new DelegatedModule(
|
||||||
|
this.options.source,
|
||||||
|
resolved,
|
||||||
|
this.options.type,
|
||||||
|
request,
|
||||||
|
module
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return module;
|
||||||
}
|
}
|
||||||
return module;
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,16 +16,21 @@ class DelegatedPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compilation.tap("DelegatedPlugin", (compilation, {
|
compiler.hooks.compilation.tap(
|
||||||
normalModuleFactory
|
"DelegatedPlugin",
|
||||||
}) => {
|
(compilation, { normalModuleFactory }) => {
|
||||||
compilation.dependencyFactories.set(DelegatedSourceDependency, normalModuleFactory);
|
compilation.dependencyFactories.set(
|
||||||
compilation.dependencyFactories.set(DelegatedExportsDependency, new NullFactory());
|
DelegatedSourceDependency,
|
||||||
});
|
normalModuleFactory
|
||||||
|
);
|
||||||
|
compilation.dependencyFactories.set(
|
||||||
|
DelegatedExportsDependency,
|
||||||
|
new NullFactory()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
compiler.hooks.compile.tap("DelegatedPlugin", ({
|
compiler.hooks.compile.tap("DelegatedPlugin", ({ normalModuleFactory }) => {
|
||||||
normalModuleFactory
|
|
||||||
}) => {
|
|
||||||
new DelegatedModuleFactoryPlugin(this.options).apply(normalModuleFactory);
|
new DelegatedModuleFactoryPlugin(this.options).apply(normalModuleFactory);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,14 @@ class DependenciesBlock {
|
||||||
}
|
}
|
||||||
|
|
||||||
addVariable(name, expression, dependencies) {
|
addVariable(name, expression, dependencies) {
|
||||||
for(let v of this.variables) {
|
for (let v of this.variables) {
|
||||||
if(v.name === name && v.expression === expression) {
|
if (v.name === name && v.expression === expression) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.variables.push(new DependenciesBlockVariable(name, expression, dependencies));
|
this.variables.push(
|
||||||
|
new DependenciesBlockVariable(name, expression, dependencies)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
addDependency(dependency) {
|
addDependency(dependency) {
|
||||||
|
@ -33,59 +35,47 @@ class DependenciesBlock {
|
||||||
|
|
||||||
removeDependency(dependency) {
|
removeDependency(dependency) {
|
||||||
const idx = this.dependencies.indexOf(dependency);
|
const idx = this.dependencies.indexOf(dependency);
|
||||||
if(idx >= 0)
|
if (idx >= 0) this.dependencies.splice(idx, 1);
|
||||||
this.dependencies.splice(idx, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateHash(hash) {
|
updateHash(hash) {
|
||||||
for(const dep of this.dependencies)
|
for (const dep of this.dependencies) dep.updateHash(hash);
|
||||||
dep.updateHash(hash);
|
for (const block of this.blocks) block.updateHash(hash);
|
||||||
for(const block of this.blocks)
|
for (const variable of this.variables) variable.updateHash(hash);
|
||||||
block.updateHash(hash);
|
|
||||||
for(const variable of this.variables)
|
|
||||||
variable.updateHash(hash);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect() {
|
disconnect() {
|
||||||
for(const dep of this.dependencies)
|
for (const dep of this.dependencies) dep.disconnect();
|
||||||
dep.disconnect();
|
for (const block of this.blocks) block.disconnect();
|
||||||
for(const block of this.blocks)
|
for (const variable of this.variables) variable.disconnect();
|
||||||
block.disconnect();
|
|
||||||
for(const variable of this.variables)
|
|
||||||
variable.disconnect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unseal() {
|
unseal() {
|
||||||
for(const block of this.blocks)
|
for (const block of this.blocks) block.unseal();
|
||||||
block.unseal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasDependencies(filter) {
|
hasDependencies(filter) {
|
||||||
if(filter) {
|
if (filter) {
|
||||||
for(const dep of this.dependencies) {
|
for (const dep of this.dependencies) {
|
||||||
if(filter(dep))
|
if (filter(dep)) return true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(this.dependencies.length > 0) {
|
if (this.dependencies.length > 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const block of this.blocks) {
|
for (const block of this.blocks) {
|
||||||
if(block.hasDependencies(filter))
|
if (block.hasDependencies(filter)) return true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
for(const variable of this.variables) {
|
for (const variable of this.variables) {
|
||||||
if(variable.hasDependencies(filter))
|
if (variable.hasDependencies(filter)) return true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
sortItems() {
|
sortItems() {
|
||||||
for(const block of this.blocks)
|
for (const block of this.blocks) block.sortItems();
|
||||||
block.sortItems();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
*/
|
*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const ReplaceSource = require("webpack-sources").ReplaceSource;
|
const { RawSource, ReplaceSource } = require("webpack-sources");
|
||||||
const RawSource = require("webpack-sources").RawSource;
|
|
||||||
|
|
||||||
class DependenciesBlockVariable {
|
class DependenciesBlockVariable {
|
||||||
constructor(name, expression, dependencies) {
|
constructor(name, expression, dependencies) {
|
||||||
|
@ -17,32 +16,33 @@ class DependenciesBlockVariable {
|
||||||
updateHash(hash) {
|
updateHash(hash) {
|
||||||
hash.update(this.name);
|
hash.update(this.name);
|
||||||
hash.update(this.expression);
|
hash.update(this.expression);
|
||||||
for(const d of this.dependencies) {
|
for (const d of this.dependencies) {
|
||||||
d.updateHash(hash);
|
d.updateHash(hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expressionSource(dependencyTemplates, runtimeTemplate) {
|
expressionSource(dependencyTemplates, runtimeTemplate) {
|
||||||
const source = new ReplaceSource(new RawSource(this.expression));
|
const source = new ReplaceSource(new RawSource(this.expression));
|
||||||
for(const dep of this.dependencies) {
|
for (const dep of this.dependencies) {
|
||||||
const template = dependencyTemplates.get(dep.constructor);
|
const template = dependencyTemplates.get(dep.constructor);
|
||||||
if(!template) throw new Error(`No template for dependency: ${dep.constructor.name}`);
|
if (!template)
|
||||||
|
throw new Error(`No template for dependency: ${dep.constructor.name}`);
|
||||||
template.apply(dep, source, runtimeTemplate, dependencyTemplates);
|
template.apply(dep, source, runtimeTemplate, dependencyTemplates);
|
||||||
}
|
}
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnect() {
|
disconnect() {
|
||||||
for(const d of this.dependencies) {
|
for (const d of this.dependencies) {
|
||||||
d.disconnect();
|
d.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hasDependencies(filter) {
|
hasDependencies(filter) {
|
||||||
if(filter) {
|
if (filter) {
|
||||||
if(this.dependencies.some(filter)) return true;
|
if (this.dependencies.some(filter)) return true;
|
||||||
} else {
|
} else {
|
||||||
if(this.dependencies.length > 0) return true;
|
if (this.dependencies.length > 0) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,11 @@ class Dependency {
|
||||||
|
|
||||||
// Returns the referenced module and export
|
// Returns the referenced module and export
|
||||||
getReference() {
|
getReference() {
|
||||||
if(!this.module) return null;
|
if (!this.module) return null;
|
||||||
return {
|
return {
|
||||||
module: this.module,
|
module: this.module,
|
||||||
weak: this.weak,
|
weak: this.weak,
|
||||||
importedNames: true, // true: full object, false: only sideeffects/no export, array of strings: the exports with this names
|
importedNames: true // true: full object, false: only sideeffects/no export, array of strings: the exports with this names
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,19 +16,34 @@ class DllEntryPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compilation.tap("DllEntryPlugin", (compilation, {
|
compiler.hooks.compilation.tap(
|
||||||
normalModuleFactory
|
"DllEntryPlugin",
|
||||||
}) => {
|
(compilation, { normalModuleFactory }) => {
|
||||||
const dllModuleFactory = new DllModuleFactory();
|
const dllModuleFactory = new DllModuleFactory();
|
||||||
compilation.dependencyFactories.set(DllEntryDependency, dllModuleFactory);
|
compilation.dependencyFactories.set(
|
||||||
compilation.dependencyFactories.set(SingleEntryDependency, normalModuleFactory);
|
DllEntryDependency,
|
||||||
});
|
dllModuleFactory
|
||||||
|
);
|
||||||
|
compilation.dependencyFactories.set(
|
||||||
|
SingleEntryDependency,
|
||||||
|
normalModuleFactory
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
compiler.hooks.make.tapAsync("DllEntryPlugin", (compilation, callback) => {
|
compiler.hooks.make.tapAsync("DllEntryPlugin", (compilation, callback) => {
|
||||||
compilation.addEntry(this.context, new DllEntryDependency(this.entries.map((e, idx) => {
|
compilation.addEntry(
|
||||||
const dep = new SingleEntryDependency(e);
|
this.context,
|
||||||
dep.loc = `${this.name}:${idx}`;
|
new DllEntryDependency(
|
||||||
return dep;
|
this.entries.map((e, idx) => {
|
||||||
}), this.name), this.name, callback);
|
const dep = new SingleEntryDependency(e);
|
||||||
|
dep.loc = `${this.name}:${idx}`;
|
||||||
|
return dep;
|
||||||
|
}),
|
||||||
|
this.name
|
||||||
|
),
|
||||||
|
this.name,
|
||||||
|
callback
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
*/
|
*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const { RawSource } = require("webpack-sources");
|
||||||
const Module = require("./Module");
|
const Module = require("./Module");
|
||||||
const RawSource = require("webpack-sources").RawSource;
|
|
||||||
|
|
||||||
class DllModule extends Module {
|
class DllModule extends Module {
|
||||||
constructor(context, dependencies, name, type) {
|
constructor(context, dependencies, name, type) {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const Tapable = require("tapable").Tapable;
|
const { Tapable } = require("tapable");
|
||||||
const DllModule = require("./DllModule");
|
const DllModule = require("./DllModule");
|
||||||
|
|
||||||
class DllModuleFactory extends Tapable {
|
class DllModuleFactory extends Tapable {
|
||||||
|
@ -14,7 +14,15 @@ class DllModuleFactory extends Tapable {
|
||||||
}
|
}
|
||||||
create(data, callback) {
|
create(data, callback) {
|
||||||
const dependency = data.dependencies[0];
|
const dependency = data.dependencies[0];
|
||||||
callback(null, new DllModule(data.context, dependency.dependencies, dependency.name, dependency.type));
|
callback(
|
||||||
|
null,
|
||||||
|
new DllModule(
|
||||||
|
data.context,
|
||||||
|
dependency.dependencies,
|
||||||
|
dependency.name,
|
||||||
|
dependency.type
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,12 +20,10 @@ class DllPlugin {
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.entryOption.tap("DllPlugin", (context, entry) => {
|
compiler.hooks.entryOption.tap("DllPlugin", (context, entry) => {
|
||||||
const itemToPlugin = (item, name) => {
|
const itemToPlugin = (item, name) => {
|
||||||
if(Array.isArray(item))
|
if (Array.isArray(item)) return new DllEntryPlugin(context, item, name);
|
||||||
return new DllEntryPlugin(context, item, name);
|
else throw new Error("DllPlugin: supply an Array as entry");
|
||||||
else
|
|
||||||
throw new Error("DllPlugin: supply an Array as entry");
|
|
||||||
};
|
};
|
||||||
if(typeof entry === "object" && !Array.isArray(entry)) {
|
if (typeof entry === "object" && !Array.isArray(entry)) {
|
||||||
Object.keys(entry).forEach(name => {
|
Object.keys(entry).forEach(name => {
|
||||||
itemToPlugin(entry[name], name).apply(compiler);
|
itemToPlugin(entry[name], name).apply(compiler);
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,39 +20,54 @@ class DllReferencePlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compilation.tap("DllReferencePlugin", (compilation, {
|
compiler.hooks.compilation.tap(
|
||||||
normalModuleFactory
|
"DllReferencePlugin",
|
||||||
}) => {
|
(compilation, { normalModuleFactory }) => {
|
||||||
compilation.dependencyFactories.set(DelegatedSourceDependency, normalModuleFactory);
|
compilation.dependencyFactories.set(
|
||||||
compilation.dependencyFactories.set(DelegatedExportsDependency, new NullFactory());
|
DelegatedSourceDependency,
|
||||||
});
|
normalModuleFactory
|
||||||
|
);
|
||||||
compiler.hooks.beforeCompile.tapAsync("DllReferencePlugin", (params, callback) => {
|
compilation.dependencyFactories.set(
|
||||||
const manifest = this.options.manifest;
|
DelegatedExportsDependency,
|
||||||
if(typeof manifest === "string") {
|
new NullFactory()
|
||||||
params.compilationDependencies.add(manifest);
|
);
|
||||||
compiler.inputFileSystem.readFile(manifest, (err, result) => {
|
|
||||||
if(err) return callback(err);
|
|
||||||
params["dll reference " + manifest] = JSON.parse(result.toString("utf-8"));
|
|
||||||
return callback();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return callback();
|
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|
||||||
compiler.hooks.compile.tap("DllReferencePlugin", (params) => {
|
compiler.hooks.beforeCompile.tapAsync(
|
||||||
|
"DllReferencePlugin",
|
||||||
|
(params, callback) => {
|
||||||
|
const manifest = this.options.manifest;
|
||||||
|
if (typeof manifest === "string") {
|
||||||
|
params.compilationDependencies.add(manifest);
|
||||||
|
compiler.inputFileSystem.readFile(manifest, (err, result) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
params["dll reference " + manifest] = JSON.parse(
|
||||||
|
result.toString("utf-8")
|
||||||
|
);
|
||||||
|
return callback();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
compiler.hooks.compile.tap("DllReferencePlugin", params => {
|
||||||
let manifest = this.options.manifest;
|
let manifest = this.options.manifest;
|
||||||
if(typeof manifest === "string") {
|
if (typeof manifest === "string") {
|
||||||
manifest = params["dll reference " + manifest];
|
manifest = params["dll reference " + manifest];
|
||||||
}
|
}
|
||||||
const name = this.options.name || manifest.name;
|
const name = this.options.name || manifest.name;
|
||||||
const sourceType = this.options.sourceType || (manifest && manifest.type) || "var";
|
const sourceType =
|
||||||
|
this.options.sourceType || (manifest && manifest.type) || "var";
|
||||||
const externals = {};
|
const externals = {};
|
||||||
const source = "dll-reference " + name;
|
const source = "dll-reference " + name;
|
||||||
externals[source] = name;
|
externals[source] = name;
|
||||||
const normalModuleFactory = params.normalModuleFactory;
|
const normalModuleFactory = params.normalModuleFactory;
|
||||||
new ExternalModuleFactoryPlugin(sourceType, externals).apply(normalModuleFactory);
|
new ExternalModuleFactoryPlugin(sourceType, externals).apply(
|
||||||
|
normalModuleFactory
|
||||||
|
);
|
||||||
new DelegatedModuleFactoryPlugin({
|
new DelegatedModuleFactoryPlugin({
|
||||||
source: source,
|
source: source,
|
||||||
type: this.options.type,
|
type: this.options.type,
|
||||||
|
|
|
@ -17,44 +17,55 @@ class DynamicEntryPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compilation.tap("DynamicEntryPlugin", (compilation, {
|
compiler.hooks.compilation.tap(
|
||||||
normalModuleFactory
|
"DynamicEntryPlugin",
|
||||||
}) => {
|
(compilation, { normalModuleFactory }) => {
|
||||||
const multiModuleFactory = new MultiModuleFactory();
|
const multiModuleFactory = new MultiModuleFactory();
|
||||||
|
|
||||||
compilation.dependencyFactories.set(MultiEntryDependency, multiModuleFactory);
|
compilation.dependencyFactories.set(
|
||||||
compilation.dependencyFactories.set(SingleEntryDependency, normalModuleFactory);
|
MultiEntryDependency,
|
||||||
});
|
multiModuleFactory
|
||||||
|
);
|
||||||
|
compilation.dependencyFactories.set(
|
||||||
|
SingleEntryDependency,
|
||||||
|
normalModuleFactory
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
compiler.hooks.make.tapAsync("DynamicEntryPlugin", (compilation, callback) => {
|
compiler.hooks.make.tapAsync(
|
||||||
const addEntry = (entry, name) => {
|
"DynamicEntryPlugin",
|
||||||
const dep = DynamicEntryPlugin.createDependency(entry, name);
|
(compilation, callback) => {
|
||||||
return new Promise((resolve, reject) => {
|
const addEntry = (entry, name) => {
|
||||||
compilation.addEntry(this.context, dep, name, (err) => {
|
const dep = DynamicEntryPlugin.createDependency(entry, name);
|
||||||
if(err) return reject(err);
|
return new Promise((resolve, reject) => {
|
||||||
resolve();
|
compilation.addEntry(this.context, dep, name, err => {
|
||||||
|
if (err) return reject(err);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
};
|
|
||||||
|
|
||||||
Promise.resolve(this.entry()).then((entry) => {
|
Promise.resolve(this.entry()).then(entry => {
|
||||||
if(typeof entry === "string" || Array.isArray(entry)) {
|
if (typeof entry === "string" || Array.isArray(entry)) {
|
||||||
addEntry(entry, "main").then(() => callback(), callback);
|
addEntry(entry, "main").then(() => callback(), callback);
|
||||||
} else if(typeof entry === "object") {
|
} else if (typeof entry === "object") {
|
||||||
Promise.all(Object.keys(entry).map((name) => {
|
Promise.all(
|
||||||
return addEntry(entry[name], name);
|
Object.keys(entry).map(name => {
|
||||||
})).then(() => callback(), callback);
|
return addEntry(entry[name], name);
|
||||||
}
|
})
|
||||||
});
|
).then(() => callback(), callback);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = DynamicEntryPlugin;
|
module.exports = DynamicEntryPlugin;
|
||||||
|
|
||||||
DynamicEntryPlugin.createDependency = (entry, name) => {
|
DynamicEntryPlugin.createDependency = (entry, name) => {
|
||||||
if(Array.isArray(entry))
|
if (Array.isArray(entry))
|
||||||
return MultiEntryPlugin.createDependency(entry, name);
|
return MultiEntryPlugin.createDependency(entry, name);
|
||||||
else
|
else return SingleEntryPlugin.createDependency(entry, name);
|
||||||
return SingleEntryPlugin.createDependency(entry, name);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,7 @@ const MultiEntryPlugin = require("./MultiEntryPlugin");
|
||||||
const DynamicEntryPlugin = require("./DynamicEntryPlugin");
|
const DynamicEntryPlugin = require("./DynamicEntryPlugin");
|
||||||
|
|
||||||
const itemToPlugin = (context, item, name) => {
|
const itemToPlugin = (context, item, name) => {
|
||||||
if(Array.isArray(item)) {
|
if (Array.isArray(item)) {
|
||||||
return new MultiEntryPlugin(context, item, name);
|
return new MultiEntryPlugin(context, item, name);
|
||||||
}
|
}
|
||||||
return new SingleEntryPlugin(context, item, name);
|
return new SingleEntryPlugin(context, item, name);
|
||||||
|
@ -18,13 +18,13 @@ const itemToPlugin = (context, item, name) => {
|
||||||
module.exports = class EntryOptionPlugin {
|
module.exports = class EntryOptionPlugin {
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.entryOption.tap("EntryOptionPlugin", (context, entry) => {
|
compiler.hooks.entryOption.tap("EntryOptionPlugin", (context, entry) => {
|
||||||
if(typeof entry === "string" || Array.isArray(entry)) {
|
if (typeof entry === "string" || Array.isArray(entry)) {
|
||||||
itemToPlugin(context, entry, "main").apply(compiler);
|
itemToPlugin(context, entry, "main").apply(compiler);
|
||||||
} else if(typeof entry === "object") {
|
} else if (typeof entry === "object") {
|
||||||
for(const name of Object.keys(entry)) {
|
for (const name of Object.keys(entry)) {
|
||||||
itemToPlugin(context, entry[name], name).apply(compiler);
|
itemToPlugin(context, entry[name], name).apply(compiler);
|
||||||
}
|
}
|
||||||
} else if(typeof entry === "function") {
|
} else if (typeof entry === "function") {
|
||||||
new DynamicEntryPlugin(context, entry).apply(compiler);
|
new DynamicEntryPlugin(context, entry).apply(compiler);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -19,8 +19,8 @@ class Entrypoint extends ChunkGroup {
|
||||||
getFiles() {
|
getFiles() {
|
||||||
const files = new Set();
|
const files = new Set();
|
||||||
|
|
||||||
for(const chunk of this.chunks) {
|
for (const chunk of this.chunks) {
|
||||||
for(const file of chunk.files) {
|
for (const file of chunk.files) {
|
||||||
files.add(file);
|
files.add(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,15 +7,16 @@
|
||||||
|
|
||||||
const DefinePlugin = require("./DefinePlugin");
|
const DefinePlugin = require("./DefinePlugin");
|
||||||
|
|
||||||
const needsEnvVarFix = ["8", "9"].indexOf(process.versions.node.split(".")[0]) >= 0 &&
|
const needsEnvVarFix =
|
||||||
|
["8", "9"].indexOf(process.versions.node.split(".")[0]) >= 0 &&
|
||||||
process.platform === "win32";
|
process.platform === "win32";
|
||||||
|
|
||||||
class EnvironmentPlugin {
|
class EnvironmentPlugin {
|
||||||
constructor(...keys) {
|
constructor(...keys) {
|
||||||
if(keys.length === 1 && Array.isArray(keys[0])) {
|
if (keys.length === 1 && Array.isArray(keys[0])) {
|
||||||
this.keys = keys[0];
|
this.keys = keys[0];
|
||||||
this.defaultValues = {};
|
this.defaultValues = {};
|
||||||
} else if(keys.length === 1 && keys[0] && typeof keys[0] === "object") {
|
} else if (keys.length === 1 && keys[0] && typeof keys[0] === "object") {
|
||||||
this.keys = Object.keys(keys[0]);
|
this.keys = Object.keys(keys[0]);
|
||||||
this.defaultValues = keys[0];
|
this.defaultValues = keys[0];
|
||||||
} else {
|
} else {
|
||||||
|
@ -31,16 +32,21 @@ class EnvironmentPlugin {
|
||||||
// affecting Node 8 & 9 by performing an OS-level
|
// affecting Node 8 & 9 by performing an OS-level
|
||||||
// operation that always succeeds before reading
|
// operation that always succeeds before reading
|
||||||
// environment variables:
|
// environment variables:
|
||||||
if(needsEnvVarFix) require("os").cpus();
|
if (needsEnvVarFix) require("os").cpus();
|
||||||
|
|
||||||
const value = process.env[key] !== undefined ? process.env[key] : this.defaultValues[key];
|
const value =
|
||||||
|
process.env[key] !== undefined
|
||||||
|
? process.env[key]
|
||||||
|
: this.defaultValues[key];
|
||||||
|
|
||||||
if(value === undefined) {
|
if (value === undefined) {
|
||||||
compiler.hooks.thisCompilation.tap("EnvironmentPlugin", (compilation) => {
|
compiler.hooks.thisCompilation.tap("EnvironmentPlugin", compilation => {
|
||||||
const error = new Error(
|
const error = new Error(
|
||||||
`EnvironmentPlugin - ${key} environment variable is undefined.\n\n` +
|
`EnvironmentPlugin - ${
|
||||||
"You can pass an object with default values to suppress this warning.\n" +
|
key
|
||||||
"See https://webpack.js.org/plugins/environment-plugin for example."
|
} environment variable is undefined.\n\n` +
|
||||||
|
"You can pass an object with default values to suppress this warning.\n" +
|
||||||
|
"See https://webpack.js.org/plugins/environment-plugin for example."
|
||||||
);
|
);
|
||||||
|
|
||||||
error.name = "EnvVariableNotDefinedError";
|
error.name = "EnvVariableNotDefinedError";
|
||||||
|
@ -48,7 +54,8 @@ class EnvironmentPlugin {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
defs[`process.env.${key}`] = typeof value === "undefined" ? "undefined" : JSON.stringify(value);
|
defs[`process.env.${key}`] =
|
||||||
|
typeof value === "undefined" ? "undefined" : JSON.stringify(value);
|
||||||
|
|
||||||
return defs;
|
return defs;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
|
@ -10,26 +10,33 @@ const webpackOptionsFlag = "WEBPACK_OPTIONS";
|
||||||
|
|
||||||
exports.cutOffByFlag = (stack, flag) => {
|
exports.cutOffByFlag = (stack, flag) => {
|
||||||
stack = stack.split("\n");
|
stack = stack.split("\n");
|
||||||
for(let i = 0; i < stack.length; i++)
|
for (let i = 0; i < stack.length; i++)
|
||||||
if(stack[i].includes(flag))
|
if (stack[i].includes(flag)) stack.length = i;
|
||||||
stack.length = i;
|
|
||||||
return stack.join("\n");
|
return stack.join("\n");
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.cutOffLoaderExecution = (stack) => exports.cutOffByFlag(stack, loaderFlag);
|
exports.cutOffLoaderExecution = stack =>
|
||||||
|
exports.cutOffByFlag(stack, loaderFlag);
|
||||||
|
|
||||||
exports.cutOffWebpackOptinos = (stack) => exports.cutOffByFlag(stack, webpackOptionsFlag);
|
exports.cutOffWebpackOptions = stack =>
|
||||||
|
exports.cutOffByFlag(stack, webpackOptionsFlag);
|
||||||
|
|
||||||
exports.cutOffMultilineMessage = (stack, message) => {
|
exports.cutOffMultilineMessage = (stack, message) => {
|
||||||
stack = stack.split("\n");
|
stack = stack.split("\n");
|
||||||
message = message.split("\n");
|
message = message.split("\n");
|
||||||
|
|
||||||
return stack.reduce((acc, line, idx) => line.includes(message[idx]) ? acc : acc.concat(line), []).join("\n");
|
return stack
|
||||||
|
.reduce(
|
||||||
|
(acc, line, idx) =>
|
||||||
|
line.includes(message[idx]) ? acc : acc.concat(line),
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
.join("\n");
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.cutOffMessage = (stack, message) => {
|
exports.cutOffMessage = (stack, message) => {
|
||||||
const nextLine = stack.indexOf("\n");
|
const nextLine = stack.indexOf("\n");
|
||||||
if(nextLine === -1) {
|
if (nextLine === -1) {
|
||||||
return stack === message ? "" : stack;
|
return stack === message ? "" : stack;
|
||||||
} else {
|
} else {
|
||||||
const firstLine = stack.substr(0, nextLine);
|
const firstLine = stack.substr(0, nextLine);
|
||||||
|
@ -44,7 +51,7 @@ exports.cleanUp = (stack, message) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.cleanUpWebpackOptions = (stack, message) => {
|
exports.cleanUpWebpackOptions = (stack, message) => {
|
||||||
stack = exports.cutOffWebpackOptinos(stack);
|
stack = exports.cutOffWebpackOptions(stack);
|
||||||
stack = exports.cutOffMultilineMessage(stack, message);
|
stack = exports.cutOffMultilineMessage(stack, message);
|
||||||
return stack;
|
return stack;
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,7 @@ class EvalDevToolModulePlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compilation.tap("EvalDevToolModulePlugin", (compilation) => {
|
compiler.hooks.compilation.tap("EvalDevToolModulePlugin", compilation => {
|
||||||
new EvalDevToolModuleTemplatePlugin({
|
new EvalDevToolModuleTemplatePlugin({
|
||||||
sourceUrlComment: this.sourceUrlComment,
|
sourceUrlComment: this.sourceUrlComment,
|
||||||
moduleFilenameTemplate: this.moduleFilenameTemplate,
|
moduleFilenameTemplate: this.moduleFilenameTemplate,
|
||||||
|
|
|
@ -4,31 +4,52 @@
|
||||||
*/
|
*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const RawSource = require("webpack-sources").RawSource;
|
const { RawSource } = require("webpack-sources");
|
||||||
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
|
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
|
||||||
const cache = new WeakMap();
|
const cache = new WeakMap();
|
||||||
|
|
||||||
class EvalDevToolModuleTemplatePlugin {
|
class EvalDevToolModuleTemplatePlugin {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.sourceUrlComment = options.sourceUrlComment || "\n//# sourceURL=[url]";
|
this.sourceUrlComment = options.sourceUrlComment || "\n//# sourceURL=[url]";
|
||||||
this.moduleFilenameTemplate = options.moduleFilenameTemplate || "webpack://[namespace]/[resourcePath]?[loaders]";
|
this.moduleFilenameTemplate =
|
||||||
|
options.moduleFilenameTemplate ||
|
||||||
|
"webpack://[namespace]/[resourcePath]?[loaders]";
|
||||||
this.namespace = options.namespace || "";
|
this.namespace = options.namespace || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(moduleTemplate) {
|
apply(moduleTemplate) {
|
||||||
moduleTemplate.hooks.module.tap("EvalDevToolModuleTemplatePlugin", (source, module) => {
|
moduleTemplate.hooks.module.tap(
|
||||||
const cacheEntry = cache.get(source);
|
"EvalDevToolModuleTemplatePlugin",
|
||||||
if(cacheEntry !== undefined) return cacheEntry;
|
(source, module) => {
|
||||||
const content = source.source();
|
const cacheEntry = cache.get(source);
|
||||||
const str = ModuleFilenameHelpers.createFilename(module, {
|
if (cacheEntry !== undefined) return cacheEntry;
|
||||||
moduleFilenameTemplate: this.moduleFilenameTemplate,
|
const content = source.source();
|
||||||
namespace: this.namespace
|
const str = ModuleFilenameHelpers.createFilename(
|
||||||
}, moduleTemplate.runtimeTemplate.requestShortener);
|
module,
|
||||||
const footer = "\n" + this.sourceUrlComment.replace(/\[url\]/g, encodeURI(str).replace(/%2F/g, "/").replace(/%20/g, "_").replace(/%5E/g, "^").replace(/%5C/g, "\\").replace(/^\//, ""));
|
{
|
||||||
const result = new RawSource(`eval(${JSON.stringify(content + footer)});`);
|
moduleFilenameTemplate: this.moduleFilenameTemplate,
|
||||||
cache.set(source, result);
|
namespace: this.namespace
|
||||||
return result;
|
},
|
||||||
});
|
moduleTemplate.runtimeTemplate.requestShortener
|
||||||
|
);
|
||||||
|
const footer =
|
||||||
|
"\n" +
|
||||||
|
this.sourceUrlComment.replace(
|
||||||
|
/\[url\]/g,
|
||||||
|
encodeURI(str)
|
||||||
|
.replace(/%2F/g, "/")
|
||||||
|
.replace(/%20/g, "_")
|
||||||
|
.replace(/%5E/g, "^")
|
||||||
|
.replace(/%5C/g, "\\")
|
||||||
|
.replace(/^\//, "")
|
||||||
|
);
|
||||||
|
const result = new RawSource(
|
||||||
|
`eval(${JSON.stringify(content + footer)});`
|
||||||
|
);
|
||||||
|
cache.set(source, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
);
|
||||||
moduleTemplate.hooks.hash.tap("EvalDevToolModuleTemplatePlugin", hash => {
|
moduleTemplate.hooks.hash.tap("EvalDevToolModuleTemplatePlugin", hash => {
|
||||||
hash.update("EvalDevToolModuleTemplatePlugin");
|
hash.update("EvalDevToolModuleTemplatePlugin");
|
||||||
hash.update("2");
|
hash.update("2");
|
||||||
|
|
|
@ -4,14 +4,17 @@
|
||||||
*/
|
*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const RawSource = require("webpack-sources").RawSource;
|
const { RawSource } = require("webpack-sources");
|
||||||
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
|
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
|
||||||
|
|
||||||
class EvalSourceMapDevToolModuleTemplatePlugin {
|
class EvalSourceMapDevToolModuleTemplatePlugin {
|
||||||
constructor(compilation, options) {
|
constructor(compilation, options) {
|
||||||
this.compilation = compilation;
|
this.compilation = compilation;
|
||||||
this.sourceMapComment = options.append || "//# sourceURL=[module]\n//# sourceMappingURL=[url]";
|
this.sourceMapComment =
|
||||||
this.moduleFilenameTemplate = options.moduleFilenameTemplate || "webpack://[namespace]/[resource-path]?[hash]";
|
options.append || "//# sourceURL=[module]\n//# sourceMappingURL=[url]";
|
||||||
|
this.moduleFilenameTemplate =
|
||||||
|
options.moduleFilenameTemplate ||
|
||||||
|
"webpack://[namespace]/[resource-path]?[hash]";
|
||||||
this.namespace = options.namespace || "";
|
this.namespace = options.namespace || "";
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
@ -19,61 +22,84 @@ class EvalSourceMapDevToolModuleTemplatePlugin {
|
||||||
apply(moduleTemplate) {
|
apply(moduleTemplate) {
|
||||||
const self = this;
|
const self = this;
|
||||||
const options = this.options;
|
const options = this.options;
|
||||||
const matchModule = ModuleFilenameHelpers.matchObject.bind(ModuleFilenameHelpers, options);
|
const matchModule = ModuleFilenameHelpers.matchObject.bind(
|
||||||
moduleTemplate.hooks.module.tap("EvalSourceMapDevToolModuleTemplatePlugin", (source, module) => {
|
ModuleFilenameHelpers,
|
||||||
if(source.__EvalSourceMapDevToolData)
|
options
|
||||||
|
);
|
||||||
|
moduleTemplate.hooks.module.tap(
|
||||||
|
"EvalSourceMapDevToolModuleTemplatePlugin",
|
||||||
|
(source, module) => {
|
||||||
|
if (source.__EvalSourceMapDevToolData)
|
||||||
|
return source.__EvalSourceMapDevToolData;
|
||||||
|
if (!matchModule(module.resource)) {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sourceMap;
|
||||||
|
let content;
|
||||||
|
if (source.sourceAndMap) {
|
||||||
|
const sourceAndMap = source.sourceAndMap(options);
|
||||||
|
sourceMap = sourceAndMap.map;
|
||||||
|
content = sourceAndMap.source;
|
||||||
|
} else {
|
||||||
|
sourceMap = source.map(options);
|
||||||
|
content = source.source();
|
||||||
|
}
|
||||||
|
if (!sourceMap) {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone (flat) the sourcemap to ensure that the mutations below do not persist.
|
||||||
|
sourceMap = Object.keys(sourceMap).reduce((obj, key) => {
|
||||||
|
obj[key] = sourceMap[key];
|
||||||
|
return obj;
|
||||||
|
}, {});
|
||||||
|
const modules = sourceMap.sources.map(source => {
|
||||||
|
const module = self.compilation.findModule(source);
|
||||||
|
return module || source;
|
||||||
|
});
|
||||||
|
let moduleFilenames = modules.map(module => {
|
||||||
|
return ModuleFilenameHelpers.createFilename(
|
||||||
|
module,
|
||||||
|
{
|
||||||
|
moduleFilenameTemplate: self.moduleFilenameTemplate,
|
||||||
|
namespace: self.namespace
|
||||||
|
},
|
||||||
|
moduleTemplate.runtimeTemplate.requestShortener
|
||||||
|
);
|
||||||
|
});
|
||||||
|
moduleFilenames = ModuleFilenameHelpers.replaceDuplicates(
|
||||||
|
moduleFilenames,
|
||||||
|
(filename, i, n) => {
|
||||||
|
for (let j = 0; j < n; j++) filename += "*";
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
sourceMap.sources = moduleFilenames;
|
||||||
|
sourceMap.sourceRoot = options.sourceRoot || "";
|
||||||
|
sourceMap.file = `${module.id}.js`;
|
||||||
|
|
||||||
|
const footer =
|
||||||
|
self.sourceMapComment.replace(
|
||||||
|
/\[url\]/g,
|
||||||
|
`data:application/json;charset=utf-8;base64,${Buffer.from(
|
||||||
|
JSON.stringify(sourceMap),
|
||||||
|
"utf8"
|
||||||
|
).toString("base64")}`
|
||||||
|
) + `\n//# sourceURL=webpack-internal:///${module.id}\n`; // workaround for chrome bug
|
||||||
|
source.__EvalSourceMapDevToolData = new RawSource(
|
||||||
|
`eval(${JSON.stringify(content + footer)});`
|
||||||
|
);
|
||||||
return source.__EvalSourceMapDevToolData;
|
return source.__EvalSourceMapDevToolData;
|
||||||
if(!matchModule(module.resource)) {
|
|
||||||
return source;
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
let sourceMap;
|
moduleTemplate.hooks.hash.tap(
|
||||||
let content;
|
"EvalSourceMapDevToolModuleTemplatePlugin",
|
||||||
if(source.sourceAndMap) {
|
hash => {
|
||||||
const sourceAndMap = source.sourceAndMap(options);
|
hash.update("eval-source-map");
|
||||||
sourceMap = sourceAndMap.map;
|
hash.update("2");
|
||||||
content = sourceAndMap.source;
|
|
||||||
} else {
|
|
||||||
sourceMap = source.map(options);
|
|
||||||
content = source.source();
|
|
||||||
}
|
}
|
||||||
if(!sourceMap) {
|
);
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clone (flat) the sourcemap to ensure that the mutations below do not persist.
|
|
||||||
sourceMap = Object.keys(sourceMap).reduce((obj, key) => {
|
|
||||||
obj[key] = sourceMap[key];
|
|
||||||
return obj;
|
|
||||||
}, {});
|
|
||||||
const modules = sourceMap.sources.map(source => {
|
|
||||||
const module = self.compilation.findModule(source);
|
|
||||||
return module || source;
|
|
||||||
});
|
|
||||||
let moduleFilenames = modules.map(module => {
|
|
||||||
return ModuleFilenameHelpers.createFilename(module, {
|
|
||||||
moduleFilenameTemplate: self.moduleFilenameTemplate,
|
|
||||||
namespace: self.namespace
|
|
||||||
}, moduleTemplate.runtimeTemplate.requestShortener);
|
|
||||||
});
|
|
||||||
moduleFilenames = ModuleFilenameHelpers.replaceDuplicates(moduleFilenames, (filename, i, n) => {
|
|
||||||
for(let j = 0; j < n; j++)
|
|
||||||
filename += "*";
|
|
||||||
return filename;
|
|
||||||
});
|
|
||||||
sourceMap.sources = moduleFilenames;
|
|
||||||
sourceMap.sourceRoot = options.sourceRoot || "";
|
|
||||||
sourceMap.file = `${module.id}.js`;
|
|
||||||
|
|
||||||
const footer = self.sourceMapComment.replace(/\[url\]/g, `data:application/json;charset=utf-8;base64,${Buffer.from(JSON.stringify(sourceMap), "utf8").toString("base64")}`) +
|
|
||||||
`\n//# sourceURL=webpack-internal:///${module.id}\n`; // workaround for chrome bug
|
|
||||||
source.__EvalSourceMapDevToolData = new RawSource(`eval(${JSON.stringify(content + footer)});`);
|
|
||||||
return source.__EvalSourceMapDevToolData;
|
|
||||||
});
|
|
||||||
moduleTemplate.hooks.hash.tap("EvalSourceMapDevToolModuleTemplatePlugin", hash => {
|
|
||||||
hash.update("eval-source-map");
|
|
||||||
hash.update("2");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
module.exports = EvalSourceMapDevToolModuleTemplatePlugin;
|
module.exports = EvalSourceMapDevToolModuleTemplatePlugin;
|
||||||
|
|
|
@ -9,23 +9,31 @@ const SourceMapDevToolModuleOptionsPlugin = require("./SourceMapDevToolModuleOpt
|
||||||
|
|
||||||
class EvalSourceMapDevToolPlugin {
|
class EvalSourceMapDevToolPlugin {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
if(arguments.length > 1)
|
if (arguments.length > 1)
|
||||||
throw new Error("EvalSourceMapDevToolPlugin only takes one argument (pass an options object)");
|
throw new Error(
|
||||||
if(typeof options === "string") {
|
"EvalSourceMapDevToolPlugin only takes one argument (pass an options object)"
|
||||||
|
);
|
||||||
|
if (typeof options === "string") {
|
||||||
options = {
|
options = {
|
||||||
append: options
|
append: options
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if(!options) options = {};
|
if (!options) options = {};
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
const options = this.options;
|
const options = this.options;
|
||||||
compiler.hooks.compilation.tap("EvalSourceMapDevToolPlugin", (compilation) => {
|
compiler.hooks.compilation.tap(
|
||||||
new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation);
|
"EvalSourceMapDevToolPlugin",
|
||||||
new EvalSourceMapDevToolModuleTemplatePlugin(compilation, options).apply(compilation.moduleTemplates.javascript);
|
compilation => {
|
||||||
});
|
new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation);
|
||||||
|
new EvalSourceMapDevToolModuleTemplatePlugin(
|
||||||
|
compilation,
|
||||||
|
options
|
||||||
|
).apply(compilation.moduleTemplates.javascript);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const ConcatSource = require("webpack-sources").ConcatSource;
|
const { ConcatSource } = require("webpack-sources");
|
||||||
|
|
||||||
const accessorToObjectAccess = accessor => {
|
const accessorToObjectAccess = accessor => {
|
||||||
return accessor.map(a => `[${JSON.stringify(a)}]`).join("");
|
return accessor.map(a => `[${JSON.stringify(a)}]`).join("");
|
||||||
|
@ -16,18 +16,18 @@ class ExportPropertyMainTemplatePlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(compilation) {
|
apply(compilation) {
|
||||||
const {
|
const { mainTemplate, chunkTemplate } = compilation;
|
||||||
mainTemplate,
|
|
||||||
chunkTemplate
|
|
||||||
} = compilation;
|
|
||||||
|
|
||||||
const onRenderWithEntry = (source, chunk, hash) => {
|
const onRenderWithEntry = (source, chunk, hash) => {
|
||||||
const postfix = `${accessorToObjectAccess([].concat(this.property))}`;
|
const postfix = `${accessorToObjectAccess([].concat(this.property))}`;
|
||||||
return new ConcatSource(source, postfix);
|
return new ConcatSource(source, postfix);
|
||||||
};
|
};
|
||||||
|
|
||||||
for(const template of [mainTemplate, chunkTemplate]) {
|
for (const template of [mainTemplate, chunkTemplate]) {
|
||||||
template.hooks.renderWithEntry.tap("ExportPropertyMainTemplatePlugin", onRenderWithEntry);
|
template.hooks.renderWithEntry.tap(
|
||||||
|
"ExportPropertyMainTemplatePlugin",
|
||||||
|
onRenderWithEntry
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
mainTemplate.hooks.hash.tap("ExportPropertyMainTemplatePlugin", hash => {
|
mainTemplate.hooks.hash.tap("ExportPropertyMainTemplatePlugin", hash => {
|
||||||
|
|
|
@ -20,36 +20,64 @@ const REPLACEMENT_TYPES = {
|
||||||
|
|
||||||
class ExtendedAPIPlugin {
|
class ExtendedAPIPlugin {
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compilation.tap("ExtendedAPIPlugin", (compilation, {
|
compiler.hooks.compilation.tap(
|
||||||
normalModuleFactory
|
"ExtendedAPIPlugin",
|
||||||
}) => {
|
(compilation, { normalModuleFactory }) => {
|
||||||
compilation.dependencyFactories.set(ConstDependency, new NullFactory());
|
compilation.dependencyFactories.set(ConstDependency, new NullFactory());
|
||||||
compilation.dependencyTemplates.set(ConstDependency, new ConstDependency.Template());
|
compilation.dependencyTemplates.set(
|
||||||
|
ConstDependency,
|
||||||
|
new ConstDependency.Template()
|
||||||
|
);
|
||||||
|
|
||||||
const mainTemplate = compilation.mainTemplate;
|
const mainTemplate = compilation.mainTemplate;
|
||||||
mainTemplate.hooks.requireExtensions.tap("ExtendedAPIPlugin", (source, chunk, hash) => {
|
mainTemplate.hooks.requireExtensions.tap(
|
||||||
const buf = [source];
|
"ExtendedAPIPlugin",
|
||||||
buf.push("");
|
(source, chunk, hash) => {
|
||||||
buf.push("// __webpack_hash__");
|
const buf = [source];
|
||||||
buf.push(`${mainTemplate.requireFn}.h = ${JSON.stringify(hash)};`);
|
buf.push("");
|
||||||
buf.push("");
|
buf.push("// __webpack_hash__");
|
||||||
buf.push("// __webpack_chunkname__");
|
buf.push(`${mainTemplate.requireFn}.h = ${JSON.stringify(hash)};`);
|
||||||
buf.push(`${mainTemplate.requireFn}.cn = ${JSON.stringify(chunk.name)};`);
|
buf.push("");
|
||||||
return Template.asString(buf);
|
buf.push("// __webpack_chunkname__");
|
||||||
});
|
buf.push(
|
||||||
mainTemplate.hooks.globalHash.tap("ExtendedAPIPlugin", () => true);
|
`${mainTemplate.requireFn}.cn = ${JSON.stringify(chunk.name)};`
|
||||||
|
);
|
||||||
|
return Template.asString(buf);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
mainTemplate.hooks.globalHash.tap("ExtendedAPIPlugin", () => true);
|
||||||
|
|
||||||
const handler = (parser, parserOptions) => {
|
const handler = (parser, parserOptions) => {
|
||||||
Object.keys(REPLACEMENTS).forEach(key => {
|
Object.keys(REPLACEMENTS).forEach(key => {
|
||||||
parser.hooks.expression.for(key).tap("ExtendedAPIPlugin", ParserHelpers.toConstantDependencyWithWebpackRequire(parser, REPLACEMENTS[key]));
|
parser.hooks.expression
|
||||||
parser.hooks.evaluateTypeof.for(key).tap("ExtendedAPIPlugin", ParserHelpers.evaluateToString(REPLACEMENT_TYPES[key]));
|
.for(key)
|
||||||
});
|
.tap(
|
||||||
};
|
"ExtendedAPIPlugin",
|
||||||
|
ParserHelpers.toConstantDependencyWithWebpackRequire(
|
||||||
|
parser,
|
||||||
|
REPLACEMENTS[key]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
parser.hooks.evaluateTypeof
|
||||||
|
.for(key)
|
||||||
|
.tap(
|
||||||
|
"ExtendedAPIPlugin",
|
||||||
|
ParserHelpers.evaluateToString(REPLACEMENT_TYPES[key])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
normalModuleFactory.hooks.parser.for("javascript/auto").tap("ExtendedAPIPlugin", handler);
|
normalModuleFactory.hooks.parser
|
||||||
normalModuleFactory.hooks.parser.for("javascript/dynamic").tap("ExtendedAPIPlugin", handler);
|
.for("javascript/auto")
|
||||||
normalModuleFactory.hooks.parser.for("javascript/esm").tap("ExtendedAPIPlugin", handler);
|
.tap("ExtendedAPIPlugin", handler);
|
||||||
});
|
normalModuleFactory.hooks.parser
|
||||||
|
.for("javascript/dynamic")
|
||||||
|
.tap("ExtendedAPIPlugin", handler);
|
||||||
|
normalModuleFactory.hooks.parser
|
||||||
|
.for("javascript/esm")
|
||||||
|
.tap("ExtendedAPIPlugin", handler);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
Author Tobias Koppers @sokra
|
Author Tobias Koppers @sokra
|
||||||
*/
|
*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const { OriginalSource, RawSource } = require("webpack-sources");
|
||||||
const Module = require("./Module");
|
const Module = require("./Module");
|
||||||
const OriginalSource = require("webpack-sources").OriginalSource;
|
|
||||||
const RawSource = require("webpack-sources").RawSource;
|
|
||||||
const WebpackMissingModule = require("./dependencies/WebpackMissingModule");
|
const WebpackMissingModule = require("./dependencies/WebpackMissingModule");
|
||||||
const Template = require("./Template");
|
const Template = require("./Template");
|
||||||
|
|
||||||
|
@ -48,64 +48,92 @@ class ExternalModule extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
getSourceForGlobalVariableExternal(variableName, type) {
|
getSourceForGlobalVariableExternal(variableName, type) {
|
||||||
if(!Array.isArray(variableName)) {
|
if (!Array.isArray(variableName)) {
|
||||||
// make it an array as the look up works the same basically
|
// make it an array as the look up works the same basically
|
||||||
variableName = [variableName];
|
variableName = [variableName];
|
||||||
}
|
}
|
||||||
|
|
||||||
// needed for e.g. window["some"]["thing"]
|
// needed for e.g. window["some"]["thing"]
|
||||||
const objectLookup = variableName.map(r => `[${JSON.stringify(r)}]`).join("");
|
const objectLookup = variableName
|
||||||
|
.map(r => `[${JSON.stringify(r)}]`)
|
||||||
|
.join("");
|
||||||
return `(function() { module.exports = ${type}${objectLookup}; }());`;
|
return `(function() { module.exports = ${type}${objectLookup}; }());`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSourceForCommonJsExternal(moduleAndSpecifiers) {
|
getSourceForCommonJsExternal(moduleAndSpecifiers) {
|
||||||
if(!Array.isArray(moduleAndSpecifiers)) {
|
if (!Array.isArray(moduleAndSpecifiers)) {
|
||||||
return `module.exports = require(${JSON.stringify(moduleAndSpecifiers)});`;
|
return `module.exports = require(${JSON.stringify(
|
||||||
|
moduleAndSpecifiers
|
||||||
|
)});`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const moduleName = moduleAndSpecifiers[0];
|
const moduleName = moduleAndSpecifiers[0];
|
||||||
const objectLookup = moduleAndSpecifiers.slice(1).map(r => `[${JSON.stringify(r)}]`).join("");
|
const objectLookup = moduleAndSpecifiers
|
||||||
|
.slice(1)
|
||||||
|
.map(r => `[${JSON.stringify(r)}]`)
|
||||||
|
.join("");
|
||||||
return `module.exports = require(${moduleName})${objectLookup};`;
|
return `module.exports = require(${moduleName})${objectLookup};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkExternalVariable(variableToCheck, request) {
|
checkExternalVariable(variableToCheck, request) {
|
||||||
return `if(typeof ${variableToCheck} === 'undefined') {${WebpackMissingModule.moduleCode(request)}}\n`;
|
return `if(typeof ${
|
||||||
|
variableToCheck
|
||||||
|
} === 'undefined') {${WebpackMissingModule.moduleCode(request)}}\n`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSourceForAmdOrUmdExternal(id, optional, request) {
|
getSourceForAmdOrUmdExternal(id, optional, request) {
|
||||||
const externalVariable = `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(`${id}`)}__`;
|
const externalVariable = `__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(
|
||||||
const missingModuleError = optional ? this.checkExternalVariable(externalVariable, request) : "";
|
`${id}`
|
||||||
|
)}__`;
|
||||||
|
const missingModuleError = optional
|
||||||
|
? this.checkExternalVariable(externalVariable, request)
|
||||||
|
: "";
|
||||||
return `${missingModuleError}module.exports = ${externalVariable};`;
|
return `${missingModuleError}module.exports = ${externalVariable};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSourceForDefaultCase(optional, request) {
|
getSourceForDefaultCase(optional, request) {
|
||||||
const missingModuleError = optional ? this.checkExternalVariable(request, request) : "";
|
const missingModuleError = optional
|
||||||
|
? this.checkExternalVariable(request, request)
|
||||||
|
: "";
|
||||||
return `${missingModuleError}module.exports = ${request};`;
|
return `${missingModuleError}module.exports = ${request};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSourceString(runtime) {
|
getSourceString(runtime) {
|
||||||
const request = typeof this.request === "object" ? this.request[this.externalType] : this.request;
|
const request =
|
||||||
switch(this.externalType) {
|
typeof this.request === "object"
|
||||||
|
? this.request[this.externalType]
|
||||||
|
: this.request;
|
||||||
|
switch (this.externalType) {
|
||||||
case "this":
|
case "this":
|
||||||
case "window":
|
case "window":
|
||||||
case "self":
|
case "self":
|
||||||
return this.getSourceForGlobalVariableExternal(request, this.externalType);
|
return this.getSourceForGlobalVariableExternal(
|
||||||
|
request,
|
||||||
|
this.externalType
|
||||||
|
);
|
||||||
case "global":
|
case "global":
|
||||||
return this.getSourceForGlobalVariableExternal(runtime.outputOptions.globalObject, this.externalType);
|
return this.getSourceForGlobalVariableExternal(
|
||||||
|
runtime.outputOptions.globalObject,
|
||||||
|
this.externalType
|
||||||
|
);
|
||||||
case "commonjs":
|
case "commonjs":
|
||||||
case "commonjs2":
|
case "commonjs2":
|
||||||
return this.getSourceForCommonJsExternal(request);
|
return this.getSourceForCommonJsExternal(request);
|
||||||
case "amd":
|
case "amd":
|
||||||
case "umd":
|
case "umd":
|
||||||
case "umd2":
|
case "umd2":
|
||||||
return this.getSourceForAmdOrUmdExternal(this.id, this.optional, request);
|
return this.getSourceForAmdOrUmdExternal(
|
||||||
|
this.id,
|
||||||
|
this.optional,
|
||||||
|
request
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
return this.getSourceForDefaultCase(this.optional, request);
|
return this.getSourceForDefaultCase(this.optional, request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getSource(sourceString) {
|
getSource(sourceString) {
|
||||||
if(this.useSourceMap) {
|
if (this.useSourceMap) {
|
||||||
return new OriginalSource(sourceString, this.identifier());
|
return new OriginalSource(sourceString, this.identifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,9 +141,7 @@ class ExternalModule extends Module {
|
||||||
}
|
}
|
||||||
|
|
||||||
source(dependencyTemplates, runtime) {
|
source(dependencyTemplates, runtime) {
|
||||||
return this.getSource(
|
return this.getSource(this.getSourceString(runtime));
|
||||||
this.getSourceString(runtime)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size() {
|
size() {
|
||||||
|
|
|
@ -14,83 +14,97 @@ class ExternalModuleFactoryPlugin {
|
||||||
|
|
||||||
apply(normalModuleFactory) {
|
apply(normalModuleFactory) {
|
||||||
const globalType = this.type;
|
const globalType = this.type;
|
||||||
normalModuleFactory.hooks.factory.tap("ExternalModuleFactoryPlugin", factory => (data, callback) => {
|
normalModuleFactory.hooks.factory.tap(
|
||||||
const context = data.context;
|
"ExternalModuleFactoryPlugin",
|
||||||
const dependency = data.dependencies[0];
|
factory => (data, callback) => {
|
||||||
|
const context = data.context;
|
||||||
|
const dependency = data.dependencies[0];
|
||||||
|
|
||||||
const handleExternal = (value, type, callback) => {
|
const handleExternal = (value, type, callback) => {
|
||||||
if(typeof type === "function") {
|
if (typeof type === "function") {
|
||||||
callback = type;
|
callback = type;
|
||||||
type = undefined;
|
type = undefined;
|
||||||
}
|
|
||||||
if(value === false) return factory(data, callback);
|
|
||||||
if(value === true) value = dependency.request;
|
|
||||||
if(typeof type === "undefined" && /^[a-z0-9]+ /.test(value)) {
|
|
||||||
const idx = value.indexOf(" ");
|
|
||||||
type = value.substr(0, idx);
|
|
||||||
value = value.substr(idx + 1);
|
|
||||||
}
|
|
||||||
callback(null, new ExternalModule(value, type || globalType, dependency.request));
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleExternals = (externals, callback) => {
|
|
||||||
if(typeof externals === "string") {
|
|
||||||
if(externals === dependency.request) {
|
|
||||||
return handleExternal(dependency.request, callback);
|
|
||||||
}
|
}
|
||||||
} else if(Array.isArray(externals)) {
|
if (value === false) return factory(data, callback);
|
||||||
let i = 0;
|
if (value === true) value = dependency.request;
|
||||||
const next = () => {
|
if (typeof type === "undefined" && /^[a-z0-9]+ /.test(value)) {
|
||||||
let asyncFlag;
|
const idx = value.indexOf(" ");
|
||||||
const handleExternalsAndCallback = (err, module) => {
|
type = value.substr(0, idx);
|
||||||
if(err) return callback(err);
|
value = value.substr(idx + 1);
|
||||||
if(!module) {
|
}
|
||||||
if(asyncFlag) {
|
callback(
|
||||||
asyncFlag = false;
|
null,
|
||||||
return;
|
new ExternalModule(value, type || globalType, dependency.request)
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleExternals = (externals, callback) => {
|
||||||
|
if (typeof externals === "string") {
|
||||||
|
if (externals === dependency.request) {
|
||||||
|
return handleExternal(dependency.request, callback);
|
||||||
|
}
|
||||||
|
} else if (Array.isArray(externals)) {
|
||||||
|
let i = 0;
|
||||||
|
const next = () => {
|
||||||
|
let asyncFlag;
|
||||||
|
const handleExternalsAndCallback = (err, module) => {
|
||||||
|
if (err) return callback(err);
|
||||||
|
if (!module) {
|
||||||
|
if (asyncFlag) {
|
||||||
|
asyncFlag = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return next();
|
||||||
}
|
}
|
||||||
return next();
|
callback(null, module);
|
||||||
}
|
};
|
||||||
callback(null, module);
|
|
||||||
|
do {
|
||||||
|
asyncFlag = true;
|
||||||
|
if (i >= externals.length) return callback();
|
||||||
|
handleExternals(externals[i++], handleExternalsAndCallback);
|
||||||
|
} while (!asyncFlag); // eslint-disable-line keyword-spacing
|
||||||
|
asyncFlag = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
do {
|
next();
|
||||||
asyncFlag = true;
|
return;
|
||||||
if(i >= externals.length) return callback();
|
} else if (externals instanceof RegExp) {
|
||||||
handleExternals(externals[i++], handleExternalsAndCallback);
|
if (externals.test(dependency.request)) {
|
||||||
} while (!asyncFlag); // eslint-disable-line keyword-spacing
|
return handleExternal(dependency.request, callback);
|
||||||
asyncFlag = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
next();
|
|
||||||
return;
|
|
||||||
} else if(externals instanceof RegExp) {
|
|
||||||
if(externals.test(dependency.request)) {
|
|
||||||
return handleExternal(dependency.request, callback);
|
|
||||||
}
|
|
||||||
} else if(typeof externals === "function") {
|
|
||||||
externals.call(null, context, dependency.request, (err, value, type) => {
|
|
||||||
if(err) return callback(err);
|
|
||||||
if(typeof value !== "undefined") {
|
|
||||||
handleExternal(value, type, callback);
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
}
|
||||||
});
|
} else if (typeof externals === "function") {
|
||||||
return;
|
externals.call(
|
||||||
} else if(typeof externals === "object" && Object.prototype.hasOwnProperty.call(externals, dependency.request)) {
|
null,
|
||||||
return handleExternal(externals[dependency.request], callback);
|
context,
|
||||||
}
|
dependency.request,
|
||||||
callback();
|
(err, value, type) => {
|
||||||
};
|
if (err) return callback(err);
|
||||||
|
if (typeof value !== "undefined") {
|
||||||
|
handleExternal(value, type, callback);
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
} else if (
|
||||||
|
typeof externals === "object" &&
|
||||||
|
Object.prototype.hasOwnProperty.call(externals, dependency.request)
|
||||||
|
) {
|
||||||
|
return handleExternal(externals[dependency.request], callback);
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
};
|
||||||
|
|
||||||
handleExternals(this.externals, (err, module) => {
|
handleExternals(this.externals, (err, module) => {
|
||||||
if(err) return callback(err);
|
if (err) return callback(err);
|
||||||
if(!module) return handleExternal(false, callback);
|
if (!module) return handleExternal(false, callback);
|
||||||
return callback(null, module);
|
return callback(null, module);
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
module.exports = ExternalModuleFactoryPlugin;
|
module.exports = ExternalModuleFactoryPlugin;
|
||||||
|
|
|
@ -12,10 +12,10 @@ class ExternalsPlugin {
|
||||||
this.externals = externals;
|
this.externals = externals;
|
||||||
}
|
}
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compile.tap("ExternalsPlugin", ({
|
compiler.hooks.compile.tap("ExternalsPlugin", ({ normalModuleFactory }) => {
|
||||||
normalModuleFactory
|
new ExternalModuleFactoryPlugin(this.type, this.externals).apply(
|
||||||
}) => {
|
normalModuleFactory
|
||||||
new ExternalModuleFactoryPlugin(this.type, this.externals).apply(normalModuleFactory);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@ const Queue = require("./util/Queue");
|
||||||
|
|
||||||
const addToSet = (a, b) => {
|
const addToSet = (a, b) => {
|
||||||
let changed = false;
|
let changed = false;
|
||||||
for(const item of b) {
|
for (const item of b) {
|
||||||
if(!a.has(item)) {
|
if (!a.has(item)) {
|
||||||
a.add(item);
|
a.add(item);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
@ -18,113 +18,128 @@ const addToSet = (a, b) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
class FlagDependencyExportsPlugin {
|
class FlagDependencyExportsPlugin {
|
||||||
|
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compilation.tap("FlagDependencyExportsPlugin", (compilation) => {
|
compiler.hooks.compilation.tap(
|
||||||
compilation.hooks.finishModules.tap("FlagDependencyExportsPlugin", (modules) => {
|
"FlagDependencyExportsPlugin",
|
||||||
const dependencies = new Map();
|
compilation => {
|
||||||
|
compilation.hooks.finishModules.tap(
|
||||||
|
"FlagDependencyExportsPlugin",
|
||||||
|
modules => {
|
||||||
|
const dependencies = new Map();
|
||||||
|
|
||||||
const queue = new Queue();
|
const queue = new Queue();
|
||||||
|
|
||||||
let module;
|
let module;
|
||||||
let moduleWithExports;
|
let moduleWithExports;
|
||||||
let moduleProvidedExports;
|
let moduleProvidedExports;
|
||||||
|
|
||||||
const processDependenciesBlock = depBlock => {
|
const processDependenciesBlock = depBlock => {
|
||||||
for(const dep of depBlock.dependencies) {
|
for (const dep of depBlock.dependencies) {
|
||||||
if(processDependency(dep))
|
if (processDependency(dep)) return true;
|
||||||
return true;
|
}
|
||||||
}
|
for (const variable of depBlock.variables) {
|
||||||
for(const variable of depBlock.variables) {
|
for (const dep of variable.dependencies) {
|
||||||
for(const dep of variable.dependencies) {
|
if (processDependency(dep)) return true;
|
||||||
if(processDependency(dep))
|
}
|
||||||
|
}
|
||||||
|
for (const block of depBlock.blocks) {
|
||||||
|
if (processDependenciesBlock(block)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const processDependency = dep => {
|
||||||
|
const exportDesc = dep.getExports && dep.getExports();
|
||||||
|
if (!exportDesc) return;
|
||||||
|
moduleWithExports = true;
|
||||||
|
const exports = exportDesc.exports;
|
||||||
|
// break early if it's only in the worst state
|
||||||
|
if (module.buildMeta.providedExports === true) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
// break if it should move to the worst state
|
||||||
for(const block of depBlock.blocks) {
|
if (exports === true) {
|
||||||
if(processDependenciesBlock(block))
|
module.buildMeta.providedExports = true;
|
||||||
return true;
|
notifyDependencies();
|
||||||
}
|
return true;
|
||||||
return false;
|
}
|
||||||
};
|
// merge in new exports
|
||||||
|
if (Array.isArray(exports)) {
|
||||||
|
if (addToSet(moduleProvidedExports, exports)) {
|
||||||
|
notifyDependencies();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// store dependencies
|
||||||
|
const exportDeps = exportDesc.dependencies;
|
||||||
|
if (exportDeps) {
|
||||||
|
for (const exportDependency of exportDeps) {
|
||||||
|
// add dependency for this module
|
||||||
|
const set = dependencies.get(exportDependency);
|
||||||
|
if (set === undefined) {
|
||||||
|
dependencies.set(exportDependency, new Set([module]));
|
||||||
|
} else {
|
||||||
|
set.add(module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
const processDependency = dep => {
|
const notifyDependencies = () => {
|
||||||
const exportDesc = dep.getExports && dep.getExports();
|
const deps = dependencies.get(module);
|
||||||
if(!exportDesc) return;
|
if (deps !== undefined) {
|
||||||
moduleWithExports = true;
|
for (const dep of deps) {
|
||||||
const exports = exportDesc.exports;
|
queue.enqueue(dep);
|
||||||
// break early if it's only in the worst state
|
}
|
||||||
if(module.buildMeta.providedExports === true) {
|
}
|
||||||
return true;
|
};
|
||||||
}
|
|
||||||
// break if it should move to the worst state
|
// Start with all modules without provided exports
|
||||||
if(exports === true) {
|
for (const module of modules) {
|
||||||
module.buildMeta.providedExports = true;
|
if (!module.buildMeta.providedExports) {
|
||||||
notifyDependencies();
|
queue.enqueue(module);
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
// merge in new exports
|
|
||||||
if(Array.isArray(exports)) {
|
|
||||||
if(addToSet(moduleProvidedExports, exports)) {
|
|
||||||
notifyDependencies();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// store dependencies
|
while (queue.length > 0) {
|
||||||
const exportDeps = exportDesc.dependencies;
|
module = queue.dequeue();
|
||||||
if(exportDeps) {
|
|
||||||
for(const exportDependency of exportDeps) {
|
if (module.buildMeta.providedExports !== true) {
|
||||||
// add dependency for this module
|
moduleWithExports =
|
||||||
const set = dependencies.get(exportDependency);
|
module.buildMeta && module.buildMeta.exportsType;
|
||||||
if(set === undefined) {
|
moduleProvidedExports = Array.isArray(
|
||||||
dependencies.set(exportDependency, new Set([module]));
|
module.buildMeta.providedExports
|
||||||
} else {
|
)
|
||||||
set.add(module);
|
? new Set(module.buildMeta.providedExports)
|
||||||
|
: new Set();
|
||||||
|
processDependenciesBlock(module);
|
||||||
|
if (!moduleWithExports) {
|
||||||
|
module.buildMeta.providedExports = true;
|
||||||
|
notifyDependencies();
|
||||||
|
} else if (module.buildMeta.providedExports !== true) {
|
||||||
|
module.buildMeta.providedExports = Array.from(
|
||||||
|
moduleProvidedExports
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
);
|
||||||
};
|
const providedExportsCache = new WeakMap();
|
||||||
|
compilation.hooks.rebuildModule.tap(
|
||||||
const notifyDependencies = () => {
|
"FlagDependencyExportsPlugin",
|
||||||
const deps = dependencies.get(module);
|
module => {
|
||||||
if(deps !== undefined) {
|
providedExportsCache.set(module, module.buildMeta.providedExports);
|
||||||
for(const dep of deps) {
|
|
||||||
queue.enqueue(dep);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
);
|
||||||
|
compilation.hooks.finishRebuildingModule.tap(
|
||||||
// Start with all modules without provided exports
|
"FlagDependencyExportsPlugin",
|
||||||
for(const module of modules) {
|
module => {
|
||||||
if(!module.buildMeta.providedExports) {
|
module.buildMeta.providedExports = providedExportsCache.get(module);
|
||||||
queue.enqueue(module);
|
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
|
}
|
||||||
while(queue.length > 0) {
|
);
|
||||||
module = queue.dequeue();
|
|
||||||
|
|
||||||
if(module.buildMeta.providedExports !== true) {
|
|
||||||
moduleWithExports = module.buildMeta && module.buildMeta.exportsType;
|
|
||||||
moduleProvidedExports = Array.isArray(module.buildMeta.providedExports) ? new Set(module.buildMeta.providedExports) : new Set();
|
|
||||||
processDependenciesBlock(module);
|
|
||||||
if(!moduleWithExports) {
|
|
||||||
module.buildMeta.providedExports = true;
|
|
||||||
notifyDependencies();
|
|
||||||
} else if(module.buildMeta.providedExports !== true) {
|
|
||||||
module.buildMeta.providedExports = Array.from(moduleProvidedExports);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const providedExportsCache = new WeakMap();
|
|
||||||
compilation.hooks.rebuildModule.tap("FlagDependencyExportsPlugin", module => {
|
|
||||||
providedExportsCache.set(module, module.buildMeta.providedExports);
|
|
||||||
});
|
|
||||||
compilation.hooks.finishRebuildingModule.tap("FlagDependencyExportsPlugin", module => {
|
|
||||||
module.buildMeta.providedExports = providedExportsCache.get(module);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,92 +5,99 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const addToSet = (a, b) => {
|
const addToSet = (a, b) => {
|
||||||
for(const item of b) {
|
for (const item of b) {
|
||||||
if(!a.includes(item))
|
if (!a.includes(item)) a.push(item);
|
||||||
a.push(item);
|
|
||||||
}
|
}
|
||||||
return a;
|
return a;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isSubset = (biggerSet, subset) => {
|
const isSubset = (biggerSet, subset) => {
|
||||||
if(biggerSet === true) return true;
|
if (biggerSet === true) return true;
|
||||||
if(subset === true) return false;
|
if (subset === true) return false;
|
||||||
return subset.every(item => biggerSet.indexOf(item) >= 0);
|
return subset.every(item => biggerSet.indexOf(item) >= 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
class FlagDependencyUsagePlugin {
|
class FlagDependencyUsagePlugin {
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compilation.tap("FlagDependencyUsagePlugin", (compilation) => {
|
compiler.hooks.compilation.tap("FlagDependencyUsagePlugin", compilation => {
|
||||||
compilation.hooks.optimizeModulesAdvanced.tap("FlagDependencyUsagePlugin", (modules) => {
|
compilation.hooks.optimizeModulesAdvanced.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)) {
|
||||||
|
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;
|
||||||
|
|
||||||
const processModule = (module, usedExports) => {
|
// for a module without side effects we stop tracking usage here when no export is used
|
||||||
module.used = true;
|
// This module won't be evaluated in this case
|
||||||
if(module.usedExports === true)
|
if (module.factoryMeta.sideEffectFree) {
|
||||||
return;
|
if (module.usedExports === false) return;
|
||||||
else if(usedExports === true)
|
if (
|
||||||
module.usedExports = true;
|
Array.isArray(module.usedExports) &&
|
||||||
else if(Array.isArray(usedExports)) {
|
module.usedExports.length === 0
|
||||||
const old = module.usedExports ? module.usedExports.length : -1;
|
)
|
||||||
module.usedExports = addToSet(module.usedExports || [], usedExports);
|
return;
|
||||||
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
|
queue.push([module, module.usedExports]);
|
||||||
// This module won't be evaluated in this case
|
};
|
||||||
if(module.factoryMeta.sideEffectFree) {
|
|
||||||
if(module.usedExports === false) return;
|
|
||||||
if(Array.isArray(module.usedExports) && module.usedExports.length === 0) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
queue.push([module, module.usedExports]);
|
const processDependenciesBlock = (depBlock, usedExports) => {
|
||||||
};
|
for (const dep of depBlock.dependencies) {
|
||||||
|
|
||||||
const processDependenciesBlock = (depBlock, usedExports) => {
|
|
||||||
for(const dep of depBlock.dependencies) {
|
|
||||||
processDependency(dep);
|
|
||||||
}
|
|
||||||
for(const variable of depBlock.variables) {
|
|
||||||
for(const dep of variable.dependencies) {
|
|
||||||
processDependency(dep);
|
processDependency(dep);
|
||||||
}
|
}
|
||||||
}
|
for (const variable of depBlock.variables) {
|
||||||
for(const block of depBlock.blocks) {
|
for (const dep of variable.dependencies) {
|
||||||
queue.push([block, usedExports]);
|
processDependency(dep);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
for (const block of depBlock.blocks) {
|
||||||
|
queue.push([block, usedExports]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const processDependency = dep => {
|
const processDependency = dep => {
|
||||||
const reference = dep.getReference && dep.getReference();
|
const reference = dep.getReference && dep.getReference();
|
||||||
if(!reference) return;
|
if (!reference) return;
|
||||||
const module = reference.module;
|
const module = reference.module;
|
||||||
const importedNames = reference.importedNames;
|
const importedNames = reference.importedNames;
|
||||||
const oldUsed = module.used;
|
const oldUsed = module.used;
|
||||||
const oldUsedExports = module.usedExports;
|
const oldUsedExports = module.usedExports;
|
||||||
if(!oldUsed || (importedNames && (!oldUsedExports || !isSubset(oldUsedExports, importedNames)))) {
|
if (
|
||||||
processModule(module, importedNames);
|
!oldUsed ||
|
||||||
|
(importedNames &&
|
||||||
|
(!oldUsedExports || !isSubset(oldUsedExports, importedNames)))
|
||||||
|
) {
|
||||||
|
processModule(module, importedNames);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const module of modules) {
|
||||||
|
module.used = false;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
for(const module of modules) {
|
const queue = [];
|
||||||
module.used = false;
|
for (const chunk of compilation.chunks) {
|
||||||
}
|
if (chunk.entryModule) {
|
||||||
|
processModule(chunk.entryModule, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const queue = [];
|
while (queue.length) {
|
||||||
for(const chunk of compilation.chunks) {
|
const queueItem = queue.pop();
|
||||||
if(chunk.entryModule) {
|
processDependenciesBlock(queueItem[0], queueItem[1]);
|
||||||
processModule(chunk.entryModule, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
);
|
||||||
while(queue.length) {
|
|
||||||
const queueItem = queue.pop();
|
|
||||||
processDependenciesBlock(queueItem[0], queueItem[1]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,20 +10,26 @@ class FlagInitialModulesAsUsedPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compilation.tap("FlagInitialModulesAsUsedPlugin", (compilation) => {
|
compiler.hooks.compilation.tap(
|
||||||
compilation.hooks.afterOptimizeChunks.tap("FlagInitialModulesAsUsedPlugin", (chunks) => {
|
"FlagInitialModulesAsUsedPlugin",
|
||||||
for(const chunk of chunks) {
|
compilation => {
|
||||||
if(!chunk.isOnlyInitial()) {
|
compilation.hooks.afterOptimizeChunks.tap(
|
||||||
return;
|
"FlagInitialModulesAsUsedPlugin",
|
||||||
|
chunks => {
|
||||||
|
for (const chunk of chunks) {
|
||||||
|
if (!chunk.isOnlyInitial()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const module of chunk.modulesIterable) {
|
||||||
|
module.used = true;
|
||||||
|
module.usedExports = true;
|
||||||
|
module.addReason(null, null, this.explanation);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for(const module of chunk.modulesIterable) {
|
);
|
||||||
module.used = true;
|
}
|
||||||
module.usedExports = true;
|
);
|
||||||
module.addReason(null, null, this.explanation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,10 @@ class FunctionModulePlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(compiler) {
|
apply(compiler) {
|
||||||
compiler.hooks.compilation.tap("FunctionModulePlugin", (compilation) => {
|
compiler.hooks.compilation.tap("FunctionModulePlugin", compilation => {
|
||||||
new FunctionModuleTemplatePlugin().apply(compilation.moduleTemplates.javascript);
|
new FunctionModuleTemplatePlugin().apply(
|
||||||
|
compilation.moduleTemplates.javascript
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,67 +4,90 @@
|
||||||
*/
|
*/
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const ConcatSource = require("webpack-sources").ConcatSource;
|
const { ConcatSource } = require("webpack-sources");
|
||||||
const Template = require("./Template");
|
const Template = require("./Template");
|
||||||
|
|
||||||
class FunctionModuleTemplatePlugin {
|
class FunctionModuleTemplatePlugin {
|
||||||
apply(moduleTemplate) {
|
apply(moduleTemplate) {
|
||||||
moduleTemplate.hooks.render.tap("FunctionModuleTemplatePlugin", (moduleSource, module) => {
|
moduleTemplate.hooks.render.tap(
|
||||||
const source = new ConcatSource();
|
"FunctionModuleTemplatePlugin",
|
||||||
const args = [module.moduleArgument];
|
(moduleSource, module) => {
|
||||||
// TODO remove HACK checking type for javascript
|
|
||||||
if(module.type && module.type.startsWith("javascript")) {
|
|
||||||
args.push(module.exportsArgument);
|
|
||||||
if(module.hasDependencies(d => d.requireWebpackRequire !== false)) {
|
|
||||||
args.push("__webpack_require__");
|
|
||||||
}
|
|
||||||
} else if(module.type && module.type.startsWith("json")) {
|
|
||||||
// no additional arguments needed
|
|
||||||
} else {
|
|
||||||
args.push(module.exportsArgument, "__webpack_require__");
|
|
||||||
}
|
|
||||||
source.add("/***/ (function(" + args.join(", ") + ") {\n\n");
|
|
||||||
if(module.buildInfo.strict) source.add("\"use strict\";\n");
|
|
||||||
source.add(moduleSource);
|
|
||||||
source.add("\n\n/***/ })");
|
|
||||||
return source;
|
|
||||||
});
|
|
||||||
|
|
||||||
moduleTemplate.hooks.package.tap("FunctionModuleTemplatePlugin", (moduleSource, module) => {
|
|
||||||
if(moduleTemplate.runtimeTemplate.outputOptions.pathinfo) {
|
|
||||||
const source = new ConcatSource();
|
const source = new ConcatSource();
|
||||||
const req = module.readableIdentifier(moduleTemplate.runtimeTemplate.requestShortener);
|
const args = [module.moduleArgument];
|
||||||
source.add("/*!****" + req.replace(/./g, "*") + "****!*\\\n");
|
// TODO remove HACK checking type for javascript
|
||||||
source.add(" !*** " + req.replace(/\*\//g, "*_/") + " ***!\n");
|
if (module.type && module.type.startsWith("javascript")) {
|
||||||
source.add(" \\****" + req.replace(/./g, "*") + "****/\n");
|
args.push(module.exportsArgument);
|
||||||
if(Array.isArray(module.buildMeta.providedExports) && module.buildMeta.providedExports.length === 0)
|
if (module.hasDependencies(d => d.requireWebpackRequire !== false)) {
|
||||||
source.add(Template.toComment("no exports provided") + "\n");
|
args.push("__webpack_require__");
|
||||||
else if(Array.isArray(module.buildMeta.providedExports))
|
|
||||||
source.add(Template.toComment("exports provided: " + module.buildMeta.providedExports.join(", ")) + "\n");
|
|
||||||
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))
|
|
||||||
source.add(Template.toComment("exports used: " + module.usedExports.join(", ")) + "\n");
|
|
||||||
else if(module.usedExports)
|
|
||||||
source.add(Template.toComment("all exports used") + "\n");
|
|
||||||
if(module.optimizationBailout) {
|
|
||||||
for(const text of module.optimizationBailout) {
|
|
||||||
let code;
|
|
||||||
if(typeof text === "function") {
|
|
||||||
code = text(moduleTemplate.runtimeTemplate.requestShortener);
|
|
||||||
} else {
|
|
||||||
code = text;
|
|
||||||
}
|
|
||||||
source.add(Template.toComment(`${code}`) + "\n");
|
|
||||||
}
|
}
|
||||||
|
} else if (module.type && module.type.startsWith("json")) {
|
||||||
|
// no additional arguments needed
|
||||||
|
} else {
|
||||||
|
args.push(module.exportsArgument, "__webpack_require__");
|
||||||
}
|
}
|
||||||
|
source.add("/***/ (function(" + args.join(", ") + ") {\n\n");
|
||||||
|
if (module.buildInfo.strict) source.add('"use strict";\n');
|
||||||
source.add(moduleSource);
|
source.add(moduleSource);
|
||||||
|
source.add("\n\n/***/ })");
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
return moduleSource;
|
);
|
||||||
});
|
|
||||||
|
moduleTemplate.hooks.package.tap(
|
||||||
|
"FunctionModuleTemplatePlugin",
|
||||||
|
(moduleSource, module) => {
|
||||||
|
if (moduleTemplate.runtimeTemplate.outputOptions.pathinfo) {
|
||||||
|
const source = new ConcatSource();
|
||||||
|
const req = module.readableIdentifier(
|
||||||
|
moduleTemplate.runtimeTemplate.requestShortener
|
||||||
|
);
|
||||||
|
source.add("/*!****" + req.replace(/./g, "*") + "****!*\\\n");
|
||||||
|
source.add(" !*** " + req.replace(/\*\//g, "*_/") + " ***!\n");
|
||||||
|
source.add(" \\****" + req.replace(/./g, "*") + "****/\n");
|
||||||
|
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))
|
||||||
|
source.add(
|
||||||
|
Template.toComment(
|
||||||
|
"exports provided: " +
|
||||||
|
module.buildMeta.providedExports.join(", ")
|
||||||
|
) + "\n"
|
||||||
|
);
|
||||||
|
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))
|
||||||
|
source.add(
|
||||||
|
Template.toComment(
|
||||||
|
"exports used: " + module.usedExports.join(", ")
|
||||||
|
) + "\n"
|
||||||
|
);
|
||||||
|
else if (module.usedExports)
|
||||||
|
source.add(Template.toComment("all exports used") + "\n");
|
||||||
|
if (module.optimizationBailout) {
|
||||||
|
for (const text of module.optimizationBailout) {
|
||||||
|
let code;
|
||||||
|
if (typeof text === "function") {
|
||||||
|
code = text(moduleTemplate.runtimeTemplate.requestShortener);
|
||||||
|
} else {
|
||||||
|
code = text;
|
||||||
|
}
|
||||||
|
source.add(Template.toComment(`${code}`) + "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
source.add(moduleSource);
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
return moduleSource;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
moduleTemplate.hooks.hash.tap("FunctionModuleTemplatePlugin", hash => {
|
moduleTemplate.hooks.hash.tap("FunctionModuleTemplatePlugin", hash => {
|
||||||
hash.update("FunctionModuleTemplatePlugin");
|
hash.update("FunctionModuleTemplatePlugin");
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue