Merge branch 'master' into fix-help-output-test-5345

# Conflicts:
#	bin/webpack.js
This commit is contained in:
Tobias Koppers 2017-08-07 09:02:43 +02:00
commit 2acaf76dc3
122 changed files with 1929 additions and 409 deletions

2
.gitignore vendored
View File

@ -4,7 +4,7 @@
/test/fixtures/temp-cache-fixture
/benchmark/js
/benchmark/fixtures
/examples/*/js
/examples/**/js
/coverage
.DS_Store
*.log

View File

@ -1,4 +1,12 @@
<div align="center">
<a href="https://github.com/webpack/webpack">
<img width="200" heigth="200" src="https://webpack.js.org/assets/icon-square-big.svg">
</a>
<br>
<br>
[![npm][npm]][npm-url]
[![node][node]][node-url]
[![deps][deps]][deps-url]
[![tests][tests]][tests-url]
@ -6,11 +14,6 @@
[![coverage][cover]][cover-url]
[![licenses][licenses]][licenses-url]
<div align="center">
<a href="https://github.com/webpack/webpack">
<img width="200" heigth="200" src="https://webpack.js.org/assets/icon-square-big.svg">
</a>
<br>
<br>
<a href="https://npmjs.com/package/webpack">
<img src="https://img.shields.io/npm/dm/webpack.svg">
@ -32,10 +35,18 @@
<h2 align="center">Install</h2>
Install with npm:
```bash
npm install --save-dev webpack
```
Install with yarn:
```bash
yarn add webpack --dev
```
<h2 align="center">Introduction</h2>
> The README reflects webpack v2.x, webpack v1.x [documentation can be found here](https://webpack.github.io/docs/?utm_source=github&utm_medium=readme&utm_campaign=top).
@ -120,7 +131,7 @@ or are automatically applied via regex from your webpack configuration.
|Name|Status|Description|
|:--:|:----:|:----------|
|<a href="https://github.com/webpack/json-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/json.svg"></a>|![json-npm]|Loads a JSON file (included by default)|
|<a href="https://github.com/webpack/json5-loader"><img width="48" height="48" src="https://cdn.rawgit.com/json5/json5-logo/master/json5-logo.svg"></a>|![json5-npm]|Loads and transpiles a JSON 5 file|
|<a href="https://github.com/webpack/json5-loader"><img width="48" height="10.656" src="https://cdn.rawgit.com/json5/json5-logo/master/json5-logo.svg"></a>|![json5-npm]|Loads and transpiles a JSON 5 file|
|<a href="https://github.com/awnist/cson-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/coffeescript.svg"></a>|![cson-npm]|Loads and transpiles a CSON file|
@ -183,17 +194,17 @@ or are automatically applied via regex from your webpack configuration.
[stylus-npm]: https://img.shields.io/npm/v/stylus-loader.svg
[postcss-npm]: https://img.shields.io/npm/v/postcss-loader.svg
#### Linting && Testing
#### Linting & Testing
|Name|Status|Description|
|:--:|:----:|:----------|
|<a href="https://github.com/webpack/mocha-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/mocha.svg"></a>|![mocha-npm]|Tests with mocha (Browser/NodeJS)|
|<a href="https://github.com/MoOx/eslint-loader"><img width="48" height="48" src="https://worldvectorlogo.com/logos/eslint.svg"></a>|![eslint-npm]|PreLoader for linting code using ESLint|
|<a href="https://github.com/webpack/jslint-loader"><img width="48" height="48" src="http://jshint.com/res/jshint-dark.png"></a>|![jshint-npm]|PreLoader for linting code using JSHint|
|<a href="https://github.com/webpack-contrib/jshint-loader"><img width="48" height="20.64" src="http://jshint.com/res/jshint-dark.png"></a>|![jshint-npm]|PreLoader for linting code using JSHint|
[mocha-npm]: https://img.shields.io/npm/v/mocha-loader.svg
[eslint-npm]: https://img.shields.io/npm/v/eslint-loader.svg
[jshint-npm]: https://img.shields.io/npm/v/jslint-loader.svg
[jshint-npm]: https://img.shields.io/npm/v/jshint-loader.svg
[jscs-npm]: https://img.shields.io/npm/v/jscs-loader.svg
#### Frameworks
@ -264,7 +275,7 @@ If you create a loader or plugin, we would <3 for you to open source it, and put
<h2 align="center">Support</h2>
We consider webpack to be a low-level tool used not only individuals but also layered beneath other awesome tools. Because of it's flexibility, webpack isn't always the _easiest_ entry-level solution, however we do believe it is the most powerful. That said, we're always looking for ways improve and simplify the tool without compromising functionality. If you have any ideas on ways to accomplish this, we're all ears!
We consider webpack to be a low-level tool used not only individually but also layered beneath other awesome tools. Because of it's flexibility, webpack isn't always the _easiest_ entry-level solution, however we do believe it is the most powerful. That said, we're always looking for ways improve and simplify the tool without compromising functionality. If you have any ideas on ways to accomplish this, we're all ears!
If you're just getting started, take a look at [our new docs and concepts page](https://webpack.js.org/concepts/). This has a high level overview that is great for beginners!!
@ -314,7 +325,7 @@ If you have discovered a 🐜 or have a feature suggestion, feel free to create
<img width="150" height="150" src="https://github.com/bebraw.png?s=150">
<br>
<a href="https://github.com/bebraw">Juho Vepsäläinen</a>
<p>Documentation<p>
<p>Documentation</p>
<br>
<p>Author</p>
<a href="https://leanpub.com/survivejs-webpack">
@ -354,23 +365,33 @@ This is how we use the donations:
<h2 align="center">Premium Partners</h2>
<div align="center">
<a href="https://www.ag-grid.com/?utm_source=webpack&utm_medium=banner&utm_campaign=sponsorship" target="_blank"><img align="center" src="https://raw.githubusercontent.com/webpack/media/2b399d58/horiz-banner-ad-ag-grid.png">
</a>
</div>
<h2 align="center">Other Backers and Sponsors</h2>
Before we started using OpenCollective, donations were made anonymously. Now that we have made the switch, we would like to acknowledge these sponsors (and the ones who continue to donate using OpenCollective). If we've missed someone, please send us a PR, and we'll add you to this list.
<div align="center">
[Google Angular Team](https://angular.io/), [Architects.io](http://architects.io/),
<a href="https://moonmail.io" target="_blank" title="Email Marketing Software"><img
src="https://static.moonmail.io/moonmail-logo.svg" height="30" alt="MoonMail"></a>
<a href="https://monei.net" target="_blank" title="Best payment gateway rates"><img
src="https://static.monei.net/monei-logo.svg" height="30" alt="MONEI"></a>
</div>
<h2 align="center">Sponsors</h2>
[Become a sponsor](https://opencollective.com/webpack#sponsor) and get your logo on our README on Github with a link to your site.
<div align="center">
<a href="https://opencollective.com/webpack/sponsor/0/website?requireActive=false" target="_blank"><img src="https://opencollective.com/webpack/sponsor/0/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/webpack/sponsor/1/website?requireActive=false" target="_blank"><img src="https://opencollective.com/webpack/sponsor/1/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/webpack/sponsor/2/website?requireActive=false" target="_blank"><img src="https://opencollective.com/webpack/sponsor/2/avatar.svg?requireActive=false"></a>
@ -402,6 +423,8 @@ src="https://static.monei.net/monei-logo.svg" height="30" alt="MONEI"></a>
<a href="https://opencollective.com/webpack/sponsor/28/website?requireActive=false" target="_blank"><img src="https://opencollective.com/webpack/sponsor/28/avatar.svg?requireActive=false"></a>
<a href="https://opencollective.com/webpack/sponsor/29/website?requireActive=false" target="_blank"><img src="https://opencollective.com/webpack/sponsor/29/avatar.svg?requireActive=false"></a>
</div>
<h2 align="center">Backers</h2>
[Become a backer](https://opencollective.com/webpack#backer) and get your image on our README on Github with a link to your site.

View File

@ -0,0 +1,22 @@
const webpack = require("webpack");
const path = require("path");
webpack({
context: __dirname,
entry: "./createBenchmark/entry.js",
output: {
path: __dirname,
filename: "benchmark-bundle.js"
},
target: "node",
node: {
__dirname: false
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.IgnorePlugin(/^(fsevents|uglify-js)$/),
new webpack.NormalModuleReplacementPlugin(/^.\/loadLoader$/, path.resolve(__dirname, "./createBenchmark/loadLoader"))
]
}, function(err, stats) {
console.log(stats.toString());
});

View File

@ -0,0 +1,25 @@
const webpack = require("webpack");
const MemoryFs = require("memory-fs");
const path = require("path");
const testCase = process.argv[2];
const config = {
context: __dirname,
entry: `./${testCase}`,
output: {
path: path.resolve(__dirname, "output-" + testCase)
},
devtool: process.argv[3]
};
const compiler = webpack(config);
compiler.run((err, stats) => {
if(err) {
console.error(err);
} else {
console.log(stats.toString({
errorDetails: true
}));
}
});

View File

@ -0,0 +1,3 @@
module.exports = (loader, callback) => {
callback(new Error("Loaders are not supported"));
}

View File

@ -0,0 +1,70 @@
let avgJs = `
const str = "we" + "do" + "some" + "ops";
for(const x of str.split("")) {
if(x.charCodeAt(0) > 40) {
console.log("omg");
} else {
console.log(Math.random() * 2 + 3 * 2);
}
}
// Some comment
switch(a.b.c.d.f.e.g.h.i) {
case true:
break;
case "magic":
throw new Error("Error!");
case 9:
(function() {
// extra scope
var x = 123;
var y = 456;
var z = x + z * x / y;
x && y && (z = x ? y : x);
}())
}
function a() {}
function b() {}
function c() {}
function d() {}
function e() {}
function f() {}
`
for(var i = 0; i < 2; i++) {
avgJs += `(function() {${avgJs}}());`;
}
const fs = require("fs");
const root = __dirname;
createTree(fs, 100, `${root}/modules-100`);
createTree(fs, 500, `${root}/modules-500`);
createTree(fs, 1000, `${root}/modules-1000`);
createTree(fs, 3000, `${root}/modules-3000`);
createTree(fs, 5000, `${root}/modules-5000`);
function createTree(fs, count, folder) {
fs.mkdirSync(folder);
let remaining = count - 1;
function make(prefix, count, depth) {
if(count === 0) {
fs.writeFileSync(`${folder}/${prefix}.js`, `export default 1;\n${avgJs}`);
} else {
const list = [];
for(let i = 0; i < count; i++) {
if(remaining-- <= 0) break;
if(depth <= 4 && i >= 3 && i <= 4) {
list.push(`const module${i} = import("./${prefix}-${i}");\ncounter += module${i};`);
} else {
list.push(`import module${i} from "./${prefix}-${i}";\ncounter += module${i};`);
}
make(`${prefix}-${i}`, depth > 4 || count > 30 ? 0 : count + depth + i ** 2, depth + 1);
}
fs.writeFileSync(`${folder}/${prefix}.js`, `let counter = 0;\n${list.join("\n")};\nexport default counter;\n${avgJs}`)
}
}
make("index", 2, 0);
}

View File

@ -366,16 +366,14 @@ yargs.parse(process.argv.slice(2), (err, argv, output) => {
process.stdout.write(statsString + "\n");
}
if(!options.watch && stats.hasErrors()) {
process.on("exit", function() {
process.exit(2); // eslint-disable-line
});
process.exitCode = 2;
}
}
if(firstOptions.watch || options.watch) {
var watchOptions = firstOptions.watchOptions || firstOptions.watch || options.watch || {};
if(watchOptions.stdin) {
process.stdin.on("end", function() {
process.exit(0); // eslint-disable-line
process.exit(); // eslint-disable-line
});
process.stdin.resume();
}

View File

@ -2,26 +2,30 @@
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var cp = require("child_process");
var tc = require("./template-common");
var fs = require("fs");
"use strict";
var extraArgs = "";
const cp = require("child_process");
const path = require("path");
const tc = require("./template-common");
const fs = require("fs");
var targetArgs = global.NO_TARGET_ARGS ? "" : " ./example.js js/output.js";
var displayReasons = global.NO_REASONS ? "" : " --display-reasons --display-used-exports --display-provided-exports";
cp.exec("node ../../bin/webpack.js" + displayReasons + " --display-chunks --display-max-modules 99999 --display-origins --display-entrypoints --output-public-path \"js/\" -p " + extraArgs + targetArgs, function(error, stdout, stderr) {
const extraArgs = "";
const targetArgs = global.NO_TARGET_ARGS ? "" : " ./example.js js/output.js";
const displayReasons = global.NO_REASONS ? "" : " --display-reasons --display-used-exports --display-provided-exports";
cp.exec(`node ${path.resolve(__dirname, "../bin/webpack.js")} ${displayReasons} --display-chunks --display-max-modules 99999 --display-origins --display-entrypoints --output-public-path "js/" -p ${extraArgs} ${targetArgs}`, function(error, stdout, stderr) {
if(stderr)
console.log(stderr);
if(error !== null)
console.log(error);
let readme;
try {
var readme = tc.replaceResults(fs.readFileSync(require("path").join(process.cwd(), "template.md"), "utf-8"), process.cwd(), stdout.replace(/[\r\n]*$/, ""), "min");
readme = tc.replaceResults(fs.readFileSync(require("path").join(process.cwd(), "template.md"), "utf-8"), process.cwd(), stdout.replace(/[\r\n]*$/, ""), "min");
} catch(e) {
console.log(stderr);
throw e;
}
cp.exec("node ../../bin/webpack.js" + displayReasons + " --display-chunks --display-max-modules 99999 --display-origins --display-entrypoints --output-public-path \"js/\" --output-pathinfo " + extraArgs + targetArgs, function(error, stdout, stderr) {
cp.exec(`node ${path.resolve(__dirname, "../bin/webpack.js")} ${displayReasons} --display-chunks --display-max-modules 99999 --display-origins --display-entrypoints --output-public-path "js/" --output-pathinfo ${extraArgs} ${targetArgs}`, function(error, stdout, stderr) {
console.log(stdout);
if(stderr)
console.log(stderr);

View File

@ -1,27 +1,15 @@
var cp = require('child_process');
var path = require("path");
var fs = require("fs");
"use strict";
var cmds = fs.readdirSync(__dirname).filter(function(dirname) {
return fs.statSync(path.join(__dirname, dirname)).isDirectory() && dirname !== "node_modules";
}).sort().map(function(dirname) {
const cp = require("child_process");
const examples = require("./examples");
const cmds = examples.map(function(dirname) {
return "cd " + dirname + " && node build.js";
});
var stack = function() {
console.log("done");
};
for(var i = cmds.length-1; i >= 0; i--) {
var cmd = cmds[i];
stack = (function(next, cmd) {
return function() {
console.log(cmd);
cp.exec(cmd, function(error, stdout, stderr) {
if(error) console.error(error);
else if(stderr) console.error(stderr), next();
else next();
});
}
}(stack, cmd));
let i = 0;
for(const cmd of cmds.reverse()) {
console.log(`[${++i}/${cmds.length}] ${cmd}`);
cp.execSync(cmd, { encoding: "utf-8" });
}
stack();
console.log("done");

View File

@ -0,0 +1,185 @@
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.
The DllPlugin in combination with the `output.library` option exposes the internal require function as global variable in the target enviroment.
A manifest is creates which includes mappings from module names to internal ids.
### webpack.config.js
``` javascript
var path = require("path");
var webpack = require("../../../");
module.exports = {
context: __dirname,
entry: ["example-vendor"],
output: {
filename: "vendor.js", // best use [hash] here too
path: path.resolve(__dirname, "js"),
library: "vendor_lib_[hash]",
},
plugins: [
new webpack.DllPlugin({
name: "vendor_lib_[hash]",
path: path.resolve(__dirname, "js/vendor-manifest.json"),
}),
],
};
```
# example-vendor
``` javascript
export function square(n) {
return n * n;
}
```
# js/vendor.js
``` javascript
var vendor_lib_6b1edee0549eb5092709 =
```
<details><summary><code>/******/ (function(modules) { /* webpackBootstrap */ })</code></summary>
``` js
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "js/";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
```
</details>
``` js
/******/ ([
/* 0 */
/*!****************!*\
!*** dll main ***!
\****************/
/*! no static exports found */
/*! all exports used */
/***/ (function(module, exports, __webpack_require__) {
module.exports = __webpack_require__;
/***/ }),
/* 1 */
/*!*****************************************!*\
!*** ../node_modules/example-vendor.js ***!
\*****************************************/
/*! exports provided: square */
/*! all exports used */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony export (immutable) */ __webpack_exports__["square"] = square;
function square(n) {
return n * n;
}
/***/ })
/******/ ]);
```
# js/vendor-manifest.json
``` javascript
{"name":"vendor_lib_6b1edee0549eb5092709","content":{"../node_modules/example-vendor.js":{"id":1,"meta":{"harmonyModule":true},"exports":["square"]}}}
```
# Info
## Uncompressed
```
Hash: 6b1edee0549eb5092709
Version: webpack 3.4.1
Asset Size Chunks Chunk Names
vendor.js 3.18 kB 0 [emitted] main
Entrypoint main = vendor.js
chunk {0} vendor.js (main) 60 bytes [entry] [rendered]
> main [0] dll main
[0] dll main 12 bytes {0} [built]
+ 1 hidden module
```
## Minimized (uglify-js, no zip)
```
Hash: 6b1edee0549eb5092709
Version: webpack 3.4.1
Asset Size Chunks Chunk Names
vendor.js 652 bytes 0 [emitted] main
Entrypoint main = vendor.js
chunk {0} vendor.js (main) 60 bytes [entry] [rendered]
> main [0] dll main
[0] dll main 12 bytes {0} [built]
+ 1 hidden module
```

View File

@ -0,0 +1,2 @@
global.NO_TARGET_ARGS = true;
require("../../build-common");

View File

@ -0,0 +1,46 @@
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.
The DllPlugin in combination with the `output.library` option exposes the internal require function as global variable in the target enviroment.
A manifest is creates which includes mappings from module names to internal ids.
### webpack.config.js
``` javascript
{{webpack.config.js}}
```
# example-vendor
``` javascript
{{../node_modules/example-vendor.js}}
```
# js/vendor.js
``` javascript
{{js/vendor.js}}
```
# js/vendor-manifest.json
``` javascript
{{js/vendor-manifest.json}}
```
# Info
## Uncompressed
```
{{stdout}}
```
## Minimized (uglify-js, no zip)
```
{{min:stdout}}
```

View File

@ -0,0 +1,18 @@
var path = require("path");
var webpack = require("../../../");
module.exports = {
context: __dirname,
entry: ["example-vendor"],
output: {
filename: "vendor.js", // best use [hash] here too
path: path.resolve(__dirname, "js"),
library: "vendor_lib_[hash]",
},
plugins: [
new webpack.DllPlugin({
name: "vendor_lib_[hash]",
path: path.resolve(__dirname, "js/vendor-manifest.json"),
}),
],
};

View File

@ -0,0 +1,209 @@
This is the app part.
The previously built vendor dll is used. The DllReferencePlugin reads the content of the dll from the manifest file and excludes all vendor modules from the compilation. Instead references to these modules will be loaded from the vendor dll via a global variable (`vendor_lib_xxxx`).
# webpack.config.js
``` javascript
var path = require("path");
var webpack = require("../../../");
module.exports = {
context: __dirname,
entry: "./example-app",
output: {
filename: "app.js",
path: path.resolve(__dirname, "js"),
},
plugins: [
new webpack.DllReferencePlugin({
context: ".",
manifest: require("../0-vendor/js/vendor-manifest.json"), // eslint-disable-line
}),
],
};
```
# example-app.js
``` javascript
import { square } from "example-vendor";
console.log(square(7));
console.log(new square(7));
```
# example.html
``` html
<html>
<head></head>
<body>
<script src="js/vendor.bundle.js" charset="utf-8"></script>
<script src="js/app.bundle.js" charset="utf-8"></script>
</body>
</html>
```
# js/app.js
<details><summary><code>/******/ (function(modules) { /* webpackBootstrap */ })</code></summary>
``` javascript
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "js/";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
```
</details>
``` javascript
/******/ ([
/* 0 */
/*!************************!*\
!*** ./example-app.js ***!
\************************/
/*! exports provided: */
/*! all exports used */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_example_vendor__ = __webpack_require__(/*! example-vendor */ 1);
console.log(Object(__WEBPACK_IMPORTED_MODULE_0_example_vendor__["square"])(7));
console.log(new __WEBPACK_IMPORTED_MODULE_0_example_vendor__["square"](7));
/***/ }),
/* 1 */
/*!******************************************************************************************************!*\
!*** delegated ../node_modules/example-vendor.js from dll-reference vendor_lib_6b1edee0549eb5092709 ***!
\******************************************************************************************************/
/*! exports provided: square */
/*! all exports used */
/***/ (function(module, exports, __webpack_require__) {
module.exports = (__webpack_require__(2))(1);
/***/ }),
/* 2 */
/*!**************************************************!*\
!*** external "vendor_lib_6b1edee0549eb5092709" ***!
\**************************************************/
/*! no static exports found */
/*! all exports used */
/***/ (function(module, exports) {
module.exports = vendor_lib_6b1edee0549eb5092709;
/***/ })
/******/ ]);
```
# Info
## Uncompressed
```
Hash: 26778169dabaf1f3965d
Version: webpack 3.4.1
Asset Size Chunks Chunk Names
app.js 3.85 kB 0 [emitted] main
Entrypoint main = app.js
chunk {0} app.js (main) 182 bytes [entry] [rendered]
> main [0] ./example-app.js
[0] ./example-app.js 98 bytes {0} [built]
[no exports]
[1] delegated ../node_modules/example-vendor.js from dll-reference vendor_lib_6b1edee0549eb5092709 42 bytes {0} [built]
[exports: square]
harmony import example-vendor [0] ./example-app.js 1:0-40
+ 1 hidden module
```
## Minimized (uglify-js, no zip)
```
Hash: 26778169dabaf1f3965d
Version: webpack 3.4.1
Asset Size Chunks Chunk Names
app.js 710 bytes 0 [emitted] main
Entrypoint main = app.js
chunk {0} app.js (main) 182 bytes [entry] [rendered]
> main [0] ./example-app.js
[0] ./example-app.js 98 bytes {0} [built]
[no exports]
[1] delegated ../node_modules/example-vendor.js from dll-reference vendor_lib_6b1edee0549eb5092709 42 bytes {0} [built]
[exports: square]
harmony import example-vendor [0] ./example-app.js 1:0-40
+ 1 hidden module
```
<!-- @TODO:
- [ ] examples/dll-mode-and-context
- [ ] examples/dll-multiple
- [ ] examples/dll-dependencies
-->

View File

@ -0,0 +1,2 @@
global.NO_TARGET_ARGS = true;
require("../../build-common");

View File

@ -0,0 +1,4 @@
import { square } from "example-vendor";
console.log(square(7));
console.log(new square(7));

View File

@ -0,0 +1,7 @@
<html>
<head></head>
<body>
<script src="js/vendor.bundle.js" charset="utf-8"></script>
<script src="js/app.bundle.js" charset="utf-8"></script>
</body>
</html>

View File

@ -0,0 +1,47 @@
This is the app part.
The previously built vendor dll is used. The DllReferencePlugin reads the content of the dll from the manifest file and excludes all vendor modules from the compilation. Instead references to these modules will be loaded from the vendor dll via a global variable (`vendor_lib_xxxx`).
# webpack.config.js
``` javascript
{{webpack.config.js}}
```
# example-app.js
``` javascript
{{example-app.js}}
```
# example.html
``` html
{{example.html}}
```
# js/app.js
``` javascript
{{js/app.js}}
```
# Info
## Uncompressed
```
{{stdout}}
```
## Minimized (uglify-js, no zip)
```
{{min:stdout}}
```
<!-- @TODO:
- [ ] examples/dll-mode-and-context
- [ ] examples/dll-multiple
- [ ] examples/dll-dependencies
-->

View File

@ -0,0 +1,17 @@
var path = require("path");
var webpack = require("../../../");
module.exports = {
context: __dirname,
entry: "./example-app",
output: {
filename: "app.js",
path: path.resolve(__dirname, "js"),
},
plugins: [
new webpack.DllReferencePlugin({
context: ".",
manifest: require("../0-vendor/js/vendor-manifest.json"), // eslint-disable-line
}),
],
};

View File

@ -0,0 +1,9 @@
This example shows how to use the DllPlugin to separate vendor and app build.
This can boost the speed of the app build because vendors are no longer included, but built separately.
See [vendor part](0-vendor) and [app part](1-app).
[DllPlugin documentation](https://webpack.js.org/plugins/dll-plugin)
> Based on this gist: https://gist.github.com/Eoksni/83d1f1559e0ec00d0e89c33a6d763049 by Eoksni

View File

@ -0,0 +1,3 @@
export function square(n) {
return n * n;
}

26
examples/examples.js Normal file
View File

@ -0,0 +1,26 @@
"use strict";
const fs = require("fs");
const path = require("path");
function findInFolder(folder, depth) {
if(fs.existsSync(path.join(folder, "template.md"))) {
return [folder];
} else if(depth > 0) {
const files = fs.readdirSync(folder);
const results = [];
for(const file of files) {
const innerPath = path.join(folder, file);
if(fs.statSync(innerPath).isDirectory()) {
const innerResult = findInFolder(innerPath, depth - 1);
for(const item of innerResult)
results.push(item);
}
}
return results;
} else {
return [];
}
}
module.exports = findInFolder(__dirname, 2).sort();

View File

@ -140,8 +140,13 @@ class ContextModule extends Module {
this.addBlock(block);
}
} else {
} else if(this.async === "weak" || this.async === "async-weak") {
// we mark all dependencies as weak
dependencies.forEach(dep => dep.weak = true);
this.dependencies = dependencies;
} else {
// if we are lazy create a new async dependency block per dependency
// and add all blocks to this context
dependencies.forEach((dep, idx) => {
@ -198,6 +203,58 @@ module.exports = webpackContext;
webpackContext.id = ${JSON.stringify(id)};`;
}
getWeakSyncSource(dependencies, id) {
const map = this.getUserRequestMap(dependencies);
return `var map = ${JSON.stringify(map, null, "\t")};
function webpackContext(req) {
var id = webpackContextResolve(req);
if(!__webpack_require__.m[id])
throw new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)");
return __webpack_require__(id);
};
function webpackContextResolve(req) {
var id = map[req];
if(!(id + 1)) // check for number or string
throw new Error("Cannot find module '" + req + "'.");
return id;
};
webpackContext.keys = function webpackContextKeys() {
return Object.keys(map);
};
webpackContext.resolve = webpackContextResolve;
webpackContext.id = ${JSON.stringify(id)};
module.exports = webpackContext;`;
}
getAsyncWeakSource(dependencies, id) {
const map = this.getUserRequestMap(dependencies);
return `var map = ${JSON.stringify(map, null, "\t")};
function webpackAsyncContext(req) {
return webpackAsyncContextResolve(req).then(function(id) {
if(!__webpack_require__.m[id])
throw new Error("Module '" + req + "' ('" + id + "') is not available (weak dependency)");
return __webpack_require__(id);
});
};
function webpackAsyncContextResolve(req) {
// Here Promise.resolve().then() is used instead of new Promise() to prevent
// uncatched exception popping up in devtools
return Promise.resolve().then(function() {
var id = map[req];
if(!(id + 1)) // check for number or string
throw new Error("Cannot find module '" + req + "'.");
return id;
});
};
webpackAsyncContext.keys = function webpackAsyncContextKeys() {
return Object.keys(map);
};
webpackAsyncContext.resolve = webpackAsyncContextResolve;
webpackAsyncContext.id = ${JSON.stringify(id)};
module.exports = webpackAsyncContext;`;
}
getEagerSource(dependencies, id) {
const map = this.getUserRequestMap(dependencies);
return `var map = ${JSON.stringify(map, null, "\t")};
@ -205,20 +262,21 @@ function webpackAsyncContext(req) {
return webpackAsyncContextResolve(req).then(__webpack_require__);
};
function webpackAsyncContextResolve(req) {
return new Promise(function(resolve, reject) {
// Here Promise.resolve().then() is used instead of new Promise() to prevent
// uncatched exception popping up in devtools
return Promise.resolve().then(function() {
var id = map[req];
if(!(id + 1)) // check for number or string
reject(new Error("Cannot find module '" + req + "'."));
else
resolve(id);
throw new Error("Cannot find module '" + req + "'.");
return id;
});
};
webpackAsyncContext.keys = function webpackAsyncContextKeys() {
return Object.keys(map);
};
webpackAsyncContext.resolve = webpackAsyncContextResolve;
module.exports = webpackAsyncContext;
webpackAsyncContext.id = ${JSON.stringify(id)};`;
webpackAsyncContext.id = ${JSON.stringify(id)};
module.exports = webpackAsyncContext;`;
}
getLazyOnceSource(block, dependencies, id, outputOptions, requestShortener) {
@ -240,8 +298,8 @@ webpackAsyncContext.keys = function webpackAsyncContextKeys() {
return Object.keys(map);
};
webpackAsyncContext.resolve = webpackAsyncContextResolve;
module.exports = webpackAsyncContext;
webpackAsyncContext.id = ${JSON.stringify(id)};`;
webpackAsyncContext.id = ${JSON.stringify(id)};
module.exports = webpackAsyncContext;`;
}
getLazySource(blocks, id) {
@ -282,8 +340,8 @@ function webpackAsyncContext(req) {
webpackAsyncContext.keys = function webpackAsyncContextKeys() {
return Object.keys(map);
};
module.exports = webpackAsyncContext;
webpackAsyncContext.id = ${JSON.stringify(id)};`;
webpackAsyncContext.id = ${JSON.stringify(id)};
module.exports = webpackAsyncContext;`;
}
getSourceForEmptyContext(id) {
@ -298,7 +356,11 @@ webpackEmptyContext.id = ${JSON.stringify(id)};`;
getSourceForEmptyAsyncContext(id) {
return `function webpackEmptyAsyncContext(req) {
return new Promise(function(resolve, reject) { reject(new Error("Cannot find module '" + req + "'.")); });
// Here Promise.resolve().then() is used instead of new Promise() to prevent
// uncatched exception popping up in devtools
return Promise.resolve().then(function() {
throw new Error("Cannot find module '" + req + "'.");
});
}
webpackEmptyAsyncContext.keys = function() { return []; };
webpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;
@ -318,13 +380,25 @@ webpackEmptyAsyncContext.id = ${JSON.stringify(id)};`;
return this.getEagerSource(this.dependencies, this.id);
}
return this.getSourceForEmptyAsyncContext(this.id);
} else if(asyncMode === "lazy-once") {
}
if(asyncMode === "lazy-once") {
const block = this.blocks[0];
if(block) {
return this.getLazyOnceSource(block, block.dependencies, this.id, outputOptions, requestShortener);
}
return this.getSourceForEmptyAsyncContext(this.id);
}
if(asyncMode === "async-weak") {
if(this.dependencies && this.dependencies.length > 0) {
return this.getAsyncWeakSource(this.dependencies, this.id);
}
return this.getSourceForEmptyAsyncContext(this.id);
}
if(asyncMode === "weak") {
if(this.dependencies && this.dependencies.length > 0) {
return this.getWeakSyncSource(this.dependencies, this.id);
}
}
if(this.dependencies && this.dependencies.length > 0) {
return this.getSyncSource(this.dependencies, this.id);
}

View File

@ -9,20 +9,26 @@ const OriginalSource = require("webpack-sources").OriginalSource;
const RawSource = require("webpack-sources").RawSource;
const WebpackMissingModule = require("./dependencies/WebpackMissingModule");
const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency");
const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency");
class DelegatedModule extends Module {
constructor(sourceRequest, data, type, userRequest) {
constructor(sourceRequest, data, type, userRequest, originalRequest) {
super();
this.sourceRequest = sourceRequest;
this.request = data.id;
this.meta = data.meta;
this.type = type;
this.originalRequest = originalRequest;
this.userRequest = userRequest;
this.built = false;
this.delegated = true;
this.delegateData = data;
}
libIdent(options) {
return typeof this.originalRequest === "string" ? this.originalRequest : this.originalRequest.libIdent(options);
}
identifier() {
return `delegated ${JSON.stringify(this.request)} from ${this.sourceRequest}`;
}
@ -38,10 +44,10 @@ class DelegatedModule extends Module {
build(options, compilation, resolver, fs, callback) {
this.built = true;
this.builtTime = Date.now();
this.usedExports = true;
this.providedExports = this.delegateData.exports || true;
this.cacheable = true;
this.dependencies.length = 0;
this.addDependency(new DelegatedSourceDependency(this.sourceRequest));
this.addDependency(new DelegatedExportsDependency(this, this.delegateData.exports || true));
callback();
}
@ -57,7 +63,7 @@ class DelegatedModule extends Module {
if(!sourceModule) {
str = WebpackMissingModule.moduleCode(this.sourceRequest);
} else {
str = `module.exports = (__webpack_require__(${sourceModule.id}))`;
str = `module.exports = (__webpack_require__(${JSON.stringify(sourceModule.id)}))`;
switch(this.type) {
case "require":

View File

@ -29,13 +29,14 @@ class DelegatedModuleFactoryPlugin {
let resolved;
if(innerRequest in this.options.content) {
resolved = this.options.content[innerRequest];
return callback(null, new DelegatedModule(this.options.source, resolved, this.options.type, innerRequest));
return callback(null, new DelegatedModule(this.options.source, resolved, this.options.type, innerRequest, request));
}
for(let i = 0; i < this.options.extensions.length; i++) {
const requestPlusExt = innerRequest + this.options.extensions[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));
return callback(null, new DelegatedModule(this.options.source, resolved, this.options.type, requestPlusExt, request + extension));
}
}
}
@ -47,7 +48,7 @@ class DelegatedModuleFactoryPlugin {
const request = module.libIdent(this.options);
if(request && request in this.options.content) {
const resolved = this.options.content[request];
return new DelegatedModule(this.options.source, resolved, this.options.type, request);
return new DelegatedModule(this.options.source, resolved, this.options.type, request, module);
}
}
return module;

View File

@ -7,6 +7,8 @@
const DelegatedModuleFactoryPlugin = require("./DelegatedModuleFactoryPlugin");
const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency");
const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency");
const NullFactory = require("./NullFactory");
class DelegatedPlugin {
constructor(options) {
@ -16,6 +18,7 @@ class DelegatedPlugin {
apply(compiler) {
compiler.plugin("compilation", (compilation, params) => {
compilation.dependencyFactories.set(DelegatedSourceDependency, params.normalModuleFactory);
compilation.dependencyFactories.set(DelegatedExportsDependency, new NullFactory());
});
compiler.plugin("compile", (params) => {

View File

@ -7,6 +7,8 @@
const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDependency");
const DelegatedModuleFactoryPlugin = require("./DelegatedModuleFactoryPlugin");
const ExternalModuleFactoryPlugin = require("./ExternalModuleFactoryPlugin");
const DelegatedExportsDependency = require("./dependencies/DelegatedExportsDependency");
const NullFactory = require("./NullFactory");
class DllReferencePlugin {
constructor(options) {
@ -17,6 +19,7 @@ class DllReferencePlugin {
compiler.plugin("compilation", (compilation, params) => {
const normalModuleFactory = params.normalModuleFactory;
compilation.dependencyFactories.set(DelegatedSourceDependency, normalModuleFactory);
compilation.dependencyFactories.set(DelegatedExportsDependency, new NullFactory());
});
compiler.plugin("before-compile", (params, callback) => {

View File

@ -10,14 +10,19 @@ const WebpackMissingModule = require("./dependencies/WebpackMissingModule");
const Template = require("./Template");
class ExternalModule extends Module {
constructor(request, type) {
constructor(request, type, userRequest) {
super();
this.request = request;
this.userRequest = userRequest;
this.type = type;
this.built = false;
this.external = true;
}
libIdent() {
return this.userRequest;
}
chunkCondition(chunk) {
return chunk.hasEntryModule();
}

View File

@ -30,7 +30,7 @@ class ExternalModuleFactoryPlugin {
type = value.substr(0, idx);
value = value.substr(idx + 1);
}
callback(null, new ExternalModule(value, type || globalType));
callback(null, new ExternalModule(value, type || globalType, dependency.request));
return true;
}
(function handleExternals(externals, callback) {

View File

@ -9,7 +9,11 @@ const SizeFormatHelpers = require("./SizeFormatHelpers");
const formatLocation = require("./formatLocation");
const identifierUtils = require("./util/identifier");
const optionOrFallback = (optionValue, fallbackValue) => typeof optionValue !== "undefined" ? optionValue : fallbackValue;
const optionsOrFallback = function() {
let optionValues = [];
optionValues.push.apply(optionValues, arguments);
return optionValues.find(optionValue => typeof optionValue !== "undefined");
};
class Stats {
constructor(compilation) {
@ -80,8 +84,19 @@ class Stats {
typeof v !== "undefined" ? v :
typeof options.all !== "undefined" ? options.all : def;
const testAgainstGivenOption = (item) => {
if(typeof item === "string") {
const regExp = new RegExp(`[\\\\/]${item.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")}([\\\\/]|$|!|\\?)`); // eslint-disable-line no-useless-escape
return ident => regExp.test(ident);
}
if(item && typeof item === "object" && typeof item.test === "function")
return ident => item.test(ident);
if(typeof item === "function")
return item;
};
const compilation = this.compilation;
const context = optionOrFallback(options.context, process.cwd());
const context = optionsOrFallback(options.context, process.cwd());
const requestShortener = new RequestShortener(context);
const showPerformance = optionOrLocalFallback(options.performance, true);
const showHash = optionOrLocalFallback(options.hash, true);
@ -106,22 +121,14 @@ class Stats {
const showErrors = optionOrLocalFallback(options.errors, true);
const showErrorDetails = optionOrLocalFallback(options.errorDetails, !forToString);
const showWarnings = optionOrLocalFallback(options.warnings, true);
const warningsFilter = optionOrFallback(options.warningsFilter, null);
const warningsFilter = optionsOrFallback(options.warningsFilter, null);
const showPublicPath = optionOrLocalFallback(options.publicPath, !forToString);
const excludeModules = [].concat(optionOrFallback(options.exclude, [])).map(item => {
if(typeof item === "string") {
const regExp = new RegExp(`[\\\\/]${item.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")}([\\\\/]|$|!|\\?)`); // eslint-disable-line no-useless-escape
return ident => regExp.test(ident);
}
if(item && typeof item === "object" && typeof item.test === "function")
return ident => item.test(ident);
if(typeof item === "function")
return item;
});
const maxModules = optionOrFallback(options.maxModules, forToString ? 15 : Infinity);
const sortModules = optionOrFallback(options.modulesSort, "id");
const sortChunks = optionOrFallback(options.chunksSort, "id");
const sortAssets = optionOrFallback(options.assetsSort, "");
const excludeModules = [].concat(optionsOrFallback(options.excludeModules, options.exclude, [])).map(testAgainstGivenOption);
const excludeAssets = [].concat(optionsOrFallback(options.excludeAssets, [])).map(testAgainstGivenOption);
const maxModules = optionsOrFallback(options.maxModules, forToString ? 15 : Infinity);
const sortModules = optionsOrFallback(options.modulesSort, "id");
const sortChunks = optionsOrFallback(options.chunksSort, "id");
const sortAssets = optionsOrFallback(options.assetsSort, "");
if(!showCachedModules) {
excludeModules.push((ident, module) => !module.built);
@ -140,6 +147,18 @@ class Stats {
};
};
const createAssetFilter = () => {
return asset => {
if(excludeAssets.length > 0) {
const ident = asset.name;
const excluded = excludeAssets.some(fn => fn(ident, asset));
if(excluded)
return false;
}
return showCachedAssets || asset.emitted;
};
};
const sortByFieldAndOrder = (fieldKey, a, b) => {
if(a[fieldKey] === null && b[fieldKey] === null) return 0;
if(a[fieldKey] === null) return 1;
@ -231,8 +250,9 @@ class Stats {
}
if(showAssets) {
const assetsByFile = {};
const compilationAssets = Object.keys(compilation.assets);
obj.assetsByChunkName = {};
obj.assets = Object.keys(compilation.assets).map(asset => {
obj.assets = compilationAssets.map(asset => {
const obj = {
name: asset,
size: compilation.assets[asset].size(),
@ -247,7 +267,8 @@ class Stats {
assetsByFile[asset] = obj;
return obj;
}).filter(asset => showCachedAssets || asset.emitted);
}).filter(createAssetFilter());
obj.filteredAssets = compilationAssets.length - obj.assets.length;
compilation.chunks.forEach(chunk => {
chunk.files.forEach(asset => {
@ -409,7 +430,7 @@ class Stats {
options = {};
}
const useColors = optionOrFallback(options.colors, false);
const useColors = optionsOrFallback(options.colors, false);
const obj = this.toJson(options, true);
@ -576,6 +597,16 @@ class Stats {
});
table(t, "rrrlll");
}
if(obj.filteredAssets > 0) {
colors.normal(" ");
if(obj.assets.length > 0)
colors.normal("+ ");
colors.normal(obj.filteredAssets);
if(obj.assets.length > 0)
colors.normal(" hidden");
colors.normal(obj.filteredAssets !== 1 ? " assets" : " asset");
newline();
}
if(obj.entrypoints) {
Object.keys(obj.entrypoints).forEach(name => {
const ep = obj.entrypoints[name];
@ -653,7 +684,7 @@ class Stats {
if(module.usedExports !== undefined) {
if(module.usedExports !== true) {
colors.normal(prefix);
if(module.usedExports === false)
if(module.usedExports === false || module.usedExports.length === 0)
colors.cyan("[no exports used]");
else
colors.cyan(`[only some exports used: ${module.usedExports.join(", ")}]`);

View File

@ -0,0 +1,33 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const NullDependency = require("./NullDependency");
class DelegatedExportsDependency extends NullDependency {
constructor(originModule, exports) {
super();
this.originModule = originModule;
this.exports = exports;
}
get type() {
return "delegated exports";
}
getReference() {
return {
module: this.originModule,
importedNames: true
};
}
getExports() {
return {
exports: this.exports
};
}
}
module.exports = DelegatedExportsDependency;

View File

@ -5,6 +5,8 @@
"use strict";
const ImportEagerContextDependency = require("./ImportEagerContextDependency");
const ImportWeakDependency = require("./ImportWeakDependency");
const ImportWeakContextDependency = require("./ImportWeakContextDependency");
const ImportLazyOnceContextDependency = require("./ImportLazyOnceContextDependency");
const ImportLazyContextDependency = require("./ImportLazyContextDependency");
const ImportDependenciesBlock = require("./ImportDependenciesBlock");
@ -46,26 +48,31 @@ class ImportParserPlugin {
}
if(param.isString()) {
if(mode !== "lazy" && mode !== "eager") {
parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackMode\` expected 'lazy' or 'eager', but received: ${mode}.`));
if(mode !== "lazy" && mode !== "eager" && mode !== "weak") {
parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackMode\` expected 'lazy', 'eager' or 'weak', but received: ${mode}.`));
}
if(mode === "eager") {
const dep = new ImportEagerDependency(param.string, expr.range);
parser.state.current.addDependency(dep);
} else if(mode === "weak") {
const dep = new ImportWeakDependency(param.string, expr.range);
parser.state.current.addDependency(dep);
} else {
const depBlock = new ImportDependenciesBlock(param.string, expr.range, chunkName, parser.state.module, expr.loc);
parser.state.current.addBlock(depBlock);
}
return true;
} else {
if(mode !== "lazy" && mode !== "lazy-once" && mode !== "eager") {
parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackMode\` expected 'lazy', 'lazy-once' or 'eager', but received: ${mode}.`));
if(mode !== "lazy" && mode !== "lazy-once" && mode !== "eager" && mode !== "weak") {
parser.state.module.warnings.push(new UnsupportedFeatureWarning(parser.state.module, `\`webpackMode\` expected 'lazy', 'lazy-once', 'eager' or 'weak', but received: ${mode}.`));
}
let Dep = ImportLazyContextDependency;
if(mode === "eager") {
Dep = ImportEagerContextDependency;
} else if(mode === "weak") {
Dep = ImportWeakContextDependency;
} else if(mode === "lazy-once") {
Dep = ImportLazyOnceContextDependency;
}

View File

@ -6,7 +6,9 @@
const ImportDependency = require("./ImportDependency");
const ImportEagerDependency = require("./ImportEagerDependency");
const ImportWeakDependency = require("./ImportWeakDependency");
const ImportEagerContextDependency = require("./ImportEagerContextDependency");
const ImportWeakContextDependency = require("./ImportWeakContextDependency");
const ImportLazyOnceContextDependency = require("./ImportLazyOnceContextDependency");
const ImportLazyContextDependency = require("./ImportLazyContextDependency");
const ImportParserPlugin = require("./ImportParserPlugin");
@ -28,9 +30,15 @@ class ImportPlugin {
compilation.dependencyFactories.set(ImportEagerDependency, normalModuleFactory);
compilation.dependencyTemplates.set(ImportEagerDependency, new ImportEagerDependency.Template());
compilation.dependencyFactories.set(ImportWeakDependency, normalModuleFactory);
compilation.dependencyTemplates.set(ImportWeakDependency, new ImportWeakDependency.Template());
compilation.dependencyFactories.set(ImportEagerContextDependency, contextModuleFactory);
compilation.dependencyTemplates.set(ImportEagerContextDependency, new ImportEagerContextDependency.Template());
compilation.dependencyFactories.set(ImportWeakContextDependency, contextModuleFactory);
compilation.dependencyTemplates.set(ImportWeakContextDependency, new ImportWeakContextDependency.Template());
compilation.dependencyFactories.set(ImportLazyOnceContextDependency, contextModuleFactory);
compilation.dependencyTemplates.set(ImportLazyOnceContextDependency, new ImportLazyOnceContextDependency.Template());

View File

@ -0,0 +1,22 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ImportContextDependency = require("./ImportContextDependency");
const ContextDependencyTemplateAsRequireCall = require("./ContextDependencyTemplateAsRequireCall");
class ImportWeakContextDependency extends ImportContextDependency {
constructor(request, recursive, regExp, range, valueRange, chunkName) {
super(request, recursive, regExp, range, valueRange, chunkName);
this.async = "async-weak";
}
get type() {
return "import() context weak";
}
}
ImportWeakContextDependency.Template = ContextDependencyTemplateAsRequireCall;
module.exports = ImportWeakContextDependency;

View File

@ -0,0 +1,47 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("./ModuleDependency");
const webpackMissingPromiseModule = require("./WebpackMissingModule").promise;
class ImportWeakDependency extends ModuleDependency {
constructor(request, range) {
super(request);
this.range = range;
this.weak = true;
}
get type() {
return "import() weak";
}
}
ImportWeakDependency.Template = class ImportDependencyTemplate {
apply(dep, source, outputOptions, requestShortener) {
const comment = this.getOptionalComment(outputOptions.pathinfo, requestShortener.shorten(dep.request));
const content = this.getContent(dep, comment);
source.replace(dep.range[0], dep.range[1] - 1, content);
}
getOptionalComment(pathinfo, shortenedRequest) {
if(!pathinfo) {
return "";
}
return `/*! ${shortenedRequest} */ `;
}
getContent(dep, comment) {
if(dep.module) {
const stringifiedId = JSON.stringify(dep.module.id);
return `Promise.resolve(${comment}${stringifiedId}).then(function(id) { if(!__webpack_require__.m[id]) throw new Error("Module '" + id + "' is not available (weak dependency)"); return __webpack_require__(id); })`;
}
return webpackMissingPromiseModule(dep.request);
}
};
module.exports = ImportWeakDependency;

View File

@ -7,9 +7,13 @@ const ContextDependency = require("./ContextDependency");
const ModuleDependencyTemplateAsRequireId = require("./ModuleDependencyTemplateAsRequireId");
class RequireContextDependency extends ContextDependency {
constructor(request, recursive, regExp, range) {
constructor(request, recursive, regExp, asyncMode, range) {
super(request, recursive, regExp);
this.range = range;
if(asyncMode) {
this.async = asyncMode;
}
}
get type() {

View File

@ -11,7 +11,15 @@ module.exports = class RequireContextDependencyParserPlugin {
parser.plugin("call require.context", expr => {
let regExp = /^\.\/.*$/;
let recursive = true;
let asyncMode;
switch(expr.arguments.length) {
case 4:
{
const asyncModeExpr = parser.evaluateExpression(expr.arguments[3]);
if(!asyncModeExpr.isString()) return;
asyncMode = asyncModeExpr.string;
}
// falls through
case 3:
{
const regExpExpr = parser.evaluateExpression(expr.arguments[2]);
@ -30,7 +38,7 @@ module.exports = class RequireContextDependencyParserPlugin {
{
const requestExpr = parser.evaluateExpression(expr.arguments[0]);
if(!requestExpr.isString()) return;
const dep = new RequireContextDependency(requestExpr.string, recursive, regExp, expr.range);
const dep = new RequireContextDependency(requestExpr.string, recursive, regExp, asyncMode, expr.range);
dep.loc = expr.loc;
dep.optional = parser.scope.inTry;
parser.state.current.addDependency(dep);

View File

@ -62,7 +62,7 @@ class RequireResolveDependencyParserPlugin {
if(!dep) return;
dep.loc = expr.loc;
dep.optional = !!parser.scope.inTry;
dep.weak = weak;
dep.async = weak ? "weak" : false;
parser.state.current.addDependency(dep);
return true;
});

View File

@ -201,7 +201,7 @@ You can however specify the name of the async chunk by passing the desired strin
// we dont have named chunks specified, so we just take all of them
if(asyncOrNoSelectedChunk) {
return allChunks.filter(chunk => !chunk.isInitial());
return allChunks;
}
/**
@ -229,8 +229,15 @@ Take a look at the "name"/"names" or async/children option.`);
}
return targetChunk.chunks.filter((chunk) => {
// we only are interested in on-demand chunks
if(chunk.isInitial())
return false;
// we can only move modules from this chunk if the "commonChunk" is the only parent
return asyncOption || chunk.parents.length === 1;
if(!asyncOption)
return chunk.parents.length === 1;
return true;
});
}

View File

@ -7,6 +7,11 @@
const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
const ConcatenatedModule = require("./ConcatenatedModule");
const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
const HarmonyCompatibilityDependency = require("../dependencies/HarmonyCompatibilityDependency");
function formatBailoutReason(msg) {
return "ModuleConcatenation bailout: " + msg;
}
class ModuleConcatenationPlugin {
constructor(options) {
@ -23,9 +28,9 @@ class ModuleConcatenationPlugin {
});
const bailoutReasonMap = new Map();
function setBailoutReason(module, prefix, reason) {
function setBailoutReason(module, reason) {
bailoutReasonMap.set(module, reason);
module.optimizationBailout.push(typeof reason === "function" ? (rs) => `${prefix}: ${reason(rs)}` : `${prefix}: ${reason}`);
module.optimizationBailout.push(typeof reason === "function" ? (rs) => formatBailoutReason(reason(rs)) : formatBailoutReason(reason));
}
function getBailoutReason(module, requestShortener) {
@ -39,13 +44,14 @@ class ModuleConcatenationPlugin {
const possibleInners = new Set();
for(const module of modules) {
// Only harmony modules are valid for optimization
if(!module.meta || !module.meta.harmonyModule) {
if(!module.meta || !module.meta.harmonyModule || !module.dependencies.some(d => d instanceof HarmonyCompatibilityDependency)) {
setBailoutReason(module, "Module is not an ECMAScript module");
continue;
}
// Because of variable renaming we can't use modules with eval
if(module.meta && module.meta.hasEval) {
setBailoutReason(module, "ModuleConcatenation", "eval is used in the module");
setBailoutReason(module, "Module uses eval()");
continue;
}
@ -53,19 +59,19 @@ class ModuleConcatenationPlugin {
// Module must not be the entry points
if(module.getChunks().some(chunk => chunk.entryModule === module)) {
setBailoutReason(module, "ModuleConcatenation (inner)", "module is an entrypoint");
setBailoutReason(module, "Module is an entry point");
continue;
}
// Exports must be known (and not dynamic)
if(!Array.isArray(module.providedExports)) {
setBailoutReason(module, "ModuleConcatenation (inner)", "exports are not known");
setBailoutReason(module, "Module exports are unknown");
continue;
}
// Using dependency variables is not possible as this wraps the code in a function
if(module.variables.length > 0) {
setBailoutReason(module, "ModuleConcatenation (inner)", "dependency variables are used (i. e. ProvidePlugin)");
setBailoutReason(module, "Module uses injected variables (usually caused by the ProvidePlugin)");
continue;
}
@ -73,9 +79,10 @@ class ModuleConcatenationPlugin {
const nonHarmonyReasons = module.reasons.filter(reason => !(reason.dependency instanceof HarmonyImportDependency));
if(nonHarmonyReasons.length > 0) {
const importingModules = new Set(nonHarmonyReasons.map(r => r.module));
setBailoutReason(module, "ModuleConcatenation (inner)", (requestShortener) => {
const names = Array.from(importingModules).map(m => m.readableIdentifier(requestShortener)).sort();
return `module is used with non-harmony imports from ${names.join(", ")}`;
const importingModuleTypes = new Map(Array.from(importingModules).map(m => [m, new Set(nonHarmonyReasons.filter(r => r.module === m).map(r => r.dependency.type).sort())]));
setBailoutReason(module, (requestShortener) => {
const names = Array.from(importingModules).map(m => `${m.readableIdentifier(requestShortener)} (referenced with ${Array.from(importingModuleTypes.get(m)).join(", ")})`).sort();
return `Module is referenced from these modules with unsupported syntax: ${names.join(", ")}`;
});
continue;
}
@ -83,7 +90,7 @@ class ModuleConcatenationPlugin {
possibleInners.add(module);
}
// sort by depth
// modules with lower depth are more likly suited as roots
// modules with lower depth are more likely suited as roots
// this improves performance, because modules already selected as inner are skipped
relevantModules.sort((a, b) => {
return a.depth - b.depth;
@ -136,11 +143,11 @@ class ModuleConcatenationPlugin {
for(const warning of concatConfiguration.warnings) {
newModule.optimizationBailout.push((requestShortener) => {
const reason = getBailoutReason(warning[0], requestShortener);
const reasonPrefix = reason ? `: ${reason}` : "";
const reasonWithPrefix = reason ? ` (<- ${reason})` : "";
if(warning[0] === warning[1])
return `ModuleConcatenation: Cannot concat with ${warning[0].readableIdentifier(requestShortener)}${reasonPrefix}`;
return formatBailoutReason(`Cannot concat with ${warning[0].readableIdentifier(requestShortener)}${reasonWithPrefix}`);
else
return `ModuleConcatenation: Cannot concat with ${warning[0].readableIdentifier(requestShortener)} because of ${warning[1].readableIdentifier(requestShortener)}${reasonPrefix}`;
return formatBailoutReason(`Cannot concat with ${warning[0].readableIdentifier(requestShortener)} because of ${warning[1].readableIdentifier(requestShortener)}${reasonWithPrefix}`);
});
}
const chunks = concatConfiguration.rootModule.getChunks();

View File

@ -58,64 +58,61 @@ webpack.validate = validateSchema.bind(this, webpackOptionsSchema);
webpack.validateSchema = validateSchema;
webpack.WebpackOptionsValidationError = WebpackOptionsValidationError;
function exportPlugins(exports, path, plugins) {
plugins.forEach(name => {
Object.defineProperty(exports, name, {
function exportPlugins(obj, mappings) {
Object.keys(mappings).forEach(name => {
Object.defineProperty(obj, name, {
configurable: false,
enumerable: true,
get() {
return require(`${path}/${name}`);
}
get: mappings[name]
});
});
}
exportPlugins(exports, ".", [
"DefinePlugin",
"NormalModuleReplacementPlugin",
"ContextReplacementPlugin",
"IgnorePlugin",
"WatchIgnorePlugin",
"BannerPlugin",
"PrefetchPlugin",
"AutomaticPrefetchPlugin",
"ProvidePlugin",
"HotModuleReplacementPlugin",
"SourceMapDevToolPlugin",
"EvalSourceMapDevToolPlugin",
"EvalDevToolModulePlugin",
"CachePlugin",
"ExtendedAPIPlugin",
"ExternalsPlugin",
"JsonpTemplatePlugin",
"LibraryTemplatePlugin",
"LoaderTargetPlugin",
"MemoryOutputFileSystem",
"ProgressPlugin",
"SetVarMainTemplatePlugin",
"UmdMainTemplatePlugin",
"NoErrorsPlugin",
"NoEmitOnErrorsPlugin",
"NewWatchingPlugin",
"EnvironmentPlugin",
"DllPlugin",
"DllReferencePlugin",
"LoaderOptionsPlugin",
"NamedModulesPlugin",
"NamedChunksPlugin",
"HashedModuleIdsPlugin",
"ModuleFilenameHelpers"
]);
exportPlugins(exports.optimize = {}, "./optimize", [
"AggressiveMergingPlugin",
"AggressiveSplittingPlugin",
"CommonsChunkPlugin",
"ChunkModuleIdRangePlugin",
"DedupePlugin",
"LimitChunkCountPlugin",
"MinChunkSizePlugin",
"ModuleConcatenationPlugin",
"OccurrenceOrderPlugin",
"UglifyJsPlugin"
]);
exportPlugins(exports.dependencies = {}, "./dependencies", []);
exportPlugins(exports, {
"DefinePlugin": () => require("./DefinePlugin"),
"NormalModuleReplacementPlugin": () => require("./NormalModuleReplacementPlugin"),
"ContextReplacementPlugin": () => require("./ContextReplacementPlugin"),
"IgnorePlugin": () => require("./IgnorePlugin"),
"WatchIgnorePlugin": () => require("./WatchIgnorePlugin"),
"BannerPlugin": () => require("./BannerPlugin"),
"PrefetchPlugin": () => require("./PrefetchPlugin"),
"AutomaticPrefetchPlugin": () => require("./AutomaticPrefetchPlugin"),
"ProvidePlugin": () => require("./ProvidePlugin"),
"HotModuleReplacementPlugin": () => require("./HotModuleReplacementPlugin"),
"SourceMapDevToolPlugin": () => require("./SourceMapDevToolPlugin"),
"EvalSourceMapDevToolPlugin": () => require("./EvalSourceMapDevToolPlugin"),
"EvalDevToolModulePlugin": () => require("./EvalDevToolModulePlugin"),
"CachePlugin": () => require("./CachePlugin"),
"ExtendedAPIPlugin": () => require("./ExtendedAPIPlugin"),
"ExternalsPlugin": () => require("./ExternalsPlugin"),
"JsonpTemplatePlugin": () => require("./JsonpTemplatePlugin"),
"LibraryTemplatePlugin": () => require("./LibraryTemplatePlugin"),
"LoaderTargetPlugin": () => require("./LoaderTargetPlugin"),
"MemoryOutputFileSystem": () => require("./MemoryOutputFileSystem"),
"ProgressPlugin": () => require("./ProgressPlugin"),
"SetVarMainTemplatePlugin": () => require("./SetVarMainTemplatePlugin"),
"UmdMainTemplatePlugin": () => require("./UmdMainTemplatePlugin"),
"NoErrorsPlugin": () => require("./NoErrorsPlugin"),
"NoEmitOnErrorsPlugin": () => require("./NoEmitOnErrorsPlugin"),
"NewWatchingPlugin": () => require("./NewWatchingPlugin"),
"EnvironmentPlugin": () => require("./EnvironmentPlugin"),
"DllPlugin": () => require("./DllPlugin"),
"DllReferencePlugin": () => require("./DllReferencePlugin"),
"LoaderOptionsPlugin": () => require("./LoaderOptionsPlugin"),
"NamedModulesPlugin": () => require("./NamedModulesPlugin"),
"NamedChunksPlugin": () => require("./NamedChunksPlugin"),
"HashedModuleIdsPlugin": () => require("./HashedModuleIdsPlugin"),
"ModuleFilenameHelpers": () => require("./ModuleFilenameHelpers")
});
exportPlugins(exports.optimize = {}, {
"AggressiveMergingPlugin": () => require("./optimize/AggressiveMergingPlugin"),
"AggressiveSplittingPlugin": () => require("./optimize/AggressiveSplittingPlugin"),
"CommonsChunkPlugin": () => require("./optimize/CommonsChunkPlugin"),
"ChunkModuleIdRangePlugin": () => require("./optimize/ChunkModuleIdRangePlugin"),
"DedupePlugin": () => require("./optimize/DedupePlugin"),
"LimitChunkCountPlugin": () => require("./optimize/LimitChunkCountPlugin"),
"MinChunkSizePlugin": () => require("./optimize/MinChunkSizePlugin"),
"ModuleConcatenationPlugin": () => require("./optimize/ModuleConcatenationPlugin"),
"OccurrenceOrderPlugin": () => require("./optimize/OccurrenceOrderPlugin"),
"UglifyJsPlugin": () => require("./optimize/UglifyJsPlugin")
});

View File

@ -61,6 +61,7 @@ rules:
context: "continuous-integration/travis-ci/pr"
travis_job:
state: "failed"
allow_failure: false
config:
env: JOB_PART=test
fetch: travis_job.log

View File

@ -1,6 +1,6 @@
{
"name": "webpack",
"version": "3.3.0",
"version": "3.4.1",
"author": "Tobias Koppers @sokra",
"description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
"dependencies": {

View File

@ -743,7 +743,7 @@
}
]
},
"warning-filters-types": {
"filter-item-types": {
"anyOf": [
{
"instanceof": "RegExp"
@ -755,6 +755,19 @@
"instanceof": "Function"
}
]
},
"filter-types": {
"anyOf": [
{
"$ref": "#/definitions/filter-item-types"
},
{
"type": "array",
"items": {
"$ref": "#/definitions/filter-item-types"
}
}
]
}
},
"properties": {
@ -1009,17 +1022,19 @@
},
"warningsFilter": {
"description": "Suppress warnings that match the specified filters. Filters can be Strings, RegExps or Functions",
"anyOf": [
{
"type": "array",
"items": {
"$ref": "#/definitions/warning-filters-types"
}
},
{
"$ref": "#/definitions/warning-filters-types"
}
]
"$ref": "#/definitions/filter-types"
},
"excludeAssets": {
"description": "Suppress assets that match the specified filters. Filters can be Strings, RegExps or Functions",
"$ref": "#/definitions/filter-types"
},
"excludeModules": {
"description": "Suppress modules that match the specified filters. Filters can be Strings, RegExps or Functions",
"$ref": "#/definitions/filter-types"
},
"exclude": {
"description": "Please use excludeModules instead.",
"$ref": "#/definitions/filter-types"
},
"errorDetails": {
"type": "boolean",

View File

@ -7,12 +7,11 @@ const fs = require("fs");
const webpack = require("../");
describe("Examples", () => {
const examples = fs.readdirSync(path.join(__dirname, "..", "examples")).map((name) =>
path.join(__dirname, "..", "examples", name)).filter((p) =>
fs.statSync(p).isDirectory() && fs.existsSync(path.join(p, "build.js")));
const basePath = path.join(__dirname, "..", "examples");
const examples = require("../examples/examples.js");
examples.forEach((examplePath) => {
it("should compile " + path.basename(examplePath), function(done) {
it("should compile " + path.relative(basePath, examplePath), function(done) {
this.timeout(20000);
let options = {};
let webpackConfigPath = path.join(examplePath, "webpack.config.js");

View File

@ -15,7 +15,8 @@ describe("ExternalModule", function() {
type = "some-type";
externalModule = new ExternalModule(
request,
type
type,
`${type} ${request}`
);
});
describe("#identifier", function() {

View File

@ -116,6 +116,10 @@ describe("WatchTestCases", () => {
const watching = compiler.watch({
aggregateTimeout: 1000
}, (err, stats) => {
if(err)
return done(err);
if(!stats)
return done(new Error("No stats reported from Compiler"));
if(stats.hash === lastHash)
return;
lastHash = stats.hash;

View File

@ -0,0 +1 @@
}

View File

@ -0,0 +1,17 @@
"use strict";
module.exports = function testAssertions(code, stdout, stderr) {
code.should.be.eql(2);
stdout[0].should.containEql("Hash: ");
stdout[1].should.containEql("Version: ");
stdout[2].should.containEql("Time: ");
stdout[5].should.containEql("./index.js");
stdout[5].should.containEql("[built]");
stdout[5].should.containEql("[failed]");
stdout[5].should.containEql("[1 error]");
stdout[7].should.containEql("ERROR in ./index.js");
stdout[8].should.containEql("Module parse failed:");
stderr.should.be.empty();
};

View File

@ -0,0 +1,4 @@
module.exports = {
context: __dirname,
entry: "./index"
};

View File

@ -0,0 +1 @@
module.exports = 4;

View File

@ -0,0 +1,18 @@
it("should not bundle context requires with asyncMode === 'weak'", function() {
var contextRequire = require.context(".", false, /two/, "weak");
(function() {
contextRequire("./two")
}).should.throw(/not available/);
});
it("should find module with asyncMode === 'weak' when required elsewhere", function() {
var contextRequire = require.context(".", false, /.+/, "weak");
contextRequire("./three").should.be.eql(3);
require("./three"); // in a real app would be served as a separate chunk
});
it("should find module with asyncMode === 'weak' when required elsewhere (recursive)", function() {
var contextRequire = require.context(".", true, /.+/, "weak");
contextRequire("./dir/four").should.be.eql(4);
require("./dir/four"); // in a real app would be served as a separate chunk
});

View File

@ -0,0 +1 @@
module.exports = 3;

View File

@ -0,0 +1 @@
module.exports = 2;

View File

@ -0,0 +1 @@
export default "a";

View File

@ -0,0 +1 @@
export default "a";

View File

@ -0,0 +1 @@
export default "a";

View File

@ -0,0 +1 @@
export default "b";

View File

@ -0,0 +1 @@
export default "c";

View File

@ -0,0 +1 @@
export default "a";

View File

@ -0,0 +1 @@
export default "b";

View File

@ -0,0 +1 @@
export default "c";

View File

@ -1,41 +1,41 @@
it("should be able to use eager mode", function(done) {
function load(name) {
return import(/* webpackMode: "eager" */"./dir1/" + name);
return import(/* webpackMode: "eager" */ "./dir1/" + name);
}
testChunkLoading(load, true, true, done);
});
it("should be able to use lazy-once mode", function(done) {
function load(name) {
return import(/* webpackMode: "lazy-once" */"./dir2/" + name);
return import(/* webpackMode: "lazy-once" */ "./dir2/" + name);
}
testChunkLoading(load, false, true, done);
});
it("should be able to use lazy-once mode with name", function(done) {
function load(name) {
return import(/* webpackMode: "lazy-once", webpackChunkName: "name-lazy-once" */"./dir3/" + name);
return import(/* webpackMode: "lazy-once", webpackChunkName: "name-lazy-once" */ "./dir3/" + name);
}
testChunkLoading(load, false, true, done);
});
it("should be able to use lazy mode", function(done) {
function load(name) {
return import(/* webpackMode: "lazy" */"./dir4/" + name);
return import(/* webpackMode: "lazy" */ "./dir4/" + name);
}
testChunkLoading(load, false, false, done);
});
it("should be able to use lazy mode with name", function(done) {
function load(name) {
return import(/* webpackMode: "lazy", webpackChunkName: "name-lazy" */"./dir5/" + name);
return import(/* webpackMode: "lazy", webpackChunkName: "name-lazy" */ "./dir5/" + name);
}
testChunkLoading(load, false, false, done);
});
it("should be able to use lazy mode with name and placeholder", function(done) {
function load(name) {
return import(/* webpackMode: "lazy", webpackChunkName: "name-lazy-[request]" */"./dir6/" + name);
return import(/* webpackMode: "lazy", webpackChunkName: "name-lazy-[request]" */ "./dir6/" + name);
}
testChunkLoading(load, false, false, done);
});
@ -58,6 +58,52 @@ it("should be able to combine chunks by name", function(done) {
testChunkLoading(load, false, true, done);
});
it("should be able to use weak mode", function(done) {
function load(name) {
return import(/* webpackMode: "weak" */ "./dir8/" + name);
}
require("./dir8/a") // chunks served manually by the user
require("./dir8/b")
require("./dir8/c")
testChunkLoading(load, true, true, done);
});
it("should be able to use weak mode (without context)", function(done) {
function load(name) {
switch(name) {
case "a":
return import(/* webpackMode: "weak" */ "./dir9/a");
case "b":
return import(/* webpackMode: "weak" */ "./dir9/b");
case "c":
return import(/* webpackMode: "weak" */ "./dir9/c");
default:
throw new Error("Unexcepted test data");
}
}
require("./dir9/a") // chunks served manually by the user
require("./dir9/b")
require("./dir9/c")
testChunkLoading(load, true, true, done);
});
it("should not find module when mode is weak and chunk not served elsewhere", function(done) {
var name = "a";
import(/* webpackMode: "weak" */ "./dir10/" + name)
.catch(function(e) {
e.should.match(/not available/);
done();
})
});
it("should not find module when mode is weak and chunk not served elsewhere (without context)", function(done) {
import(/* webpackMode: "weak" */ "./dir11/a")
.catch(function(e) {
e.should.match(/not available/);
done();
})
});
function testChunkLoading(load, expectedSyncInitial, expectedSyncRequested, done) {
var sync = false;
var syncInitial = true;

View File

@ -0,0 +1,24 @@
it("should not include a module with a weak dependency using context", function() {
var fileA = "a";
var fileB = "b";
var fileC = "c";
var resolveWeakA = require.resolveWeak("./" + fileA);
var resolveWeakB = require.resolveWeak("./" + fileB);
var resolveWeakC = require.resolveWeak("./" + fileC);
var a = !!__webpack_modules__[resolveWeakA];
var b = !!__webpack_modules__[resolveWeakB];
var c = !!__webpack_modules__[resolveWeakC];
require(["./b"]);
require("./c");
resolveWeakA.should.exist;
resolveWeakB.should.exist;
resolveWeakC.should.exist;
a.should.be.eql(false);
b.should.be.eql(false);
c.should.be.eql(true);
});

View File

@ -5,9 +5,10 @@ it("should inject the module object into a chunk (AMD1)", function(done) {
});
});
it("should inject the module object into a chunk (AMD2)"/*, function() {
it("should inject the module object into a chunk (AMD2)", function() {
require([module.webpackPolyfill ? "./x1" : "./fail"]);
}*/);
module.webpackPolyfill.should.be.eql(1);
});
it("should inject the module object into a chunk (ensure)", function(done) {
require.ensure([], function(require) {

View File

@ -0,0 +1 @@
module.exports = module.id;

View File

@ -0,0 +1,6 @@
it("should be able to use require.resolveWeak with expression", function() {
var expr = "file";
var id = require.resolveWeak("./dir/" + expr);
id.should.be.eql(require("./dir/file.js"));
});

View File

@ -0,0 +1 @@
module.exports = "a";

View File

@ -0,0 +1 @@
module.exports = "b";

View File

@ -0,0 +1 @@
module.exports = "c";

View File

@ -0,0 +1,22 @@
it("should load the full async commons", function(done) {
require.ensure(["./a"], function(require) {
require("./a").should.be.eql("a");
done();
});
});
it("should load a chunk with async commons (AMD)", function(done) {
require(["./a", "./b"], function(a, b) {
a.should.be.eql("a");
b.should.be.eql("b");
done();
});
});
it("should load a chunk with async commons (require.ensure)", function(done) {
require.ensure([], function(require) {
require("./a").should.be.eql("a");
require("./c").should.be.eql("c");
done();
});
});

View File

@ -0,0 +1,9 @@
var webpack = require("../../../../");
module.exports = {
plugins: [
new webpack.optimize.CommonsChunkPlugin({
async: true
})
]
};

View File

@ -0,0 +1,3 @@
module.exports = function(req) {
return ["a", "b", "c"][req];
};

View File

@ -0,0 +1 @@
module.exports = ["a", "b", "c", "d", "e"];

View File

@ -0,0 +1,7 @@
it("should delegate the modules", function() {
require("./a").should.be.eql("a");
require("./loader!./b").should.be.eql("b");
require("./dir/c").should.be.eql("c");
require("./d").should.be.eql("d");
require("./e").should.be.eql("e");
});

View File

@ -0,0 +1,26 @@
var DelegatedPlugin = require("../../../../lib/DelegatedPlugin");
var HashedModuleIdsPlugin = require("../../../../lib/HashedModuleIdsPlugin");
module.exports = {
plugins: [
new HashedModuleIdsPlugin(),
new DelegatedPlugin({
source: "./bundle",
type: "require",
context: __dirname,
content: {
"./a.js": { id: 0 },
"./loader.js!./b.js": { id: 1 },
"./dir/c.js": { id: 2 }
}
}),
new DelegatedPlugin({
source: "./bundle2",
type: "object",
context: __dirname,
content: {
"./d.js": { id: 3 },
"./e.js": { id: 4 }
}
})
]
};

View File

@ -32,3 +32,19 @@ it("should load an harmony module from dll (star export)", function() {
it("should load a module with loader applied", function() {
require("dll/g.abc.js").should.be.eql("number");
});
it("should give modules the correct ids", function() {
Object.keys(__webpack_modules__).filter(m => !m.startsWith("../..")).should.be.eql([
"./e.js",
"./index.js",
"dll-reference ../0-create-dll/dll.js",
"dll/a.js",
"dll/b.js",
"dll/d.js",
"dll/e.js",
"dll/e1.js",
"dll/e2.js",
"dll/f.jsx",
"dll/g.abc.js"
]);
});

View File

@ -7,6 +7,10 @@ it("should load a module from dll", function() {
require("../0-create-dll/a").should.be.eql("a");
});
it("should load a module of non-default type without extension from dll", function() {
require("../0-create-dll/f").should.be.eql("f");
});
it("should load an async module from dll", function(done) {
require("../0-create-dll/b")().then(function(c) {
c.should.be.eql({ default: "c" });
@ -27,4 +31,20 @@ it("should load an harmony module from dll (star export)", function() {
it("should load a module with loader applied", function() {
require("../0-create-dll/g.abc.js").should.be.eql("number");
})
});
it("should give modules the correct ids", function() {
Object.keys(__webpack_modules__).filter(m => !m.startsWith("../..")).should.be.eql([
"../0-create-dll/a.js",
"../0-create-dll/b.js",
"../0-create-dll/d.js",
"../0-create-dll/e.js",
"../0-create-dll/e1.js",
"../0-create-dll/e2.js",
"../0-create-dll/f.jsx",
"../0-create-dll/g.abc.js",
"./e.js",
"./index.js",
"dll-reference ../0-create-dll/dll.js"
]);
});

View File

@ -15,6 +15,9 @@ module.exports = {
] }
]
},
resolve: {
extensions: [".js", ".jsx"]
},
plugins: [
new webpack.DllReferencePlugin({
manifest: require("../../../js/config/dll-plugin/manifest0.json"), // eslint-disable-line node/no-missing-require

View File

@ -0,0 +1,2 @@
export * from "../0-create-dll/e1";
export * from "../0-create-dll/e2";

View File

@ -0,0 +1,2 @@
export * from "dll/e1";
export * from "dll/e2";

View File

@ -0,0 +1,32 @@
var should = require("should");
import d from "../0-create-dll/d";
import { x1, y2 } from "./e";
import { x2, y1 } from "../0-create-dll/e";
it("should load a module from dll", function() {
require("../0-create-dll/a").should.be.eql("a");
});
it("should load an async module from dll", function(done) {
require("../0-create-dll/b")().then(function(c) {
c.should.be.eql({ default: "c" });
done();
}).catch(done);
});
it("should load an harmony module from dll (default export)", function() {
d.should.be.eql("d");
});
it("should load an harmony module from dll (star export)", function() {
x1.should.be.eql(123);
x2.should.be.eql(123);
y1.should.be.eql(456);
y2.should.be.eql(456);
});
it("should load a module with loader applied", function() {
require("../0-create-dll/g.abc.js").should.be.eql("number");
});

View File

@ -0,0 +1,27 @@
var path = require("path");
var webpack = require("../../../../");
module.exports = {
module: {
rules: [
{ oneOf: [
{
test: /\.abc\.js$/,
loader: "../0-create-dll/g-loader.js",
options: {
test: 1
}
}
] }
]
},
plugins: [
new webpack.DllReferencePlugin({
manifest: require("../../../js/config/dll-plugin/manifest0.json"), // eslint-disable-line node/no-missing-require
name: "../0-create-dll/dll.js",
context: path.resolve(__dirname, "../0-create-dll"),
sourceType: "commonjs2"
}),
new webpack.HashedModuleIdsPlugin(),
]
};

View File

@ -0,0 +1,5 @@
import value from "dll/module";
it("should not scope hoist delegated modules", function() {
value.should.be.eql("ok");
});

View File

@ -0,0 +1,19 @@
var webpack = require("../../../../");
module.exports = {
plugins: [
new webpack.DllReferencePlugin({
name: "function(id) { return {default: 'ok'}; }",
scope: "dll",
content: {
"./module": {
id: 1,
meta: {
harmonyModule: true
},
exports: ["default"]
}
}
}),
new webpack.optimize.ModuleConcatenationPlugin()
]
};

View File

@ -0,0 +1 @@
module.exports = "a";

View File

@ -0,0 +1 @@
module.exports = "b";

View File

@ -0,0 +1 @@
module.exports = "c";

View File

@ -0,0 +1,14 @@
chunk {0} 0.js 21 bytes {3} [rendered]
> async commons [1] (webpack)/test/statsCases/async-commons-chunk-all-selected/index.js 2:1-5:3
> async commons [1] (webpack)/test/statsCases/async-commons-chunk-all-selected/index.js 9:1-13:3
> async commons [1] (webpack)/test/statsCases/async-commons-chunk-all-selected/index.js 17:1-21:3
[0] (webpack)/test/statsCases/async-commons-chunk-all-selected/a.js 21 bytes {0} [built]
chunk {1} 1.js 21 bytes {3} [rendered]
> [1] (webpack)/test/statsCases/async-commons-chunk-all-selected/index.js 17:1-21:3
[3] (webpack)/test/statsCases/async-commons-chunk-all-selected/c.js 21 bytes {1} [built]
chunk {2} 2.js 21 bytes {3} [rendered]
> [1] (webpack)/test/statsCases/async-commons-chunk-all-selected/index.js 9:1-13:3
[2] (webpack)/test/statsCases/async-commons-chunk-all-selected/b.js 21 bytes {2} [built]
chunk {3} entry.js (entry) 550 bytes [entry] [rendered]
> entry [1] (webpack)/test/statsCases/async-commons-chunk-all-selected/index.js
[1] (webpack)/test/statsCases/async-commons-chunk-all-selected/index.js 550 bytes {3} [built]

View File

@ -0,0 +1,22 @@
it("should load the full async commons", function(done) {
require.ensure(["./a"], function(require) {
require("./a").should.be.eql("a");
done();
});
});
it("should load a chunk with async commons (AMD)", function(done) {
require(["./a", "./b"], function(a, b) {
a.should.be.eql("a");
b.should.be.eql("b");
done();
});
});
it("should load a chunk with async commons (require.ensure)", function(done) {
require.ensure([], function(require) {
require("./a").should.be.eql("a");
require("./c").should.be.eql("c");
done();
});
});

View File

@ -0,0 +1,20 @@
var webpack = require("../../../");
module.exports = {
entry: {
entry: "./"
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
async: true
})
],
stats: {
hash: false,
timings: false,
assets: false,
chunks: true,
chunkOrigins: true,
modules: false
}
};

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