Merge branch 'main' into cspell-globs

This commit is contained in:
Tobias Koppers 2022-01-18 10:40:25 +01:00
commit 313e416bd2
193 changed files with 6598 additions and 778 deletions

1
.gitattributes vendored
View File

@ -3,4 +3,5 @@ test/statsCases/** eol=lf
examples/* eol=lf
bin/* eol=lf
*.svg eol=lf
*.css eol=lf
**/*webpack.lock.data/** -text

View File

@ -1,74 +0,0 @@
dist: trusty
language: node_js
branches:
only:
- webpack-4
- main
- next
- dev-1
cache:
yarn: true
directories:
- ".jest-cache"
- ".eslintcache"
stages:
- basic
- advanced
matrix:
include:
- os: linux
node_js: "12"
env: NO_WATCH_TESTS=1 JEST="--maxWorkers=2 --cacheDirectory .jest-cache" JOB_PART=basic
stage: basic
- os: linux
node_js: "12"
env: NO_WATCH_TESTS=1 JEST="--maxWorkers=2 --cacheDirectory .jest-cache" JOB_PART=lintunit
stage: advanced
- os: linux
node_js: "12"
env: NO_WATCH_TESTS=1 JEST="--maxWorkers=2 --cacheDirectory .jest-cache" JOB_PART=integration
stage: advanced
- os: linux
node_js: "12"
env: NO_WATCH_TESTS=1 ALTERNATIVE_SORT=1 JEST="--maxWorkers=2 --cacheDirectory .jest-cache" JOB_PART=integration
stage: advanced
- os: linux
node_js: "10"
env:
- NODEJS_VERSION=v15.0.0-nightly2020082003293aa3a1
- YARN_EXTRA_ARGS="--ignore-engines"
- NO_WATCH_TESTS=1
- JEST="--maxWorkers=2 --cacheDirectory .jest-cache"
- JOB_PART=integration
stage: advanced
fast_finish: true
before_install:
- |
if [ "$NODEJS_VERSION" != "" ];
then
mkdir /opt/node
curl --silent "https://nodejs.org/download/nightly/$NODEJS_VERSION/node-$NODEJS_VERSION-linux-x64.tar.gz" | tar -zxf - --directory /opt/node
export PATH="/opt/node/node-$NODEJS_VERSION-linux-x64/bin:$PATH"
node --version
fi
install:
- yarn --frozen-lockfile $YARN_EXTRA_ARGS
- yarn link --frozen-lockfile $YARN_EXTRA_ARGS || true
- yarn link webpack --frozen-lockfile $YARN_EXTRA_ARGS
script: yarn travis:$JOB_PART
after_success:
- cat ./coverage/lcov.info | node_modules/.bin/coveralls --verbose
- bash <(curl -s https://codecov.io/bash) -F $JOB_PART -X gcov
- rm -f .jest-cache/haste-map* .jest-cache/perf-cache*
notifications:
slack:
secure: JduSdKWwbnLCwo7Z4E59SGE+Uw832UwnXzQiKEpg1BV45MYDPRiGltly1tRHmPh9OGjvGx3XSkC2tNGOBLtL4UL2SCkf012x0t7jDutKRfcv/njynl8jk8l+UhPmaWiHXDQAgGiiKdL4RfzPLW3HeVHCOWm0LKMzcarTa8tw+rE=

View File

@ -95,7 +95,7 @@ export type LibraryExport = string[] | string;
*/
export type LibraryName = string[] | string | LibraryCustomUmdObject;
/**
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
*/
export type LibraryType =
| (
@ -110,6 +110,7 @@ export type LibraryType =
| "commonjs"
| "commonjs2"
| "commonjs-module"
| "commonjs-static"
| "amd"
| "amd-require"
| "umd"
@ -189,6 +190,7 @@ export type ExternalsType =
| "commonjs"
| "commonjs2"
| "commonjs-module"
| "commonjs-static"
| "amd"
| "amd-require"
| "umd"
@ -443,6 +445,14 @@ export type CompareBeforeEmit = boolean;
* This option enables cross-origin loading of chunks.
*/
export type CrossOriginLoading = false | "anonymous" | "use-credentials";
/**
* Specifies the filename template of non-initial output css files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
export type CssChunkFilename = FilenameTemplate;
/**
* Specifies the filename template of output css files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
export type CssFilename = FilenameTemplate;
/**
* Similar to `output.devtoolModuleFilenameTemplate`, but used in the case of duplicate module identifiers.
*/
@ -1077,7 +1087,7 @@ export interface LibraryOptions {
*/
name?: LibraryName;
/**
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
*/
type: LibraryType;
/**
@ -1976,6 +1986,14 @@ export interface Output {
* This option enables cross-origin loading of chunks.
*/
crossOriginLoading?: CrossOriginLoading;
/**
* Specifies the filename template of non-initial output css files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
cssChunkFilename?: CssChunkFilename;
/**
* Specifies the filename template of output css files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
cssFilename?: CssFilename;
/**
* Similar to `output.devtoolModuleFilenameTemplate`, but used in the case of duplicate module identifiers.
*/
@ -2061,7 +2079,7 @@ export interface Output {
*/
libraryExport?: LibraryExport;
/**
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
*/
libraryTarget?: LibraryType;
/**
@ -2692,6 +2710,14 @@ export interface AssetResourceGeneratorOptions {
*/
publicPath?: RawPublicPath;
}
/**
* Generator options for css modules.
*/
export interface CssGeneratorOptions {}
/**
* Parser options for css modules.
*/
export interface CssParserOptions {}
/**
* No generator options are supported for this module type.
*/
@ -2770,6 +2796,10 @@ export interface ExperimentsCommon {
* Enable additional in memory caching of modules that are unchanged and reference only unchanged modules.
*/
cacheUnaffected?: boolean;
/**
* Enable css support.
*/
css?: boolean;
/**
* Apply defaults of next major version.
*/
@ -3112,6 +3142,14 @@ export interface OutputNormalized {
* This option enables cross-origin loading of chunks.
*/
crossOriginLoading?: CrossOriginLoading;
/**
* Specifies the filename template of non-initial output css files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
cssChunkFilename?: CssChunkFilename;
/**
* Specifies the filename template of output css files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
cssFilename?: CssFilename;
/**
* Similar to `output.devtoolModuleFilenameTemplate`, but used in the case of duplicate module identifiers.
*/

View File

@ -29,7 +29,7 @@ export type LibraryExport = string[] | string;
*/
export type LibraryName = string[] | string | LibraryCustomUmdObject;
/**
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
*/
export type LibraryType =
| (
@ -44,6 +44,7 @@ export type LibraryType =
| "commonjs"
| "commonjs2"
| "commonjs-module"
| "commonjs-static"
| "amd"
| "amd-require"
| "umd"
@ -126,7 +127,7 @@ export interface LibraryOptions {
*/
name?: LibraryName;
/**
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
*/
type: LibraryType;
/**

View File

@ -18,6 +18,7 @@ export type ExternalsType =
| "commonjs"
| "commonjs2"
| "commonjs-module"
| "commonjs-static"
| "amd"
| "amd-require"
| "umd"

View File

@ -29,7 +29,7 @@ export type LibraryExport = string[] | string;
*/
export type LibraryName = string[] | string | LibraryCustomUmdObject;
/**
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
*/
export type LibraryType =
| (
@ -44,6 +44,7 @@ export type LibraryType =
| "commonjs"
| "commonjs2"
| "commonjs-module"
| "commonjs-static"
| "amd"
| "amd-require"
| "umd"
@ -70,6 +71,7 @@ export type ExternalsType =
| "commonjs"
| "commonjs2"
| "commonjs-module"
| "commonjs-static"
| "amd"
| "amd-require"
| "umd"
@ -182,7 +184,7 @@ export interface LibraryOptions {
*/
name?: LibraryName;
/**
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
* Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).
*/
type: LibraryType;
/**

536
examples/css/README.md Normal file
View File

@ -0,0 +1,536 @@
# example.js
```javascript
import "./style.css";
import "./style2.css";
import { main } from "./style.module.css";
import("./lazy-style.css");
document.getElementsByTagName("main")[0].className = main;
```
# style.css
```javascript
@import "style-imported.css";
@import "https://fonts.googleapis.com/css?family=Open+Sans";
body {
background: green;
font-family: "Open Sans";
}
```
# dist/output.js
```javascript
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ 3:
/*!*************************!*\
!*** ./images/file.png ***!
\*************************/
/*! default exports */
/*! exports [not provided] [no usage info] */
/*! runtime requirements: module, __webpack_require__.p, __webpack_require__.* */
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
module.exports = __webpack_require__.p + "89a353e9c515885abd8e.png";
/***/ })
/******/ });
```
<details><summary><code>/* webpack runtime code */</code></summary>
``` js
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = __webpack_modules__;
/******/
/************************************************************************/
/******/ /* webpack/runtime/ensure chunk */
/******/ (() => {
/******/ __webpack_require__.f = {};
/******/ // This file contains only the entry chunk.
/******/ // The chunk loading function for additional chunks
/******/ __webpack_require__.e = (chunkId) => {
/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
/******/ __webpack_require__.f[key](chunkId, promises);
/******/ return promises;
/******/ }, []));
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/get css chunk filename */
/******/ (() => {
/******/ // This function allow to reference async chunks
/******/ __webpack_require__.k = (chunkId) => {
/******/ // return url for filenames based on template
/******/ return "" + chunkId + ".output.css";
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/get javascript chunk filename */
/******/ (() => {
/******/ // This function allow to reference async chunks
/******/ __webpack_require__.u = (chunkId) => {
/******/ // return url for filenames based on template
/******/ return "" + chunkId + ".output.js";
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/load script */
/******/ (() => {
/******/ var inProgress = {};
/******/ var dataWebpackPrefix = "app:";
/******/ // loadScript function to load a script via script tag
/******/ __webpack_require__.l = (url, done, key, chunkId) => {
/******/ if(inProgress[url]) { inProgress[url].push(done); return; }
/******/ var script, needAttach;
/******/ if(key !== undefined) {
/******/ var scripts = document.getElementsByTagName("script");
/******/ for(var i = 0; i < scripts.length; i++) {
/******/ var s = scripts[i];
/******/ if(s.getAttribute("src") == url || s.getAttribute("data-webpack") == dataWebpackPrefix + key) { script = s; break; }
/******/ }
/******/ }
/******/ if(!script) {
/******/ needAttach = true;
/******/ script = document.createElement('script');
/******/
/******/ script.charset = 'utf-8';
/******/ script.timeout = 120;
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/ }
/******/ script.setAttribute("data-webpack", dataWebpackPrefix + key);
/******/ script.src = url;
/******/ }
/******/ inProgress[url] = [done];
/******/ var onScriptComplete = (prev, event) => {
/******/ // avoid mem leaks in IE.
/******/ script.onerror = script.onload = null;
/******/ clearTimeout(timeout);
/******/ var doneFns = inProgress[url];
/******/ delete inProgress[url];
/******/ script.parentNode && script.parentNode.removeChild(script);
/******/ doneFns && doneFns.forEach((fn) => (fn(event)));
/******/ if(prev) return prev(event);
/******/ }
/******/ ;
/******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);
/******/ script.onerror = onScriptComplete.bind(null, script.onerror);
/******/ script.onload = onScriptComplete.bind(null, script.onload);
/******/ needAttach && document.head.appendChild(script);
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/publicPath */
/******/ (() => {
/******/ __webpack_require__.p = "dist/";
/******/ })();
/******/
/******/ /* webpack/runtime/css loading */
/******/ (() => {
/******/ // object to store loaded and loading chunks
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
/******/ var installedChunks = {};
/******/
/******/ var uniqueName = "app";
/******/ var loadCssChunkData = (target, link, chunkId) => {
/******/ var data, token = "", token2, exports = {}, exportsWithId = [], exportsWithDashes = [], i = 0, cc = 1;
/******/ try { if(!link) link = loadStylesheet(chunkId); data = link.sheet.cssRules; data = data[data.length - 1].style; } catch(e) { data = getComputedStyle(document.head); }
/******/ data = data.getPropertyValue("--webpack-" + uniqueName + "-" + chunkId);
/******/ if(!data) return [];
/******/ for(; cc; i++) {
/******/ cc = data.charCodeAt(i);
/******/ if(cc == 40) { token2 = token; token = ""; }
/******/ else if(cc == 41) { exports[token2.replace(/^_/, "")] = token.replace(/^_/, ""); token = ""; }
/******/ else if(cc == 47 || cc == 37) { token = token.replace(/^_/, ""); exports[token] = token; exportsWithId.push(token); if(cc == 37) exportsWithDashes.push(token); token = ""; }
/******/ else if(!cc || cc == 44) { token = token.replace(/^_/, ""); exportsWithId.forEach((x) => (exports[x] = uniqueName + "-" + token + "-" + exports[x])); exportsWithDashes.forEach((x) => (exports[x] = "--" + exports[x])); __webpack_require__.r(exports); target[token] = ((exports, module) => {
/******/ module.exports = exports;
/******/ }).bind(null, exports); token = ""; exports = {}; exportsWithId.length = 0; }
/******/ else if(cc == 92) { token += data[++i] }
/******/ else { token += data[i]; }
/******/ }
/******/ installedChunks[chunkId] = 0;
/******/
/******/ }
/******/ var loadingAttribute = "data-webpack-loading";
/******/ var loadStylesheet = (chunkId, url, done) => {
/******/ var link, needAttach, key = "chunk-" + chunkId;
/******/
/******/ var links = document.getElementsByTagName("link");
/******/ for(var i = 0; i < links.length; i++) {
/******/ var l = links[i];
/******/ if(l.rel == "stylesheet" && (l.href == url || l.getAttribute("href") == url || l.getAttribute("data-webpack") == uniqueName + ":" + key)) { link = l; break; }
/******/ }
/******/ if(!done) return link;
/******/
/******/ if(!link) {
/******/ needAttach = true;
/******/ link = document.createElement('link');
/******/ link.setAttribute("data-webpack", uniqueName + ":" + key);
/******/ link.setAttribute(loadingAttribute, 1);
/******/ link.rel = "stylesheet";
/******/ link.href = url;
/******/ }
/******/ var onLinkComplete = (prev, event) => {
/******/ link.onerror = link.onload = null;
/******/ link.removeAttribute(loadingAttribute);
/******/ clearTimeout(timeout);
/******/ if(event && event.type != "load") link.parentNode.removeChild(link)
/******/ done(event);
/******/ if(prev) return prev(event);
/******/ };
/******/ if(link.getAttribute(loadingAttribute)) {
/******/ var timeout = setTimeout(onLinkComplete.bind(null, undefined, { type: 'timeout', target: link }), 120000);
/******/ link.onerror = onLinkComplete.bind(null, link.onerror);
/******/ link.onload = onLinkComplete.bind(null, link.onload);
/******/ } else onLinkComplete(undefined, { type: 'load', target: link });
/******/
/******/ needAttach && document.head.appendChild(link);
/******/ return link;
/******/ };
/******/ loadCssChunkData(__webpack_require__.m, 0, 0);
/******/
/******/ __webpack_require__.f.css = (chunkId, promises) => {
/******/ // css chunk loading
/******/ var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;
/******/ if(installedChunkData !== 0) { // 0 means "already installed".
/******/
/******/ // a Promise means "currently loading".
/******/ if(installedChunkData) {
/******/ promises.push(installedChunkData[2]);
/******/ } else {
/******/ if(true) { // all chunks have CSS
/******/ // setup Promise in chunk cache
/******/ var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));
/******/ promises.push(installedChunkData[2] = promise);
/******/
/******/ // start chunk loading
/******/ var url = __webpack_require__.p + __webpack_require__.k(chunkId);
/******/ // create error before stack unwound to get useful stacktrace later
/******/ var error = new Error();
/******/ var loadingEnded = (event) => {
/******/ if(__webpack_require__.o(installedChunks, chunkId)) {
/******/ installedChunkData = installedChunks[chunkId];
/******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined;
/******/ if(installedChunkData) {
/******/ if(event.type !== "load") {
/******/ var errorType = event && event.type;
/******/ var realSrc = event && event.target && event.target.src;
/******/ error.message = 'Loading css chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
/******/ error.name = 'ChunkLoadError';
/******/ error.type = errorType;
/******/ error.request = realSrc;
/******/ installedChunkData[1](error);
/******/ } else {
/******/ loadCssChunkData(__webpack_require__.m, link, chunkId);
/******/ installedChunkData[0]();
/******/ }
/******/ }
/******/ }
/******/ };
/******/ var link = loadStylesheet(chunkId, url, loadingEnded);
/******/ } else installedChunks[chunkId] = 0;
/******/ }
/******/ }
/******/ };
/******/
/******/ // no hmr
/******/ })();
/******/
/******/ /* webpack/runtime/jsonp chunk loading */
/******/ (() => {
/******/ // no baseURI
/******/
/******/ // object to store loaded and loading chunks
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
/******/ var installedChunks = {
/******/ 0: 0
/******/ };
/******/
/******/ __webpack_require__.f.j = (chunkId, promises) => {
/******/ // JSONP chunk loading for javascript
/******/ var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;
/******/ if(installedChunkData !== 0) { // 0 means "already installed".
/******/
/******/ // a Promise means "currently loading".
/******/ if(installedChunkData) {
/******/ promises.push(installedChunkData[2]);
/******/ } else {
/******/ if(0 == chunkId) {
/******/ // setup Promise in chunk cache
/******/ var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));
/******/ promises.push(installedChunkData[2] = promise);
/******/
/******/ // start chunk loading
/******/ var url = __webpack_require__.p + __webpack_require__.u(chunkId);
/******/ // create error before stack unwound to get useful stacktrace later
/******/ var error = new Error();
/******/ var loadingEnded = (event) => {
/******/ if(__webpack_require__.o(installedChunks, chunkId)) {
/******/ installedChunkData = installedChunks[chunkId];
/******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined;
/******/ if(installedChunkData) {
/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type);
/******/ var realSrc = event && event.target && event.target.src;
/******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
/******/ error.name = 'ChunkLoadError';
/******/ error.type = errorType;
/******/ error.request = realSrc;
/******/ installedChunkData[1](error);
/******/ }
/******/ }
/******/ };
/******/ __webpack_require__.l(url, loadingEnded, "chunk-" + chunkId, chunkId);
/******/ } else installedChunks[chunkId] = 0;
/******/ }
/******/ }
/******/ };
/******/
/******/ // no prefetching
/******/
/******/ // no preloaded
/******/
/******/ // no HMR
/******/
/******/ // no HMR manifest
/******/
/******/ // no on chunks loaded
/******/
/******/ // install a JSONP callback for chunk loading
/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
/******/ var [chunkIds, moreModules, runtime] = data;
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0;
/******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
/******/ for(moduleId in moreModules) {
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if(runtime) var result = runtime(__webpack_require__);
/******/ }
/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
/******/ installedChunks[chunkId][0]();
/******/ }
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/
/******/ }
/******/
/******/ var chunkLoadingGlobal = self["webpackChunkapp"] = self["webpackChunkapp"] || [];
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
/******/ })();
/******/
/************************************************************************/
```
</details>
``` js
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {
/*!********************!*\
!*** ./example.js ***!
\********************/
/*! namespace exports */
/*! exports [not provided] [no usage info] */
/*! runtime requirements: __webpack_require__, __webpack_require__.r, __webpack_exports__, __webpack_require__.e, __webpack_require__.* */
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _style_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./style.css */ 1);
/* harmony import */ var _style2_css__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./style2.css */ 5);
/* harmony import */ var _style_module_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./style.module.css */ 6);
__webpack_require__.e(/*! import() */ 1).then(__webpack_require__.bind(__webpack_require__, /*! ./lazy-style.css */ 7));
document.getElementsByTagName("main")[0].className = _style_module_css__WEBPACK_IMPORTED_MODULE_2__.main;
})();
/******/ })()
;
```
# dist/output.css
```javascript
@import url("https://fonts.googleapis.com/css?family=Open+Sans");
.img {
width: 150px;
height: 150px;
background: url(89a353e9c515885abd8e.png);
}
body {
background: green;
font-family: "Open Sans";
}
body {
background: red;
}
:root {
--app-6-large: 72px;
}
.app-6-main {
font-size: var(--app-6-large);
color: darkblue;
}
head{--webpack-app-0:_4,_2,_1,_5,large%main/_6;}
```
## production
```javascript
@import url("https://fonts.googleapis.com/css?family=Open+Sans");
.img {
width: 150px;
height: 150px;
background: url(89a353e9c515885abd8e.png);
}
body {
background: green;
font-family: "Open Sans";
}
body {
background: red;
}
:root {
--app-491-b: 72px;
}
.app-491-D {
font-size: var(--app-491-b);
color: darkblue;
}
head{--webpack-app-179:_548,_431,_258,_268,b%D/_491;}
```
# dist/1.output.css
```javascript
body {
color: blue;
}
head{--webpack-app-1:_7;}
```
# Info
## Unoptimized
```
assets by chunk 16.9 KiB (name: main)
asset output.js 16.5 KiB [emitted] (name: main)
asset output.css 385 bytes [emitted] (name: main)
asset 89a353e9c515885abd8e.png 14.6 KiB [emitted] [immutable] [from: images/file.png] (auxiliary name: main)
asset 1.output.css 49 bytes [emitted]
Entrypoint main 16.9 KiB (14.6 KiB) = output.js 16.5 KiB output.css 385 bytes 1 auxiliary asset
chunk (runtime: main) output.js, output.css (main) 218 bytes (javascript) 335 bytes (css) 14.6 KiB (asset) 42 bytes (css-import) 10 KiB (runtime) [entry] [rendered]
> ./example.js main
runtime modules 10 KiB 9 modules
dependent modules 42 bytes (javascript) 14.6 KiB (asset) 335 bytes (css) 42 bytes (css-import) [dependent] 6 modules
./example.js 176 bytes [built] [code generated]
[no exports]
[used exports unknown]
entry ./example.js main
chunk (runtime: main) 1.output.css 23 bytes
> ./lazy-style.css ./example.js 4:0-26
./lazy-style.css 23 bytes [built] [code generated]
[no exports]
[used exports unknown]
import() ./lazy-style.css ./example.js 4:0-26
webpack 5.66.0 compiled successfully
```
## Production mode
```
assets by chunk 4.25 KiB (name: main)
asset output.js 3.87 KiB [emitted] [minimized] (name: main)
asset output.css 385 bytes [emitted] (name: main)
asset 89a353e9c515885abd8e.png 14.6 KiB [emitted] [immutable] [from: images/file.png] (auxiliary name: main)
asset 159.output.css 53 bytes [emitted]
Entrypoint main 4.25 KiB (14.6 KiB) = output.js 3.87 KiB output.css 385 bytes 1 auxiliary asset
chunk (runtime: main) 159.output.css 23 bytes
> ./lazy-style.css ./example.js 4:0-26
./lazy-style.css 23 bytes [built] [code generated]
[no exports]
import() ./lazy-style.css ./example.js 4:0-26
chunk (runtime: main) output.js, output.css (main) 218 bytes (javascript) 335 bytes (css) 14.6 KiB (asset) 42 bytes (css-import) 10 KiB (runtime) [entry] [rendered]
> ./example.js main
runtime modules 10 KiB 9 modules
dependent modules 42 bytes (javascript) 14.6 KiB (asset) 335 bytes (css) 42 bytes (css-import) [dependent] 6 modules
./example.js 176 bytes [built] [code generated]
[no exports]
[no exports used]
entry ./example.js main
webpack 5.66.0 compiled successfully
```

1
examples/css/build.js Normal file
View File

@ -0,0 +1 @@
require("../build-common");

6
examples/css/example.js Normal file
View File

@ -0,0 +1,6 @@
import "./style.css";
import "./style2.css";
import { main } from "./style.module.css";
import("./lazy-style.css");
document.getElementsByTagName("main")[0].className = main;

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

10
examples/css/index.html Normal file
View File

@ -0,0 +1,10 @@
<html>
<head>
<link rel="stylesheet" href="dist/output.css" data-webpack="app:chunk-0" />
</head>
<body>
<main>Hello World</main>
<p class="img"></p>
<script src="dist/output.js"></script>
</body>
</html>

View File

@ -0,0 +1,3 @@
body {
color: blue;
}

View File

@ -0,0 +1,5 @@
.img {
width: 150px;
height: 150px;
background: url("./images/file.png");
}

7
examples/css/style.css Normal file
View File

@ -0,0 +1,7 @@
@import "style-imported.css";
@import "https://fonts.googleapis.com/css?family=Open+Sans";
body {
background: green;
font-family: "Open Sans";
}

View File

@ -0,0 +1,8 @@
:root {
--large: 72px;
}
.main {
font-size: var(--large);
color: darkblue;
}

3
examples/css/style2.css Normal file
View File

@ -0,0 +1,3 @@
body {
background: red;
}

49
examples/css/template.md Normal file
View File

@ -0,0 +1,49 @@
# example.js
```javascript
_{{example.js}}_
```
# style.css
```javascript
_{{style.css}}_
```
# dist/output.js
```javascript
_{{dist/output.js}}_
```
# dist/output.css
```javascript
_{{dist/output.css}}_
```
## production
```javascript
_{{production:dist/output.css}}_
```
# dist/1.output.css
```javascript
_{{dist/1.output.css}}_
```
# Info
## Unoptimized
```
_{{stdout}}_
```
## Production mode
```
_{{production:stdout}}_
```

View File

@ -0,0 +1,8 @@
module.exports = {
output: {
uniqueName: "app"
},
experiments: {
css: true
}
};

View File

@ -21,7 +21,7 @@ const {
/**
* @template T
* @callback CallbackCache
* @param {WebpackError=} err
* @param {(WebpackError | null)=} err
* @param {T=} result
* @returns {void}
*/

View File

@ -5,6 +5,7 @@
"use strict";
const { forEachBail } = require("enhanced-resolve");
const asyncLib = require("neo-async");
const getLazyHashedEtag = require("./cache/getLazyHashedEtag");
const mergeEtags = require("./cache/mergeEtags");
@ -18,7 +19,7 @@ const mergeEtags = require("./cache/mergeEtags");
/**
* @template T
* @callback CallbackCache
* @param {WebpackError=} err
* @param {(WebpackError | null)=} err
* @param {T=} result
* @returns {void}
*/
@ -26,7 +27,7 @@ const mergeEtags = require("./cache/mergeEtags");
/**
* @template T
* @callback CallbackNormalErrorCache
* @param {Error=} err
* @param {(Error | null)=} err
* @param {T=} result
* @returns {void}
*/
@ -46,15 +47,7 @@ class MultiItemCache {
* @returns {void}
*/
get(callback) {
const next = i => {
this._items[i].get((err, result) => {
if (err) return callback(err);
if (result !== undefined) return callback(null, result);
if (++i >= this._items.length) return callback();
next(i);
});
};
next(0);
forEachBail(this._items, (item, callback) => item.get(callback), callback);
}
/**

View File

@ -80,6 +80,8 @@ class Chunk {
this.preventIntegration = false;
/** @type {(string | function(PathData, AssetInfo=): string)?} */
this.filenameTemplate = undefined;
/** @type {(string | function(PathData, AssetInfo=): string)?} */
this.cssFilenameTemplate = undefined;
/** @private @type {SortableSet<ChunkGroup>} */
this._groups = new SortableSet(undefined, compareChunkGroupsByIndex);
/** @type {RuntimeSpec} */

View File

@ -45,7 +45,7 @@ const validate = createSchemaValidation(
* @param {OutputFileSystem} fs filesystem
* @param {string} outputPath output path
* @param {Set<string>} currentAssets filename of the current assets (must not start with .. or ., must only use / as path separator)
* @param {function(Error=, Set<string>=): void} callback returns the filenames of the assets that shouldn't be there
* @param {function((Error | null)=, Set<string>=): void} callback returns the filenames of the assets that shouldn't be there
* @returns {void}
*/
const getDiffToFs = (fs, outputPath, currentAssets, callback) => {

View File

@ -116,34 +116,34 @@ const { isSourceEqual } = require("./util/source");
/**
* @callback Callback
* @param {WebpackError=} err
* @param {(WebpackError | null)=} err
* @returns {void}
*/
/**
* @callback ModuleCallback
* @param {WebpackError=} err
* @param {(WebpackError | null)=} err
* @param {Module=} result
* @returns {void}
*/
/**
* @callback ModuleFactoryResultCallback
* @param {WebpackError=} err
* @param {(WebpackError | null)=} err
* @param {ModuleFactoryResult=} result
* @returns {void}
*/
/**
* @callback ModuleOrFactoryResultCallback
* @param {WebpackError=} err
* @param {(WebpackError | null)=} err
* @param {Module | ModuleFactoryResult=} result
* @returns {void}
*/
/**
* @callback ExecuteModuleCallback
* @param {WebpackError=} err
* @param {(WebpackError | null)=} err
* @param {ExecuteModuleResult=} result
* @returns {void}
*/
@ -3193,47 +3193,87 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
this;
const results = this.codeGenerationResults;
const errors = [];
asyncLib.eachLimit(
jobs,
this.options.parallelism,
({ module, hash, runtime, runtimes }, callback) => {
this._codeGenerationModule(
module,
runtime,
runtimes,
hash,
dependencyTemplates,
chunkGraph,
moduleGraph,
runtimeTemplate,
errors,
results,
(err, codeGenerated) => {
if (codeGenerated) statModulesGenerated++;
else statModulesFromCache++;
callback(err);
/** @type {Set<Module> | undefined} */
let notCodeGeneratedModules = undefined;
const runIteration = () => {
let delayedJobs = [];
let delayedModules = new Set();
asyncLib.eachLimit(
jobs,
this.options.parallelism,
(job, callback) => {
const { module } = job;
const { codeGenerationDependencies } = module;
if (codeGenerationDependencies !== undefined) {
if (
notCodeGeneratedModules === undefined ||
codeGenerationDependencies.some(dep => {
const referencedModule = moduleGraph.getModule(dep);
return notCodeGeneratedModules.has(referencedModule);
})
) {
delayedJobs.push(job);
delayedModules.add(module);
return callback();
}
}
);
},
err => {
if (err) return callback(err);
if (errors.length > 0) {
errors.sort(
compareSelect(err => err.module, compareModulesByIdentifier)
const { hash, runtime, runtimes } = job;
this._codeGenerationModule(
module,
runtime,
runtimes,
hash,
dependencyTemplates,
chunkGraph,
moduleGraph,
runtimeTemplate,
errors,
results,
(err, codeGenerated) => {
if (codeGenerated) statModulesGenerated++;
else statModulesFromCache++;
callback(err);
}
);
for (const error of errors) {
this.errors.push(error);
},
err => {
if (err) return callback(err);
if (delayedJobs.length > 0) {
if (delayedJobs.length === jobs.length) {
return callback(
new Error(
`Unable to make progress during code generation because of circular code generation dependency: ${Array.from(
delayedModules,
m => m.identifier()
).join(", ")}`
)
);
}
jobs = delayedJobs;
delayedJobs = [];
notCodeGeneratedModules = delayedModules;
delayedModules = new Set();
return runIteration();
}
if (errors.length > 0) {
errors.sort(
compareSelect(err => err.module, compareModulesByIdentifier)
);
for (const error of errors) {
this.errors.push(error);
}
}
this.logger.log(
`${Math.round(
(100 * statModulesGenerated) /
(statModulesGenerated + statModulesFromCache)
)}% code generated (${statModulesGenerated} generated, ${statModulesFromCache} from cache)`
);
callback();
}
this.logger.log(
`${Math.round(
(100 * statModulesGenerated) /
(statModulesGenerated + statModulesFromCache)
)}% code generated (${statModulesGenerated} generated, ${statModulesFromCache} from cache)`
);
callback();
}
);
);
};
runIteration();
}
/**
@ -3283,7 +3323,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
moduleGraph,
dependencyTemplates,
runtimeTemplate,
runtime
runtime,
codeGenerationResults: results
});
} catch (err) {
errors.push(new CodeGenerationError(module, err));

View File

@ -58,13 +58,13 @@ const { isSourceEqual } = require("./util/source");
/**
* @template T
* @callback Callback
* @param {Error=} err
* @param {(Error | null)=} err
* @param {T=} result
*/
/**
* @callback RunAsChildCallback
* @param {Error=} err
* @param {(Error | null)=} err
* @param {Chunk[]=} entries
* @param {Compilation=} compilation
*/

View File

@ -71,7 +71,7 @@ const makeSerializable = require("./util/makeSerializable");
/**
* @callback ResolveDependenciesCallback
* @param {Error=} err
* @param {(Error | null)=} err
* @param {ContextElementDependency[]=} dependencies
*/
@ -149,12 +149,9 @@ class ContextModule extends Module {
this.resolveDependencies = undefined;
}
prettyRegExp(regexString) {
// remove the "/" at the front and the beginning
// "/foo/" -> "foo"
return regexString
.substring(1, regexString.length - 1)
.replace(/!/g, "%21");
_prettyRegExp(regexString, stripSlash = true) {
const str = (regexString + "").replace(/!/g, "%21").replace(/\|/g, "%7C");
return stripSlash ? str.substring(1, str.length - 1) : str;
}
_createIdentifier() {
@ -175,13 +172,19 @@ class ContextModule extends Module {
identifier += `|${this.options.addon}`;
}
if (this.options.regExp) {
identifier += `|${this.options.regExp}`;
identifier += `|${this._prettyRegExp(this.options.regExp, false)}`;
}
if (this.options.include) {
identifier += `|include: ${this.options.include}`;
identifier += `|include: ${this._prettyRegExp(
this.options.include,
false
)}`;
}
if (this.options.exclude) {
identifier += `|exclude: ${this.options.exclude}`;
identifier += `|exclude: ${this._prettyRegExp(
this.options.exclude,
false
)}`;
}
if (this.options.referencedExports) {
identifier += `|referencedExports: ${JSON.stringify(
@ -231,13 +234,13 @@ class ContextModule extends Module {
identifier += ` ${requestShortener.shorten(this.options.addon)}`;
}
if (this.options.regExp) {
identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`;
identifier += ` ${this._prettyRegExp(this.options.regExp)}`;
}
if (this.options.include) {
identifier += ` include: ${this.prettyRegExp(this.options.include + "")}`;
identifier += ` include: ${this._prettyRegExp(this.options.include)}`;
}
if (this.options.exclude) {
identifier += ` exclude: ${this.prettyRegExp(this.options.exclude + "")}`;
identifier += ` exclude: ${this._prettyRegExp(this.options.exclude)}`;
}
if (this.options.referencedExports) {
identifier += ` referencedExports: ${this.options.referencedExports
@ -272,6 +275,7 @@ class ContextModule extends Module {
this.context,
options.associatedObjectForCache
);
if (this.layer) identifier = `(${this.layer})/${identifier}`;
if (this.options.mode) {
identifier += ` ${this.options.mode}`;
}
@ -286,13 +290,13 @@ class ContextModule extends Module {
)}`;
}
if (this.options.regExp) {
identifier += ` ${this.prettyRegExp(this.options.regExp + "")}`;
identifier += ` ${this._prettyRegExp(this.options.regExp)}`;
}
if (this.options.include) {
identifier += ` include: ${this.prettyRegExp(this.options.include + "")}`;
identifier += ` include: ${this._prettyRegExp(this.options.include)}`;
}
if (this.options.exclude) {
identifier += ` exclude: ${this.prettyRegExp(this.options.exclude + "")}`;
identifier += ` exclude: ${this._prettyRegExp(this.options.exclude)}`;
}
if (this.options.referencedExports) {
identifier += ` referencedExports: ${this.options.referencedExports
@ -312,7 +316,7 @@ class ContextModule extends Module {
/**
* @param {NeedBuildContext} context context info
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild({ fileSystemInfo }, callback) {

View File

@ -91,7 +91,7 @@ class DelegatedModule extends Module {
/**
* @param {NeedBuildContext} context context info
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {

View File

@ -172,6 +172,16 @@ class Dependency {
this._loc = loc;
}
setLoc(startLine, startColumn, endLine, endColumn) {
this._locSL = startLine;
this._locSC = startColumn;
this._locEL = endLine;
this._locEC = endColumn;
this._locI = undefined;
this._locN = undefined;
this._loc = undefined;
}
/**
* @returns {string | null} an identifier to merge equal requests
*/

View File

@ -7,6 +7,7 @@
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
/** @typedef {import("./ConcatenationScope")} ConcatenationScope */
/** @typedef {import("./Dependency")} Dependency */
/** @typedef {import("./Dependency").RuntimeSpec} RuntimeSpec */
@ -28,8 +29,16 @@
* @property {RuntimeSpec} runtime current runtimes, for which code is generated
* @property {InitFragment<GenerateContext>[]} initFragments mutable array of init fragments for the current module
* @property {ConcatenationScope=} concatenationScope when in a concatenated module, information about other concatenated modules
* @property {CodeGenerationResults} codeGenerationResults the code generation results
*/
/**
* @typedef {Object} CssDependencyTemplateContextExtras
* @property {Map<string, string>} cssExports the css exports
*/
/** @typedef {DependencyTemplateContext & CssDependencyTemplateContextExtras} CssDependencyTemplateContext */
class DependencyTemplate {
/* istanbul ignore next */
/**

View File

@ -96,7 +96,7 @@ class DllModule extends Module {
/**
* @param {NeedBuildContext} context context info
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {

View File

@ -53,6 +53,7 @@ const { register } = require("./util/serialization");
*/
const TYPES = new Set(["javascript"]);
const CSS_TYPES = new Set(["css-import"]);
const RUNTIME_REQUIREMENTS = new Set([RuntimeGlobals.module]);
const RUNTIME_REQUIREMENTS_FOR_SCRIPT = new Set([RuntimeGlobals.loadScript]);
const RUNTIME_REQUIREMENTS_FOR_MODULE = new Set([
@ -392,7 +393,7 @@ class ExternalModule extends Module {
* @returns {Set<string>} types available (do not mutate)
*/
getSourceTypes() {
return TYPES;
return this.externalType === "css-import" ? CSS_TYPES : TYPES;
}
/**
@ -409,7 +410,9 @@ class ExternalModule extends Module {
* @returns {boolean} true, if the chunk is ok for the module
*/
chunkCondition(chunk, { chunkGraph }) {
return chunkGraph.getNumberOfEntryModules(chunk) > 0;
return this.externalType === "css-import"
? true
: chunkGraph.getNumberOfEntryModules(chunk) > 0;
}
/**
@ -429,7 +432,7 @@ class ExternalModule extends Module {
/**
* @param {NeedBuildContext} context context info
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {
@ -526,8 +529,14 @@ class ExternalModule extends Module {
return { request, externalType };
}
_getSourceData(runtimeTemplate, moduleGraph, chunkGraph, runtime) {
const { request, externalType } = this._getRequestAndExternalType();
_getSourceData(
request,
externalType,
runtimeTemplate,
moduleGraph,
chunkGraph,
runtime
) {
switch (externalType) {
case "this":
case "window":
@ -541,6 +550,7 @@ class ExternalModule extends Module {
case "commonjs":
case "commonjs2":
case "commonjs-module":
case "commonjs-static":
return getSourceForCommonJsExternal(request);
case "node-commonjs":
return this.buildInfo.module
@ -613,60 +623,90 @@ class ExternalModule extends Module {
runtime,
concatenationScope
}) {
const sourceData = this._getSourceData(
runtimeTemplate,
moduleGraph,
chunkGraph,
runtime
);
const { request, externalType } = this._getRequestAndExternalType();
switch (externalType) {
case "asset": {
const sources = new Map();
sources.set(
"javascript",
new RawSource(`module.exports = ${JSON.stringify(request)};`)
);
const data = new Map();
data.set("url", request);
return { sources, runtimeRequirements: RUNTIME_REQUIREMENTS, data };
}
case "css-import": {
const sources = new Map();
sources.set(
"css-import",
new RawSource(`@import url(${JSON.stringify(request)});`)
);
return {
sources,
runtimeRequirements: EMPTY_RUNTIME_REQUIREMENTS
};
}
default: {
const sourceData = this._getSourceData(
request,
externalType,
runtimeTemplate,
moduleGraph,
chunkGraph,
runtime
);
let sourceString = sourceData.expression;
if (sourceData.iife)
sourceString = `(function() { return ${sourceString}; }())`;
if (concatenationScope) {
sourceString = `${runtimeTemplate.supportsConst() ? "const" : "var"} ${
ConcatenationScope.NAMESPACE_OBJECT_EXPORT
} = ${sourceString};`;
concatenationScope.registerNamespaceExport(
ConcatenationScope.NAMESPACE_OBJECT_EXPORT
);
} else {
sourceString = `module.exports = ${sourceString};`;
}
if (sourceData.init) sourceString = `${sourceData.init}\n${sourceString}`;
let sourceString = sourceData.expression;
if (sourceData.iife)
sourceString = `(function() { return ${sourceString}; }())`;
if (concatenationScope) {
sourceString = `${
runtimeTemplate.supportsConst() ? "const" : "var"
} ${ConcatenationScope.NAMESPACE_OBJECT_EXPORT} = ${sourceString};`;
concatenationScope.registerNamespaceExport(
ConcatenationScope.NAMESPACE_OBJECT_EXPORT
);
} else {
sourceString = `module.exports = ${sourceString};`;
}
if (sourceData.init)
sourceString = `${sourceData.init}\n${sourceString}`;
let data = undefined;
if (sourceData.chunkInitFragments) {
data = new Map();
data.set("chunkInitFragments", sourceData.chunkInitFragments);
}
let data = undefined;
if (sourceData.chunkInitFragments) {
data = new Map();
data.set("chunkInitFragments", sourceData.chunkInitFragments);
}
const sources = new Map();
if (this.useSourceMap || this.useSimpleSourceMap) {
sources.set(
"javascript",
new OriginalSource(sourceString, this.identifier())
);
} else {
sources.set("javascript", new RawSource(sourceString));
}
const sources = new Map();
if (this.useSourceMap || this.useSimpleSourceMap) {
sources.set(
"javascript",
new OriginalSource(sourceString, this.identifier())
);
} else {
sources.set("javascript", new RawSource(sourceString));
}
let runtimeRequirements = sourceData.runtimeRequirements;
if (!concatenationScope) {
if (!runtimeRequirements) {
runtimeRequirements = RUNTIME_REQUIREMENTS;
} else {
const set = new Set(runtimeRequirements);
set.add(RuntimeGlobals.module);
runtimeRequirements = set;
let runtimeRequirements = sourceData.runtimeRequirements;
if (!concatenationScope) {
if (!runtimeRequirements) {
runtimeRequirements = RUNTIME_REQUIREMENTS;
} else {
const set = new Set(runtimeRequirements);
set.add(RuntimeGlobals.module);
runtimeRequirements = set;
}
}
return {
sources,
runtimeRequirements:
runtimeRequirements || EMPTY_RUNTIME_REQUIREMENTS,
data
};
}
}
return {
sources,
runtimeRequirements: runtimeRequirements || EMPTY_RUNTIME_REQUIREMENTS,
data
};
}
/**

View File

@ -117,7 +117,7 @@ class ExternalModuleFactoryPlugin {
/**
* @param {Externals} externals externals config
* @param {function(Error=, ExternalModule=): void} callback callback
* @param {function((Error | null)=, ExternalModule=): void} callback callback
* @returns {void}
*/
const handleExternals = (externals, callback) => {

View File

@ -1185,7 +1185,7 @@ class FileSystemInfo {
/**
* @param {string} path file path
* @param {function(WebpackError=, (FileSystemInfoEntry | "ignore" | null)=): void} callback callback function
* @param {function((WebpackError | null)=, (FileSystemInfoEntry | "ignore" | null)=): void} callback callback function
* @returns {void}
*/
getFileTimestamp(path, callback) {
@ -1196,7 +1196,7 @@ class FileSystemInfo {
/**
* @param {string} path context path
* @param {function(WebpackError=, (ResolvedContextFileSystemInfoEntry | "ignore" | null)=): void} callback callback function
* @param {function((WebpackError | null)=, (ResolvedContextFileSystemInfoEntry | "ignore" | null)=): void} callback callback function
* @returns {void}
*/
getContextTimestamp(path, callback) {
@ -1217,7 +1217,7 @@ class FileSystemInfo {
/**
* @param {string} path context path
* @param {function(WebpackError=, (ContextFileSystemInfoEntry | "ignore" | null)=): void} callback callback function
* @param {function((WebpackError | null)=, (ContextFileSystemInfoEntry | "ignore" | null)=): void} callback callback function
* @returns {void}
*/
_getUnresolvedContextTimestamp(path, callback) {
@ -1228,7 +1228,7 @@ class FileSystemInfo {
/**
* @param {string} path file path
* @param {function(WebpackError=, string=): void} callback callback function
* @param {function((WebpackError | null)=, string=): void} callback callback function
* @returns {void}
*/
getFileHash(path, callback) {
@ -1239,7 +1239,7 @@ class FileSystemInfo {
/**
* @param {string} path context path
* @param {function(WebpackError=, string=): void} callback callback function
* @param {function((WebpackError | null)=, string=): void} callback callback function
* @returns {void}
*/
getContextHash(path, callback) {
@ -1259,7 +1259,7 @@ class FileSystemInfo {
/**
* @param {string} path context path
* @param {function(WebpackError=, ContextHash=): void} callback callback function
* @param {function((WebpackError | null)=, ContextHash=): void} callback callback function
* @returns {void}
*/
_getUnresolvedContextHash(path, callback) {
@ -1270,7 +1270,7 @@ class FileSystemInfo {
/**
* @param {string} path context path
* @param {function(WebpackError=, ResolvedContextTimestampAndHash=): void} callback callback function
* @param {function((WebpackError | null)=, ResolvedContextTimestampAndHash=): void} callback callback function
* @returns {void}
*/
getContextTsh(path, callback) {
@ -1290,7 +1290,7 @@ class FileSystemInfo {
/**
* @param {string} path context path
* @param {function(WebpackError=, ContextTimestampAndHash=): void} callback callback function
* @param {function((WebpackError | null)=, ContextTimestampAndHash=): void} callback callback function
* @returns {void}
*/
_getUnresolvedContextTsh(path, callback) {
@ -1330,7 +1330,7 @@ class FileSystemInfo {
/**
* @param {string} context context directory
* @param {Iterable<string>} deps dependencies
* @param {function(Error=, ResolveBuildDependenciesResult=): void} callback callback function
* @param {function((Error | null)=, ResolveBuildDependenciesResult=): void} callback callback function
* @returns {void}
*/
resolveBuildDependencies(context, deps, callback) {
@ -1798,7 +1798,7 @@ class FileSystemInfo {
/**
* @param {Map<string, string | false>} resolveResults results from resolving
* @param {function(Error=, boolean=): void} callback callback with true when resolveResults resolve the same way
* @param {function((Error | null)=, boolean=): void} callback callback with true when resolveResults resolve the same way
* @returns {void}
*/
checkResolveResultsValid(resolveResults, callback) {
@ -1880,7 +1880,7 @@ class FileSystemInfo {
* @param {Object} options options object (for future extensions)
* @param {boolean=} options.hash should use hash to snapshot
* @param {boolean=} options.timestamp should use timestamp to snapshot
* @param {function(WebpackError=, Snapshot=): void} callback callback function
* @param {function((WebpackError | null)=, (Snapshot | null)=): void} callback callback function
* @returns {void}
*/
createSnapshot(startTime, files, directories, missing, options, callback) {
@ -2256,8 +2256,10 @@ class FileSystemInfo {
for (const path of managedItems) {
const cache = this._managedItems.get(path);
if (cache !== undefined) {
if (cache !== "missing") {
if (!cache.startsWith("*")) {
managedFiles.add(join(this.fs, path, "package.json"));
} else if (cache === "*nested") {
managedMissing.add(join(this.fs, path, "package.json"));
}
managedItemInfo.set(path, cache);
} else {
@ -2271,8 +2273,10 @@ class FileSystemInfo {
}
jobError();
} else if (entry) {
if (entry !== "missing") {
if (!entry.startsWith("*")) {
managedFiles.add(join(this.fs, path, "package.json"));
} else if (cache === "*nested") {
managedMissing.add(join(this.fs, path, "package.json"));
}
managedItemInfo.set(path, entry);
jobDone();
@ -2375,7 +2379,7 @@ class FileSystemInfo {
/**
* @param {Snapshot} snapshot the snapshot made
* @param {function(WebpackError=, boolean=): void} callback callback function
* @param {function((WebpackError | null)=, boolean=): void} callback callback function
* @returns {void}
*/
checkSnapshotValid(snapshot, callback) {
@ -2395,7 +2399,7 @@ class FileSystemInfo {
/**
* @param {Snapshot} snapshot the snapshot made
* @param {function(WebpackError=, boolean=): void} callback callback function
* @param {function((WebpackError | null)=, boolean=): void} callback callback function
* @returns {void}
*/
_checkSnapshotValidNoCache(snapshot, callback) {
@ -2944,7 +2948,7 @@ class FileSystemInfo {
* @param {function(string, IStats, function(Error=, ItemType=): void): void} options.fromFile called when context item is a file
* @param {function(string, IStats, function(Error=, ItemType=): void): void} options.fromDirectory called when context item is a directory
* @param {function(string[], ItemType[]): T} options.reduce called from all context items
* @param {function(Error=, (T)=): void} callback callback
* @param {function((Error | null)=, (T)=): void} callback callback
*/
_readContext(
{
@ -3127,7 +3131,7 @@ class FileSystemInfo {
/**
* @param {ContextFileSystemInfoEntry} entry entry
* @param {function(Error=, ResolvedContextFileSystemInfoEntry=): void} callback callback
* @param {function((Error | null)=, ResolvedContextFileSystemInfoEntry=): void} callback callback
* @returns {void}
*/
_resolveContextTimestamp(entry, callback) {
@ -3235,7 +3239,7 @@ class FileSystemInfo {
/**
* @param {ContextHash} entry context hash
* @param {function(Error=, string=): void} callback callback
* @param {function((Error | null)=, string=): void} callback callback
* @returns {void}
*/
_resolveContextHash(entry, callback) {
@ -3391,7 +3395,7 @@ class FileSystemInfo {
/**
* @param {ContextTimestampAndHash} entry entry
* @param {function(Error=, ResolvedContextTimestampAndHash=): void} callback callback
* @param {function((Error | null)=, ResolvedContextTimestampAndHash=): void} callback callback
* @returns {void}
*/
_resolveContextTsh(entry, callback) {
@ -3471,8 +3475,8 @@ class FileSystemInfo {
}
if (!elements.has(path)) {
// file or directory doesn't exist
this._managedItems.set(path, "missing");
return callback(null, "missing");
this._managedItems.set(path, "*missing");
return callback(null, "*missing");
}
// something exists
// it may be a file or directory
@ -3481,8 +3485,8 @@ class FileSystemInfo {
(path.endsWith("/node_modules") || path.endsWith("\\node_modules"))
) {
// we are only interested in existence of this special directory
this._managedItems.set(path, "exists");
return callback(null, "exists");
this._managedItems.set(path, "*node_modules");
return callback(null, "*node_modules");
}
// we assume it's a directory, as files shouldn't occur in managed paths
@ -3499,8 +3503,8 @@ class FileSystemInfo {
) {
// This is only a grouping folder e. g. used by yarn
// we are only interested in existence of this special directory
this._managedItems.set(path, "nested");
return callback(null, "nested");
this._managedItems.set(path, "*nested");
return callback(null, "*nested");
}
this.logger.warn(
`Managed item ${path} isn't a directory or doesn't contain a package.json (see snapshot.managedPaths option)`

View File

@ -7,6 +7,7 @@
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
/** @typedef {import("./Compilation")} Compilation */
/** @typedef {import("./ConcatenationScope")} ConcatenationScope */
/** @typedef {import("./DependencyTemplate")} DependencyTemplate */
@ -27,6 +28,7 @@
* @property {Set<string>} runtimeRequirements the requirements for runtime
* @property {RuntimeSpec} runtime the runtime
* @property {ConcatenationScope=} concatenationScope when in concatenated module, information about other concatenated modules
* @property {CodeGenerationResults=} codeGenerationResults code generation results of other modules (need to have a codeGenerationDependency to use that)
* @property {string} type which kind of code should be generated
* @property {function(): Map<string, any>=} getData get access to the code generation data
*/

View File

@ -51,7 +51,7 @@ module.exports.makeWebpackError = makeWebpackError;
/**
* @template T
* @param {function(WebpackError=, T=): void} callback webpack error callback
* @param {function((WebpackError | null)=, T=): void} callback webpack error callback
* @param {string} hook name of hook
* @returns {Callback<T>} generic callback
*/

View File

@ -19,6 +19,7 @@ const makeSerializable = require("./util/makeSerializable");
/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
/** @typedef {import("./Chunk")} Chunk */
/** @typedef {import("./ChunkGroup")} ChunkGroup */
/** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
/** @typedef {import("./Compilation")} Compilation */
/** @typedef {import("./ConcatenationScope")} ConcatenationScope */
/** @typedef {import("./Dependency")} Dependency */
@ -56,6 +57,7 @@ const makeSerializable = require("./util/makeSerializable");
* @property {ChunkGraph} chunkGraph the chunk graph
* @property {RuntimeSpec} runtime the runtimes code should be generated for
* @property {ConcatenationScope=} concatenationScope when in concatenated module, information about other concatenated modules
* @property {CodeGenerationResults} codeGenerationResults code generation results of other modules (need to have a codeGenerationDependency to use that)
*/
/**
@ -165,6 +167,8 @@ class Module extends DependenciesBlock {
this.buildInfo = undefined;
/** @type {Dependency[] | undefined} */
this.presentationalDependencies = undefined;
/** @type {Dependency[] | undefined} */
this.codeGenerationDependencies = undefined;
}
// TODO remove in webpack 6
@ -493,6 +497,19 @@ class Module extends DependenciesBlock {
this.presentationalDependencies.push(presentationalDependency);
}
/**
* @param {Dependency} codeGenerationDependency dependency being tied to module.
* This is a Dependency where the code generation result of the referenced module is needed during code generation.
* The Dependency should also be added to normal dependencies via addDependency.
* @returns {void}
*/
addCodeGenerationDependency(codeGenerationDependency) {
if (this.codeGenerationDependencies === undefined) {
this.codeGenerationDependencies = [];
}
this.codeGenerationDependencies.push(codeGenerationDependency);
}
/**
* Removes all dependencies and blocks
* @returns {void}
@ -501,6 +518,9 @@ class Module extends DependenciesBlock {
if (this.presentationalDependencies !== undefined) {
this.presentationalDependencies.length = 0;
}
if (this.codeGenerationDependencies !== undefined) {
this.codeGenerationDependencies.length = 0;
}
super.clearDependenciesAndBlocks();
}
@ -671,7 +691,7 @@ class Module extends DependenciesBlock {
/**
* @param {NeedBuildContext} context context info
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {
@ -799,7 +819,8 @@ class Module extends DependenciesBlock {
runtimeTemplate,
moduleGraph: chunkGraph.moduleGraph,
chunkGraph,
runtime: undefined
runtime: undefined,
codeGenerationResults: undefined
};
const sources = this.codeGeneration(codeGenContext).sources;
return type ? sources.get(type) : sources.get(first(this.getSourceTypes()));
@ -976,6 +997,7 @@ class Module extends DependenciesBlock {
write(this.buildMeta);
write(this.buildInfo);
write(this.presentationalDependencies);
write(this.codeGenerationDependencies);
super.serialize(context);
}
@ -993,6 +1015,7 @@ class Module extends DependenciesBlock {
this.buildMeta = read();
this.buildInfo = read();
this.presentationalDependencies = read();
this.codeGenerationDependencies = read();
super.deserialize(context);
}
}

View File

@ -5,6 +5,7 @@
"use strict";
const NormalModule = require("./NormalModule");
const createHash = require("./util/createHash");
const memoize = require("./util/memoize");
@ -138,7 +139,10 @@ ModuleFilenameHelpers.createFilename = (
);
identifier = memoize(() => requestShortener.shorten(module.identifier()));
moduleId = () => chunkGraph.getModuleId(module);
absoluteResourcePath = () => module.identifier().split("!").pop();
absoluteResourcePath = () =>
module instanceof NormalModule
? module.resource
: module.identifier().split("!").pop();
hash = getHash(identifier, hashFunction);
}
const resource = memoize(() => shortIdentifier().split("!").pop());

View File

@ -27,7 +27,7 @@ const ArrayQueue = require("./util/ArrayQueue");
/**
* @template T
* @callback Callback
* @param {Error=} err
* @param {(Error | null)=} err
* @param {T=} result
*/

View File

@ -13,7 +13,7 @@ const asyncLib = require("neo-async");
/**
* @template T
* @callback Callback
* @param {Error=} err
* @param {(Error | null)=} err
* @param {T=} result
*/

View File

@ -310,7 +310,7 @@ class NormalModule extends Module {
}
// Info from Build
/** @type {WebpackError=} */
/** @type {(WebpackError | null)=} */
this.error = null;
/** @private @type {Source=} */
this._source = null;
@ -355,11 +355,13 @@ class NormalModule extends Module {
* @returns {string | null} an identifier for library inclusion
*/
libIdent(options) {
return contextify(
let ident = contextify(
options.context,
this.userRequest,
options.associatedObjectForCache
);
if (this.layer) ident = `(${this.layer})/${ident}`;
return ident;
}
/**
@ -730,7 +732,7 @@ class NormalModule extends Module {
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {NormalModuleCompilationHooks} hooks the hooks
* @param {function(WebpackError=): void} callback callback function
* @param {function((WebpackError | null)=): void} callback callback function
* @returns {void}
*/
_doBuild(options, compilation, resolver, fs, hooks, callback) {
@ -1168,7 +1170,8 @@ class NormalModule extends Module {
moduleGraph,
chunkGraph,
runtime,
concatenationScope
concatenationScope,
codeGenerationResults
}) {
/** @type {Set<string>} */
const runtimeRequirements = new Set();
@ -1200,6 +1203,7 @@ class NormalModule extends Module {
runtimeRequirements,
runtime,
concatenationScope,
codeGenerationResults,
getData,
type
});
@ -1234,7 +1238,7 @@ class NormalModule extends Module {
/**
* @param {NeedBuildContext} context context info
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {

View File

@ -74,7 +74,7 @@ class RawModule extends Module {
/**
* @param {NeedBuildContext} context context info
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {

View File

@ -164,7 +164,7 @@ exports.scriptNonce = "__webpack_require__.nc";
* function to load a script tag.
* Arguments: (url: string, done: (event) => void), key?: string | number, chunkId?: string | number) => void
* done function is called when loading has finished or timeout occurred.
* It will attach to existing script tags with data-webpack == key or src == url.
* It will attach to existing script tags with data-webpack == uniqueName + ":" + key or src == url.
*/
exports.loadScript = "__webpack_require__.l";
@ -190,11 +190,26 @@ exports.runtimeId = "__webpack_require__.j";
*/
exports.getChunkScriptFilename = "__webpack_require__.u";
/**
* the filename of the css part of the chunk
*/
exports.getChunkCssFilename = "__webpack_require__.k";
/**
* a flag when a module/chunk/tree has css modules
*/
exports.hasCssModules = "has css modules";
/**
* the filename of the script part of the hot update chunk
*/
exports.getChunkUpdateScriptFilename = "__webpack_require__.hu";
/**
* the filename of the css part of the hot update chunk
*/
exports.getChunkUpdateCssFilename = "__webpack_require__.hk";
/**
* startup signal from runtime
* This will be called when the runtime chunk has been loaded.

View File

@ -78,7 +78,7 @@ class RuntimeModule extends Module {
/**
* @param {NeedBuildContext} context context info
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {

View File

@ -6,6 +6,7 @@
"use strict";
const RuntimeGlobals = require("./RuntimeGlobals");
const { getChunkFilenameTemplate } = require("./css/CssModulesPlugin");
const RuntimeRequirementsDependency = require("./dependencies/RuntimeRequirementsDependency");
const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
const AsyncModuleRuntimeModule = require("./runtime/AsyncModuleRuntimeModule");
@ -261,6 +262,30 @@ class RuntimePlugin {
);
return true;
});
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.getChunkCssFilename)
.tap("RuntimePlugin", (chunk, set) => {
if (
typeof compilation.outputOptions.cssChunkFilename === "string" &&
/\[(full)?hash(:\d+)?\]/.test(
compilation.outputOptions.cssChunkFilename
)
) {
set.add(RuntimeGlobals.getFullHash);
}
compilation.addRuntimeModule(
chunk,
new GetChunkFilenameRuntimeModule(
"css",
"css",
RuntimeGlobals.getChunkCssFilename,
chunk =>
getChunkFilenameTemplate(chunk, compilation.outputOptions),
set.has(RuntimeGlobals.hmrDownloadUpdateHandlers)
)
);
return true;
});
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.getChunkUpdateScriptFilename)
.tap("RuntimePlugin", (chunk, set) => {

View File

@ -16,6 +16,7 @@ const { forEachRuntime, subtractRuntime } = require("./util/runtime");
/** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */
/** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
/** @typedef {import("./Compilation")} Compilation */
/** @typedef {import("./Dependency")} Dependency */
/** @typedef {import("./Module")} Module */
@ -1014,6 +1015,26 @@ class RuntimeTemplate {
runtimeRequirements.add(RuntimeGlobals.exports);
return `${RuntimeGlobals.makeNamespaceObject}(${exportsArgument});\n`;
}
/**
* @param {Object} options options object
* @param {Module} options.module the module
* @param {string} options.publicPath the public path
* @param {RuntimeSpec=} options.runtime runtime
* @param {CodeGenerationResults} options.codeGenerationResults the code generation results
* @returns {string} the url of the asset
*/
assetUrl({ publicPath, runtime, module, codeGenerationResults }) {
if (!module) {
return "data:,";
}
const codeGen = codeGenerationResults.get(module, runtime);
const { data } = codeGen;
const url = data.get("url");
if (url) return url;
const filename = data.get("filename");
return publicPath + filename;
}
}
module.exports = RuntimeTemplate;

View File

@ -370,7 +370,8 @@ class Template {
dependencyTemplates: renderContext.dependencyTemplates,
moduleGraph: renderContext.moduleGraph,
runtimeTemplate: renderContext.runtimeTemplate,
runtime: renderContext.chunk.runtime
runtime: renderContext.chunk.runtime,
codeGenerationResults
});
if (!codeGenResult) continue;
runtimeSource = codeGenResult.sources.get("runtime");

View File

@ -15,7 +15,7 @@ const Stats = require("./Stats");
/**
* @template T
* @callback Callback
* @param {Error=} err
* @param {(Error | null)=} err
* @param {T=} result
*/
@ -49,7 +49,7 @@ class Watching {
this.watchOptions = {};
}
if (typeof this.watchOptions.aggregateTimeout !== "number") {
this.watchOptions.aggregateTimeout = 200;
this.watchOptions.aggregateTimeout = 20;
}
this.compiler = compiler;
this.running = false;

View File

@ -118,11 +118,47 @@ class WebpackOptionsApply extends OptionsApply {
if (options.externalsPresets.webAsync) {
//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
const ExternalsPlugin = require("./ExternalsPlugin");
new ExternalsPlugin("import", /^(https?:\/\/|std:)/).apply(compiler);
new ExternalsPlugin(
"import",
options.experiments.css
? ({ request, dependencyType }, callback) => {
if (dependencyType === "url") {
if (/^(\/\/|https?:\/\/)/.test(request))
return callback(null, `asset ${request}`);
} else if (dependencyType === "css-import") {
if (/^(\/\/|https?:\/\/)/.test(request))
return callback(null, `css-import ${request}`);
} else if (/^(\/\/|https?:\/\/|std:)/.test(request)) {
if (/^\.css(\?|$)/.test(request))
return callback(null, `css-import ${request}`);
return callback(null, `import ${request}`);
}
callback();
}
: /^(\/\/|https?:\/\/|std:)/
).apply(compiler);
} else if (options.externalsPresets.web) {
//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
const ExternalsPlugin = require("./ExternalsPlugin");
new ExternalsPlugin("module", /^(https?:\/\/|std:)/).apply(compiler);
new ExternalsPlugin(
"module",
options.experiments.css
? ({ request, dependencyType }, callback) => {
if (dependencyType === "url") {
if (/^(\/\/|https?:\/\/)/.test(request))
return callback(null, `asset ${request}`);
} else if (dependencyType === "css-import") {
if (/^(\/\/|https?:\/\/)/.test(request))
return callback(null, `css-import ${request}`);
} else if (/^(\/\/|https?:\/\/|std:)/.test(request)) {
if (/^\.css(\?|$)/.test(request))
return callback(null, `css-import ${request}`);
return callback(null, `module ${request}`);
}
callback();
}
: /^(\/\/|https?:\/\/|std:)/
).apply(compiler);
}
new ChunkPrefetchPreloadPlugin().apply(compiler);
@ -253,6 +289,11 @@ class WebpackOptionsApply extends OptionsApply {
}).apply(compiler);
}
if (options.experiments.css) {
const CssModulesPlugin = require("./css/CssModulesPlugin");
new CssModulesPlugin().apply(compiler);
}
if (options.experiments.lazyCompilation) {
const LazyCompilationPlugin = require("./hmr/LazyCompilationPlugin");
const lazyOptions =

View File

@ -74,6 +74,41 @@ const mergeRelatedInfo = (a, b) => {
return result;
};
const encodeDataUri = (encoding, source) => {
let encodedContent;
switch (encoding) {
case "base64": {
encodedContent = source.buffer().toString("base64");
break;
}
case false: {
const content = source.source();
if (typeof content !== "string") {
encodedContent = content.toString("utf-8");
}
encodedContent = encodeURIComponent(encodedContent).replace(
/[!'()*]/g,
character => "%" + character.codePointAt(0).toString(16)
);
break;
}
default:
throw new Error(`Unsupported encoding '${encoding}'`);
}
return encodedContent;
};
const decodeDataUriContent = (encoding, content) => {
const isBase64 = encoding === "base64";
return isBase64
? Buffer.from(content, "base64")
: Buffer.from(decodeURIComponent(content), "ascii");
};
const JS_TYPES = new Set(["javascript"]);
const JS_AND_ASSET_TYPES = new Set(["javascript", "asset"]);
@ -158,39 +193,26 @@ class AssetGenerator extends Generator {
}
let encodedContent;
if (
module.resourceResolveData &&
module.resourceResolveData.encoding === encoding
module.resourceResolveData.encoding === encoding &&
decodeDataUriContent(
module.resourceResolveData.encoding,
module.resourceResolveData.encodedContent
).equals(originalSource.buffer())
) {
encodedContent = module.resourceResolveData.encodedContent;
} else {
switch (encoding) {
case "base64": {
encodedContent = originalSource.buffer().toString("base64");
break;
}
case false: {
const content = originalSource.source();
if (typeof content !== "string") {
encodedContent = content.toString("utf-8");
}
encodedContent = encodeURIComponent(encodedContent).replace(
/[!'()*]/g,
character => "%" + character.codePointAt(0).toString(16)
);
break;
}
default:
throw new Error(`Unsupported encoding '${encoding}'`);
}
encodedContent = encodeDataUri(encoding, originalSource);
}
encodedSource = `data:${mimeType}${
encoding ? `;${encoding}` : ""
},${encodedContent}`;
}
const data = getData();
data.set("url", encodedSource);
return new RawSource(
`${RuntimeGlobals.module}.exports = ${JSON.stringify(
encodedSource

View File

@ -0,0 +1,145 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { RawSource } = require("webpack-sources");
const Module = require("../Module");
const RuntimeGlobals = require("../RuntimeGlobals");
const makeSerializable = require("../util/makeSerializable");
/** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
/** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */
/** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
/** @typedef {import("../Module").NeedBuildContext} NeedBuildContext */
/** @typedef {import("../RequestShortener")} RequestShortener */
/** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("../WebpackError")} WebpackError */
/** @typedef {import("../util/Hash")} Hash */
/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
const TYPES = new Set(["javascript"]);
class RawDataUrlModule extends Module {
/**
* @param {string} url raw url
* @param {string} identifier unique identifier
* @param {string=} readableIdentifier readable identifier
*/
constructor(url, identifier, readableIdentifier) {
super("asset/raw-data-url", null);
this.url = url;
this.identifierStr = identifier || this.url;
this.readableIdentifierStr = readableIdentifier || this.identifierStr;
}
/**
* @returns {Set<string>} types available (do not mutate)
*/
getSourceTypes() {
return TYPES;
}
/**
* @returns {string} a unique identifier of the module
*/
identifier() {
return this.identifierStr;
}
/**
* @param {string=} type the source type for which the size should be estimated
* @returns {number} the estimated size of the module (must be non-zero)
*/
size(type) {
return Math.max(1, this.url.length);
}
/**
* @param {RequestShortener} requestShortener the request shortener
* @returns {string} a user readable identifier of the module
*/
readableIdentifier(requestShortener) {
return requestShortener.shorten(this.readableIdentifierStr);
}
/**
* @param {NeedBuildContext} context context info
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {
return callback(null, !this.buildMeta);
}
/**
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {function(WebpackError=): void} callback callback function
* @returns {void}
*/
build(options, compilation, resolver, fs, callback) {
this.buildMeta = {};
this.buildInfo = {
cacheable: true
};
callback();
}
/**
* @param {CodeGenerationContext} context context for code generation
* @returns {CodeGenerationResult} result
*/
codeGeneration(context) {
const sources = new Map();
sources.set(
"javascript",
new RawSource(`module.exports = ${JSON.stringify(this.url)};`)
);
const data = new Map();
data.set("url", this.url);
const runtimeRequirements = new Set();
runtimeRequirements.add(RuntimeGlobals.module);
return { sources, runtimeRequirements, data };
}
/**
* @param {Hash} hash the hash used to track dependencies
* @param {UpdateHashContext} context context
* @returns {void}
*/
updateHash(hash, context) {
hash.update(this.url);
super.updateHash(hash, context);
}
serialize(context) {
const { write } = context;
write(this.url);
write(this.identifierStr);
write(this.readableIdentifierStr);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.url = read();
this.identifierStr = read();
this.readableIdentifierStr = read();
super.deserialize(context);
}
}
makeSerializable(RawDataUrlModule, "webpack/lib/asset/RawDataUrlModule");
module.exports = RawDataUrlModule;

View File

@ -106,7 +106,7 @@ class ResolverCachePlugin {
* @param {Resolver} resolver the resolver
* @param {Object} resolveContext context for resolving meta info
* @param {Object} request the request info object
* @param {function(Error=, Object=): void} callback callback function
* @param {function((Error | null)=, Object=): void} callback callback function
* @returns {void}
*/
const doRealResolve = (

View File

@ -37,6 +37,7 @@ const webpackSchema = require("../schemas/WebpackOptions.json");
/**
* @typedef {Object} ArgumentConfig
* @property {string} description
* @property {string} [negatedDescription]
* @property {string} path
* @property {boolean} multiple
* @property {"enum"|"string"|"path"|"number"|"boolean"|"RegExp"|"reset"} type
@ -96,11 +97,42 @@ const getArguments = (schema = webpackSchema) => {
*/
const getDescription = path => {
for (const { schema } of path) {
if (schema.cli && schema.cli.helper) continue;
if (schema.cli) {
if (schema.cli.helper) continue;
if (schema.cli.description) return schema.cli.description;
}
if (schema.description) return schema.description;
}
};
/**
*
* @param {PathItem[]} path path in the schema
* @returns {string | undefined} negative description
*/
const getNegatedDescription = path => {
for (const { schema } of path) {
if (schema.cli) {
if (schema.cli.helper) continue;
if (schema.cli.negatedDescription) return schema.cli.negatedDescription;
}
}
};
/**
*
* @param {PathItem[]} path path in the schema
* @returns {string | undefined} reset description
*/
const getResetDescription = path => {
for (const { schema } of path) {
if (schema.cli) {
if (schema.cli.helper) continue;
if (schema.cli.resetDescription) return schema.cli.resetDescription;
}
}
};
/**
*
* @param {any} schemaPart schema
@ -142,13 +174,17 @@ const getArguments = (schema = webpackSchema) => {
const addResetFlag = path => {
const schemaPath = path[0].path;
const name = pathToArgumentName(`${schemaPath}.reset`);
const description = getDescription(path);
const description =
getResetDescription(path) ||
`Clear all items provided in '${schemaPath}' configuration. ${getDescription(
path
)}`;
flags[name] = {
configs: [
{
type: "reset",
multiple: false,
description: `Clear all items provided in '${schemaPath}' configuration. ${description}`,
description,
path: schemaPath
}
],
@ -167,6 +203,7 @@ const getArguments = (schema = webpackSchema) => {
const argConfigBase = schemaToArgumentConfig(path[0].schema);
if (!argConfigBase) return 0;
const negatedDescription = getNegatedDescription(path);
const name = pathToArgumentName(path[0].path);
/** @type {ArgumentConfig} */
const argConfig = {
@ -176,6 +213,10 @@ const getArguments = (schema = webpackSchema) => {
path: path[0].path
};
if (negatedDescription) {
argConfig.negatedDescription = negatedDescription;
}
if (!flags[name]) {
flags[name] = {
configs: [],

View File

@ -184,6 +184,7 @@ const applyWebpackOptionsDefaults = options => {
cache,
syncWebAssembly: options.experiments.syncWebAssembly,
asyncWebAssembly: options.experiments.asyncWebAssembly,
css: options.experiments.css,
futureDefaults
});
@ -239,6 +240,7 @@ const applyWebpackOptionsDefaults = options => {
applyOptimizationDefaults(options.optimization, {
development,
production,
css: options.experiments.css,
records: !!(options.recordsInputPath || options.recordsOutputPath)
});
@ -276,6 +278,7 @@ const applyExperimentsDefaults = (experiments, { production, development }) => {
D(experiments, "lazyCompilation", undefined);
D(experiments, "buildHttp", undefined);
D(experiments, "cacheUnaffected", experiments.futureDefaults);
D(experiments, "css", experiments.futureDefaults);
if (typeof experiments.buildHttp === "object") {
D(experiments.buildHttp, "frozen", production);
@ -458,12 +461,13 @@ const applyJavascriptParserOptionsDefaults = (
* @param {boolean} options.cache is caching enabled
* @param {boolean} options.syncWebAssembly is syncWebAssembly enabled
* @param {boolean} options.asyncWebAssembly is asyncWebAssembly enabled
* @param {boolean} options.css is css enabled
* @param {boolean} options.futureDefaults is future defaults enabled
* @returns {void}
*/
const applyModuleDefaults = (
module,
{ cache, syncWebAssembly, asyncWebAssembly, futureDefaults }
{ cache, syncWebAssembly, asyncWebAssembly, css, futureDefaults }
) => {
if (cache) {
D(module, "unsafeCache", module => {
@ -587,6 +591,41 @@ const applyModuleDefaults = (
...wasm
});
}
if (css) {
const cssRule = {
type: "css",
resolve: {
fullySpecified: true,
preferRelative: true
}
};
const cssModulesRule = {
type: "css/module",
resolve: {
fullySpecified: true
}
};
rules.push({
test: /\.css$/i,
oneOf: [
{
test: /\.module\.css$/i,
...cssModulesRule
},
{
...cssRule
}
]
});
rules.push({
mimetype: "text/css+module",
...cssModulesRule
});
rules.push({
mimetype: "text/css",
...cssRule
});
}
rules.push(
{
dependency: "url",
@ -692,6 +731,20 @@ const applyOutputDefaults = (
}
return output.module ? "[id].mjs" : "[id].js";
});
F(output, "cssFilename", () => {
const filename = output.filename;
if (typeof filename !== "function") {
return filename.replace(/\.[mc]?js(\?|$)/, ".css$1");
}
return "[id].css";
});
F(output, "cssChunkFilename", () => {
const chunkFilename = output.chunkFilename;
if (typeof chunkFilename !== "function") {
return chunkFilename.replace(/\.[mc]?js(\?|$)/, ".css$1");
}
return "[id].css";
});
D(output, "assetModuleFilename", "[hash][ext][query]");
D(output, "webassemblyModuleFilename", "[hash].module.wasm");
D(output, "compareBeforeEmit", true);
@ -1030,12 +1083,13 @@ const applyPerformanceDefaults = (performance, { production }) => {
* @param {Object} options options
* @param {boolean} options.production is production
* @param {boolean} options.development is development
* @param {boolean} options.css is css enabled
* @param {boolean} options.records using records
* @returns {void}
*/
const applyOptimizationDefaults = (
optimization,
{ production, development, records }
{ production, development, css, records }
) => {
D(optimization, "removeAvailableModules", false);
D(optimization, "removeEmptyChunks", true);
@ -1086,7 +1140,9 @@ const applyOptimizationDefaults = (
});
const { splitChunks } = optimization;
if (splitChunks) {
A(splitChunks, "defaultSizeTypes", () => ["javascript", "unknown"]);
A(splitChunks, "defaultSizeTypes", () =>
css ? ["javascript", "css", "unknown"] : ["javascript", "unknown"]
);
D(splitChunks, "hidePathInfo", production);
D(splitChunks, "chunks", "async");
D(splitChunks, "usedExports", optimization.usedExports === true);

View File

@ -297,6 +297,8 @@ const getNormalizedWebpackOptions = config => {
chunkLoading: output.chunkLoading,
chunkLoadingGlobal: output.chunkLoadingGlobal,
chunkLoadTimeout: output.chunkLoadTimeout,
cssFilename: output.cssFilename,
cssChunkFilename: output.cssChunkFilename,
clean: output.clean,
compareBeforeEmit: output.compareBeforeEmit,
crossOriginLoading: output.crossOriginLoading,

View File

@ -79,12 +79,14 @@ class ContainerEntryModule extends Module {
* @returns {string | null} an identifier for library inclusion
*/
libIdent(options) {
return `webpack/container/entry/${this._name}`;
return `${this.layer ? `(${this.layer})/` : ""}webpack/container/entry/${
this._name
}`;
}
/**
* @param {NeedBuildContext} context context info
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {

View File

@ -60,9 +60,9 @@ class FallbackModule extends Module {
* @returns {string | null} an identifier for library inclusion
*/
libIdent(options) {
return `webpack/container/fallback/${this.requests[0]}/and ${
this.requests.length - 1
} more`;
return `${this.layer ? `(${this.layer})/` : ""}webpack/container/fallback/${
this.requests[0]
}/and ${this.requests.length - 1} more`;
}
/**
@ -76,7 +76,7 @@ class FallbackModule extends Module {
/**
* @param {NeedBuildContext} context context info
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {

View File

@ -67,12 +67,14 @@ class RemoteModule extends Module {
* @returns {string | null} an identifier for library inclusion
*/
libIdent(options) {
return `webpack/container/remote/${this.request}`;
return `${this.layer ? `(${this.layer})/` : ""}webpack/container/remote/${
this.request
}`;
}
/**
* @param {NeedBuildContext} context context info
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {

109
lib/css/CssGenerator.js Normal file
View File

@ -0,0 +1,109 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Sergey Melyukov @smelukov
*/
"use strict";
const { ReplaceSource } = require("webpack-sources");
const Generator = require("../Generator");
const InitFragment = require("../InitFragment");
const RuntimeGlobals = require("../RuntimeGlobals");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Generator").GenerateContext} GenerateContext */
/** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */
/** @typedef {import("../NormalModule")} NormalModule */
/** @typedef {import("../util/Hash")} Hash */
const TYPES = new Set(["css"]);
class CssGenerator extends Generator {
constructor() {
super();
}
/**
* @param {NormalModule} module module for which the code should be generated
* @param {GenerateContext} generateContext context for generate
* @returns {Source} generated code
*/
generate(module, generateContext) {
const originalSource = module.originalSource();
const source = new ReplaceSource(originalSource);
const initFragments = [];
const cssExports = new Map();
generateContext.runtimeRequirements.add(RuntimeGlobals.hasCssModules);
const templateContext = {
runtimeTemplate: generateContext.runtimeTemplate,
dependencyTemplates: generateContext.dependencyTemplates,
moduleGraph: generateContext.moduleGraph,
chunkGraph: generateContext.chunkGraph,
module,
runtime: generateContext.runtime,
runtimeRequirements: generateContext.runtimeRequirements,
concatenationScope: generateContext.concatenationScope,
codeGenerationResults: generateContext.codeGenerationResults,
initFragments,
cssExports
};
const handleDependency = dependency => {
const constructor = /** @type {new (...args: any[]) => Dependency} */ (
dependency.constructor
);
const template = generateContext.dependencyTemplates.get(constructor);
if (!template) {
throw new Error(
"No template for dependency: " + dependency.constructor.name
);
}
template.apply(dependency, source, templateContext);
};
module.dependencies.forEach(handleDependency);
if (module.presentationalDependencies !== undefined)
module.presentationalDependencies.forEach(handleDependency);
if (cssExports.size > 0) {
const data = generateContext.getData();
data.set("css-exports", cssExports);
}
return InitFragment.addToSource(source, initFragments, generateContext);
}
/**
* @param {NormalModule} module fresh module
* @returns {Set<string>} available types (do not mutate)
*/
getTypes(module) {
return TYPES;
}
/**
* @param {NormalModule} module the module
* @param {string=} type source type
* @returns {number} estimate size of the module
*/
getSize(module, type) {
const originalSource = module.originalSource();
if (!originalSource) {
return 0;
}
return originalSource.size();
}
/**
* @param {Hash} hash hash that will be modified
* @param {UpdateHashContext} updateHashContext context for updating hash
*/
updateHash(hash, { module }) {}
}
module.exports = CssGenerator;

View File

@ -0,0 +1,449 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { SyncWaterfallHook } = require("tapable");
const Compilation = require("../Compilation");
const RuntimeGlobals = require("../RuntimeGlobals");
const RuntimeModule = require("../RuntimeModule");
const Template = require("../Template");
const compileBooleanMatcher = require("../util/compileBooleanMatcher");
const { chunkHasCss } = require("./CssModulesPlugin");
/** @typedef {import("../Chunk")} Chunk */
/**
* @typedef {Object} JsonpCompilationPluginHooks
* @property {SyncWaterfallHook<[string, Chunk]>} createStylesheet
*/
/** @type {WeakMap<Compilation, JsonpCompilationPluginHooks>} */
const compilationHooksMap = new WeakMap();
class CssLoadingRuntimeModule extends RuntimeModule {
/**
* @param {Compilation} compilation the compilation
* @returns {JsonpCompilationPluginHooks} hooks
*/
static getCompilationHooks(compilation) {
if (!(compilation instanceof Compilation)) {
throw new TypeError(
"The 'compilation' argument must be an instance of Compilation"
);
}
let hooks = compilationHooksMap.get(compilation);
if (hooks === undefined) {
hooks = {
createStylesheet: new SyncWaterfallHook(["source", "chunk"])
};
compilationHooksMap.set(compilation, hooks);
}
return hooks;
}
constructor(runtimeRequirements, runtimeOptions) {
super("css loading", 10);
this._runtimeRequirements = runtimeRequirements;
this.runtimeOptions = runtimeOptions;
}
/**
* @returns {string} runtime code
*/
generate() {
const { compilation, chunk, _runtimeRequirements } = this;
const {
chunkGraph,
runtimeTemplate,
outputOptions: {
crossOriginLoading,
uniqueName,
chunkLoadTimeout: loadTimeout
}
} = compilation;
const fn = RuntimeGlobals.ensureChunkHandlers;
const conditionMap = chunkGraph.getChunkConditionMap(
chunk,
(chunk, chunkGraph) =>
!!chunkGraph.getChunkModulesIterableBySourceType(chunk, "css")
);
const hasCssMatcher = compileBooleanMatcher(conditionMap);
const withLoading =
_runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers) &&
hasCssMatcher !== false;
const withHmr = _runtimeRequirements.has(
RuntimeGlobals.hmrDownloadUpdateHandlers
);
const initialChunkIdsWithCss = new Set();
const initialChunkIdsWithoutCss = new Set();
for (const c of chunk.getAllInitialChunks()) {
(chunkHasCss(c, chunkGraph)
? initialChunkIdsWithCss
: initialChunkIdsWithoutCss
).add(c.id);
}
if (!withLoading && !withHmr && initialChunkIdsWithCss.size === 0) {
return null;
}
const { createStylesheet } =
CssLoadingRuntimeModule.getCompilationHooks(compilation);
const stateExpression = withHmr
? `${RuntimeGlobals.hmrRuntimeStatePrefix}_css`
: undefined;
const code = Template.asString([
"link = document.createElement('link');",
uniqueName
? 'link.setAttribute("data-webpack", uniqueName + ":" + key);'
: "",
"link.setAttribute(loadingAttribute, 1);",
'link.rel = "stylesheet";',
"link.href = url;",
crossOriginLoading
? Template.asString([
"if (link.src.indexOf(window.location.origin + '/') !== 0) {",
Template.indent(
`link.crossOrigin = ${JSON.stringify(crossOriginLoading)};`
),
"}"
])
: ""
]);
const cc = str => str.charCodeAt(0);
return Template.asString([
"// object to store loaded and loading chunks",
"// undefined = chunk not loaded, null = chunk preloaded/prefetched",
"// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded",
`var installedChunks = ${
stateExpression ? `${stateExpression} = ${stateExpression} || ` : ""
}{${Array.from(
initialChunkIdsWithoutCss,
id => `${JSON.stringify(id)}:0`
).join(",")}};`,
"",
uniqueName
? `var uniqueName = ${JSON.stringify(
runtimeTemplate.outputOptions.uniqueName
)};`
: "// data-webpack is not used as build has no uniqueName",
`var loadCssChunkData = ${runtimeTemplate.basicFunction(
"target, link, chunkId",
[
`var data, token = "", token2, exports = {}, exportsWithId = [], exportsWithDashes = [], ${
withHmr ? "moduleIds = [], " : ""
}i = 0, cc = 1;`,
"try { if(!link) link = loadStylesheet(chunkId); data = link.sheet.cssRules; data = data[data.length - 1].style; } catch(e) { data = getComputedStyle(document.head); }",
`data = data.getPropertyValue(${
uniqueName
? runtimeTemplate.concatenation(
"--webpack-",
{ expr: "uniqueName" },
"-",
{ expr: "chunkId" }
)
: runtimeTemplate.concatenation("--webpack-", { expr: "chunkId" })
});`,
"if(!data) return [];",
"for(; cc; i++) {",
Template.indent([
"cc = data.charCodeAt(i);",
`if(cc == ${cc("(")}) { token2 = token; token = ""; }`,
`else if(cc == ${cc(
")"
)}) { exports[token2.replace(/^_/, "")] = token.replace(/^_/, ""); token = ""; }`,
`else if(cc == ${cc("/")} || cc == ${cc(
"%"
)}) { token = token.replace(/^_/, ""); exports[token] = token; exportsWithId.push(token); if(cc == ${cc(
"%"
)}) exportsWithDashes.push(token); token = ""; }`,
`else if(!cc || cc == ${cc(
","
)}) { token = token.replace(/^_/, ""); exportsWithId.forEach(${runtimeTemplate.expressionFunction(
`exports[x] = ${
uniqueName
? runtimeTemplate.concatenation(
{ expr: "uniqueName" },
"-",
{ expr: "token" },
"-",
{ expr: "exports[x]" }
)
: runtimeTemplate.concatenation({ expr: "token" }, "-", {
expr: "exports[x]"
})
}`,
"x"
)}); exportsWithDashes.forEach(${runtimeTemplate.expressionFunction(
`exports[x] = "--" + exports[x]`,
"x"
)}); ${
RuntimeGlobals.makeNamespaceObject
}(exports); target[token] = (${runtimeTemplate.basicFunction(
"exports, module",
`module.exports = exports;`
)}).bind(null, exports); ${
withHmr
? "moduleIds.push(token); target[token].cssExports = exports; "
: ""
}token = ""; exports = {}; exportsWithId.length = 0; }`,
`else if(cc == ${cc("\\")}) { token += data[++i] }`,
`else { token += data[i]; }`
]),
"}",
`${
withHmr ? `if(target == ${RuntimeGlobals.moduleFactories}) ` : ""
}installedChunks[chunkId] = 0;`,
withHmr ? "return moduleIds;" : ""
]
)}`,
'var loadingAttribute = "data-webpack-loading";',
`var loadStylesheet = ${runtimeTemplate.basicFunction(
"chunkId, url, done" + (withHmr ? ", hmr" : ""),
[
'var link, needAttach, key = "chunk-" + chunkId;',
withHmr ? "if(!hmr) {" : "",
'var links = document.getElementsByTagName("link");',
"for(var i = 0; i < links.length; i++) {",
Template.indent([
"var l = links[i];",
`if(l.rel == "stylesheet" && (${
withHmr
? 'l.href.startsWith(url) || l.getAttribute("href").startsWith(url)'
: 'l.href == url || l.getAttribute("href") == url'
}${
uniqueName
? ' || l.getAttribute("data-webpack") == uniqueName + ":" + key'
: ""
})) { link = l; break; }`
]),
"}",
"if(!done) return link;",
withHmr ? "}" : "",
"if(!link) {",
Template.indent([
"needAttach = true;",
createStylesheet.call(code, this.chunk)
]),
"}",
`var onLinkComplete = ${runtimeTemplate.basicFunction(
"prev, event",
Template.asString([
"link.onerror = link.onload = null;",
"link.removeAttribute(loadingAttribute);",
"clearTimeout(timeout);",
'if(event && event.type != "load") link.parentNode.removeChild(link)',
"done(event);",
"if(prev) return prev(event);"
])
)};`,
"if(link.getAttribute(loadingAttribute)) {",
Template.indent([
`var timeout = setTimeout(onLinkComplete.bind(null, undefined, { type: 'timeout', target: link }), ${loadTimeout});`,
"link.onerror = onLinkComplete.bind(null, link.onerror);",
"link.onload = onLinkComplete.bind(null, link.onload);"
]),
"} else onLinkComplete(undefined, { type: 'load', target: link });", // We assume any existing stylesheet is render blocking
withHmr ? "hmr ? document.head.insertBefore(link, hmr) :" : "",
"needAttach && document.head.appendChild(link);",
"return link;"
]
)};`,
initialChunkIdsWithCss.size > 2
? `${JSON.stringify(
Array.from(initialChunkIdsWithCss)
)}.forEach(loadCssChunkData.bind(null, ${
RuntimeGlobals.moduleFactories
}, 0));`
: initialChunkIdsWithCss.size > 0
? `${Array.from(
initialChunkIdsWithCss,
id =>
`loadCssChunkData(${
RuntimeGlobals.moduleFactories
}, 0, ${JSON.stringify(id)});`
).join("")}`
: "// no initial css",
"",
withLoading
? Template.asString([
`${fn}.css = ${runtimeTemplate.basicFunction(
"chunkId, promises",
hasCssMatcher !== false
? [
"// css chunk loading",
`var installedChunkData = ${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;`,
'if(installedChunkData !== 0) { // 0 means "already installed".',
Template.indent([
"",
'// a Promise means "currently loading".',
"if(installedChunkData) {",
Template.indent([
"promises.push(installedChunkData[2]);"
]),
"} else {",
Template.indent([
hasCssMatcher === true
? "if(true) { // all chunks have CSS"
: `if(${hasCssMatcher("chunkId")}) {`,
Template.indent([
"// setup Promise in chunk cache",
`var promise = new Promise(${runtimeTemplate.expressionFunction(
`installedChunkData = installedChunks[chunkId] = [resolve, reject]`,
"resolve, reject"
)});`,
"promises.push(installedChunkData[2] = promise);",
"",
"// start chunk loading",
`var url = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkCssFilename}(chunkId);`,
"// create error before stack unwound to get useful stacktrace later",
"var error = new Error();",
`var loadingEnded = ${runtimeTemplate.basicFunction(
"event",
[
`if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId)) {`,
Template.indent([
"installedChunkData = installedChunks[chunkId];",
"if(installedChunkData !== 0) installedChunks[chunkId] = undefined;",
"if(installedChunkData) {",
Template.indent([
'if(event.type !== "load") {',
Template.indent([
"var errorType = event && event.type;",
"var realSrc = event && event.target && event.target.src;",
"error.message = 'Loading css chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';",
"error.name = 'ChunkLoadError';",
"error.type = errorType;",
"error.request = realSrc;",
"installedChunkData[1](error);"
]),
"} else {",
Template.indent([
`loadCssChunkData(${RuntimeGlobals.moduleFactories}, link, chunkId);`,
"installedChunkData[0]();"
]),
"}"
]),
"}"
]),
"}"
]
)};`,
"var link = loadStylesheet(chunkId, url, loadingEnded);"
]),
"} else installedChunks[chunkId] = 0;"
]),
"}"
]),
"}"
]
: "installedChunks[chunkId] = 0;"
)};`
])
: "// no chunk loading",
"",
withHmr
? Template.asString([
"var oldTags = [];",
"var newTags = [];",
`var applyHandler = ${runtimeTemplate.basicFunction("options", [
`return { dispose: ${runtimeTemplate.basicFunction(
"",
[]
)}, apply: ${runtimeTemplate.basicFunction("", [
"var moduleIds = [];",
`newTags.forEach(${runtimeTemplate.expressionFunction(
"info[1].sheet.disabled = false",
"info"
)});`,
"while(oldTags.length) {",
Template.indent([
"var oldTag = oldTags.pop();",
"if(oldTag.parentNode) oldTag.parentNode.removeChild(oldTag);"
]),
"}",
"while(newTags.length) {",
Template.indent([
`var info = newTags.pop();`,
`var chunkModuleIds = loadCssChunkData(${RuntimeGlobals.moduleFactories}, info[1], info[0]);`,
`chunkModuleIds.forEach(${runtimeTemplate.expressionFunction(
"moduleIds.push(id)",
"id"
)});`
]),
"}",
"return moduleIds;"
])} };`
])}`,
`var cssTextKey = ${runtimeTemplate.returningFunction(
`Array.from(link.sheet.cssRules, ${runtimeTemplate.returningFunction(
"r.cssText",
"r"
)}).join()`,
"link"
)}`,
`${
RuntimeGlobals.hmrDownloadUpdateHandlers
}.css = ${runtimeTemplate.basicFunction(
"chunkIds, removedChunks, removedModules, promises, applyHandlers, updatedModulesList",
[
"applyHandlers.push(applyHandler);",
`chunkIds.forEach(${runtimeTemplate.basicFunction("chunkId", [
`var filename = ${RuntimeGlobals.getChunkCssFilename}(chunkId);`,
`var url = ${RuntimeGlobals.publicPath} + filename;`,
"var oldTag = loadStylesheet(chunkId, url);",
"if(!oldTag) return;",
`promises.push(new Promise(${runtimeTemplate.basicFunction(
"resolve, reject",
[
`var link = loadStylesheet(chunkId, url + (url.indexOf("?") < 0 ? "?" : "&") + "hmr=" + Date.now(), ${runtimeTemplate.basicFunction(
"event",
[
'if(event.type !== "load") {',
Template.indent([
"var errorType = event && event.type;",
"var realSrc = event && event.target && event.target.src;",
"error.message = 'Loading css hot update chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';",
"error.name = 'ChunkLoadError';",
"error.type = errorType;",
"error.request = realSrc;",
"reject(error);"
]),
"} else {",
Template.indent([
"try { if(cssTextKey(oldTag) == cssTextKey(link)) { if(link.parentNode) link.parentNode.removeChild(link); return resolve(); } } catch(e) {}",
"var factories = {};",
"loadCssChunkData(factories, link, chunkId);",
`Object.keys(factories).forEach(${runtimeTemplate.expressionFunction(
"updatedModulesList.push(id)",
"id"
)})`,
"link.sheet.disabled = true;",
"oldTags.push(oldTag);",
"newTags.push([chunkId, link]);",
"resolve();"
]),
"}"
]
)}, oldTag);`
]
)}));`
])});`
]
)}`
])
: "// no hmr"
]);
}
}
module.exports = CssLoadingRuntimeModule;

447
lib/css/CssModulesPlugin.js Normal file
View File

@ -0,0 +1,447 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const { ConcatSource } = require("webpack-sources");
const HotUpdateChunk = require("../HotUpdateChunk");
const RuntimeGlobals = require("../RuntimeGlobals");
const SelfModuleFactory = require("../SelfModuleFactory");
const CssExportDependency = require("../dependencies/CssExportDependency");
const CssImportDependency = require("../dependencies/CssImportDependency");
const CssLocalIdentifierDependency = require("../dependencies/CssLocalIdentifierDependency");
const CssSelfLocalIdentifierDependency = require("../dependencies/CssSelfLocalIdentifierDependency");
const CssUrlDependency = require("../dependencies/CssUrlDependency");
const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
const { compareModulesByIdentifier } = require("../util/comparators");
const createSchemaValidation = require("../util/create-schema-validation");
const createHash = require("../util/createHash");
const memoize = require("../util/memoize");
const CssGenerator = require("./CssGenerator");
const CssParser = require("./CssParser");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
const getCssLoadingRuntimeModule = memoize(() =>
require("./CssLoadingRuntimeModule")
);
const getSchema = name => {
const { definitions } = require("../../schemas/WebpackOptions.json");
return {
definitions,
oneOf: [{ $ref: `#/definitions/${name}` }]
};
};
const validateGeneratorOptions = createSchemaValidation(
require("../../schemas/plugins/css/CssGeneratorOptions.check.js"),
() => getSchema("CssGeneratorOptions"),
{
name: "Css Modules Plugin",
baseDataPath: "parser"
}
);
const validateParserOptions = createSchemaValidation(
require("../../schemas/plugins/css/CssParserOptions.check.js"),
() => getSchema("CssParserOptions"),
{
name: "Css Modules Plugin",
baseDataPath: "parser"
}
);
const escapeCss = (str, omitOptionalUnderscore) => {
const escaped = `${str}`.replace(
// cspell:word uffff
/[^a-zA-Z0-9_\u0081-\uffff-]/g,
s => `\\${s}`
);
return !omitOptionalUnderscore && /^(?!--)[0-9_-]/.test(escaped)
? `_${escaped}`
: escaped;
};
const plugin = "CssModulesPlugin";
class CssModulesPlugin {
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
compiler.hooks.compilation.tap(
plugin,
(compilation, { normalModuleFactory }) => {
const selfFactory = new SelfModuleFactory(compilation.moduleGraph);
compilation.dependencyFactories.set(
CssUrlDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
CssUrlDependency,
new CssUrlDependency.Template()
);
compilation.dependencyTemplates.set(
CssLocalIdentifierDependency,
new CssLocalIdentifierDependency.Template()
);
compilation.dependencyFactories.set(
CssSelfLocalIdentifierDependency,
selfFactory
);
compilation.dependencyTemplates.set(
CssSelfLocalIdentifierDependency,
new CssSelfLocalIdentifierDependency.Template()
);
compilation.dependencyTemplates.set(
CssExportDependency,
new CssExportDependency.Template()
);
compilation.dependencyFactories.set(
CssImportDependency,
normalModuleFactory
);
compilation.dependencyTemplates.set(
CssImportDependency,
new CssImportDependency.Template()
);
compilation.dependencyTemplates.set(
StaticExportsDependency,
new StaticExportsDependency.Template()
);
normalModuleFactory.hooks.createParser
.for("css")
.tap(plugin, parserOptions => {
validateParserOptions(parserOptions);
return new CssParser();
});
normalModuleFactory.hooks.createParser
.for("css/global")
.tap(plugin, parserOptions => {
validateParserOptions(parserOptions);
return new CssParser({
allowPseudoBlocks: false,
allowModeSwitch: false
});
});
normalModuleFactory.hooks.createParser
.for("css/module")
.tap(plugin, parserOptions => {
validateParserOptions(parserOptions);
return new CssParser({
defaultMode: "local"
});
});
normalModuleFactory.hooks.createGenerator
.for("css")
.tap(plugin, generatorOptions => {
validateGeneratorOptions(generatorOptions);
return new CssGenerator();
});
normalModuleFactory.hooks.createGenerator
.for("css/global")
.tap(plugin, generatorOptions => {
validateGeneratorOptions(generatorOptions);
return new CssGenerator();
});
normalModuleFactory.hooks.createGenerator
.for("css/module")
.tap(plugin, generatorOptions => {
validateGeneratorOptions(generatorOptions);
return new CssGenerator();
});
const orderedCssModulesPerChunk = new WeakMap();
compilation.hooks.afterCodeGeneration.tap("CssModulesPlugin", () => {
const { chunkGraph } = compilation;
for (const chunk of compilation.chunks) {
if (CssModulesPlugin.chunkHasCss(chunk, chunkGraph)) {
orderedCssModulesPerChunk.set(
chunk,
this.getOrderedChunkCssModules(chunk, chunkGraph, compilation)
);
}
}
});
compilation.hooks.contentHash.tap("CssModulesPlugin", chunk => {
const {
chunkGraph,
outputOptions: {
hashSalt,
hashDigest,
hashDigestLength,
hashFunction
}
} = compilation;
const modules = orderedCssModulesPerChunk.get(chunk);
if (modules === undefined) return;
const hash = createHash(hashFunction);
if (hashSalt) hash.update(hashSalt);
for (const module of modules) {
hash.update(chunkGraph.getModuleHash(module, chunk.runtime));
}
const digest = /** @type {string} */ (hash.digest(hashDigest));
chunk.contentHash.css = digest.substr(0, hashDigestLength);
});
compilation.hooks.renderManifest.tap(plugin, (result, options) => {
const { chunkGraph } = compilation;
const { hash, chunk, codeGenerationResults } = options;
if (chunk instanceof HotUpdateChunk) return result;
const modules = orderedCssModulesPerChunk.get(chunk);
if (modules !== undefined) {
result.push({
render: () =>
this.renderChunk({
chunk,
chunkGraph,
codeGenerationResults,
uniqueName: compilation.outputOptions.uniqueName,
modules
}),
filenameTemplate: CssModulesPlugin.getChunkFilenameTemplate(
chunk,
compilation.outputOptions
),
pathOptions: {
hash,
runtime: chunk.runtime,
chunk,
contentHashType: "css"
},
identifier: `css${chunk.id}`,
hash: chunk.contentHash.css
});
}
return result;
});
const enabledChunks = new WeakSet();
const handler = (chunk, set) => {
if (enabledChunks.has(chunk)) {
return;
}
enabledChunks.add(chunk);
set.add(RuntimeGlobals.publicPath);
set.add(RuntimeGlobals.getChunkCssFilename);
set.add(RuntimeGlobals.hasOwnProperty);
set.add(RuntimeGlobals.moduleFactoriesAddOnly);
set.add(RuntimeGlobals.makeNamespaceObject);
const CssLoadingRuntimeModule = getCssLoadingRuntimeModule();
compilation.addRuntimeModule(chunk, new CssLoadingRuntimeModule(set));
};
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.hasCssModules)
.tap(plugin, handler);
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.ensureChunkHandlers)
.tap(plugin, handler);
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.hmrDownloadUpdateHandlers)
.tap(plugin, handler);
}
);
}
getModulesInOrder(chunk, modules, compilation) {
if (!modules) return [];
const modulesList = [...modules];
// Get ordered list of modules per chunk group
// Lists are in reverse order to allow to use Array.pop()
const modulesByChunkGroup = Array.from(chunk.groupsIterable, chunkGroup => {
const sortedModules = modulesList
.map(module => {
return {
module,
index: chunkGroup.getModulePostOrderIndex(module)
};
})
.filter(item => item.index !== undefined)
.sort((a, b) => b.index - a.index)
.map(item => item.module);
return { list: sortedModules, set: new Set(sortedModules) };
});
if (modulesByChunkGroup.length === 1)
return modulesByChunkGroup[0].list.reverse();
const compareModuleLists = ({ list: a }, { list: b }) => {
if (a.length === 0) {
return b.length === 0 ? 0 : 1;
} else {
if (b.length === 0) return -1;
return compareModulesByIdentifier(a[a.length - 1], b[b.length - 1]);
}
};
modulesByChunkGroup.sort(compareModuleLists);
const finalModules = [];
for (;;) {
const failedModules = new Set();
const list = modulesByChunkGroup[0].list;
if (list.length === 0) {
// done, everything empty
break;
}
let selectedModule = list[list.length - 1];
let hasFailed = undefined;
outer: for (;;) {
for (const { list, set } of modulesByChunkGroup) {
if (list.length === 0) continue;
const lastModule = list[list.length - 1];
if (lastModule === selectedModule) continue;
if (!set.has(selectedModule)) continue;
failedModules.add(selectedModule);
if (failedModules.has(lastModule)) {
// There is a conflict, try other alternatives
hasFailed = lastModule;
continue;
}
selectedModule = lastModule;
hasFailed = false;
continue outer; // restart
}
break;
}
if (hasFailed) {
// There is a not resolve-able conflict with the selectedModule
if (compilation) {
// TODO print better warning
compilation.warnings.push(
new Error(
`chunk ${
chunk.name || chunk.id
}\nConflicting order between ${hasFailed.readableIdentifier(
compilation.requestShortener
)} and ${selectedModule.readableIdentifier(
compilation.requestShortener
)}`
)
);
}
selectedModule = hasFailed;
}
// Insert the selected module into the final modules list
finalModules.push(selectedModule);
// Remove the selected module from all lists
for (const { list, set } of modulesByChunkGroup) {
const lastModule = list[list.length - 1];
if (lastModule === selectedModule) list.pop();
else if (hasFailed && set.has(selectedModule)) {
const idx = list.indexOf(selectedModule);
if (idx >= 0) list.splice(idx, 1);
}
}
modulesByChunkGroup.sort(compareModuleLists);
}
return finalModules;
}
getOrderedChunkCssModules(chunk, chunkGraph, compilation) {
return [
...this.getModulesInOrder(
chunk,
chunkGraph.getOrderedChunkModulesIterableBySourceType(
chunk,
"css-import",
compareModulesByIdentifier
),
compilation
),
...this.getModulesInOrder(
chunk,
chunkGraph.getOrderedChunkModulesIterableBySourceType(
chunk,
"css",
compareModulesByIdentifier
),
compilation
)
];
}
renderChunk({
uniqueName,
chunk,
chunkGraph,
codeGenerationResults,
modules
}) {
const source = new ConcatSource();
const metaData = [];
for (const module of modules) {
try {
const codeGenResult = codeGenerationResults.get(module, chunk.runtime);
const s =
codeGenResult.sources.get("css") ||
codeGenResult.sources.get("css-import");
if (s) {
source.add(s);
source.add("\n");
}
const exports =
codeGenResult.data && codeGenResult.data.get("css-exports");
const moduleId = chunkGraph.getModuleId(module) + "";
metaData.push(
`${
exports
? Array.from(exports, ([n, v]) => {
const shortcutValue = `${
uniqueName ? uniqueName + "-" : ""
}${moduleId}-${n}`;
return v === shortcutValue
? `${escapeCss(n)}/`
: v === "--" + shortcutValue
? `${escapeCss(n)}%`
: `${escapeCss(n)}(${escapeCss(v)})`;
}).join("")
: ""
}${escapeCss(moduleId)}`
);
} catch (e) {
e.message += `\nduring rendering of css ${module.identifier()}`;
throw e;
}
}
source.add(
`head{--webpack-${escapeCss(
(uniqueName ? uniqueName + "-" : "") + chunk.id,
true
)}:${metaData.join(",")};}`
);
return source;
}
static getChunkFilenameTemplate(chunk, outputOptions) {
if (chunk.cssFilenameTemplate) {
return chunk.cssFilenameTemplate;
} else if (chunk.canBeInitial()) {
return outputOptions.cssFilename;
} else {
return outputOptions.cssChunkFilename;
}
}
static chunkHasCss(chunk, chunkGraph) {
return (
!!chunkGraph.getChunkModulesIterableBySourceType(chunk, "css") ||
!!chunkGraph.getChunkModulesIterableBySourceType(chunk, "css-import")
);
}
}
module.exports = CssModulesPlugin;

618
lib/css/CssParser.js Normal file
View File

@ -0,0 +1,618 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const Parser = require("../Parser");
const ConstDependency = require("../dependencies/ConstDependency");
const CssExportDependency = require("../dependencies/CssExportDependency");
const CssImportDependency = require("../dependencies/CssImportDependency");
const CssLocalIdentifierDependency = require("../dependencies/CssLocalIdentifierDependency");
const CssSelfLocalIdentifierDependency = require("../dependencies/CssSelfLocalIdentifierDependency");
const CssUrlDependency = require("../dependencies/CssUrlDependency");
const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
const walkCssTokens = require("./walkCssTokens");
/** @typedef {import("../Parser").ParserState} ParserState */
/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
const CC_LEFT_CURLY = "{".charCodeAt(0);
const CC_RIGHT_CURLY = "}".charCodeAt(0);
const CC_COLON = ":".charCodeAt(0);
const CC_SLASH = "/".charCodeAt(0);
const CC_SEMICOLON = ";".charCodeAt(0);
const cssUnescape = str => {
return str.replace(/\\([0-9a-fA-F]{1,6}[ \t\n\r\f]?|[\s\S])/g, match => {
if (match.length > 2) {
return String.fromCharCode(parseInt(match.slice(1).trim(), 16));
} else {
return match[1];
}
});
};
class LocConverter {
constructor(input) {
this._input = input;
this.line = 1;
this.column = 0;
this.pos = 0;
}
get(pos) {
if (this.pos !== pos) {
if (this.pos < pos) {
const str = this._input.slice(this.pos, pos);
let i = str.lastIndexOf("\n");
if (i === -1) {
this.column += str.length;
} else {
this.column = str.length - i - 1;
this.line++;
while (i > 0 && (i = str.lastIndexOf("\n", i - 1)) !== -1)
this.line++;
}
} else {
let i = this._input.lastIndexOf("\n", this.pos);
while (i >= pos) {
this.line--;
i = i > 0 ? this._input.lastIndexOf("\n", i - 1) : -1;
}
this.column = pos - i;
}
this.pos = pos;
}
return this;
}
}
const CSS_MODE_TOP_LEVEL = 0;
const CSS_MODE_IN_RULE = 1;
const CSS_MODE_IN_LOCAL_RULE = 2;
const CSS_MODE_AT_IMPORT_EXPECT_URL = 3;
// TODO implement layer and supports for @import
const CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS = 4;
const CSS_MODE_AT_IMPORT_EXPECT_MEDIA = 5;
const CSS_MODE_AT_OTHER = 6;
const explainMode = mode => {
switch (mode) {
case CSS_MODE_TOP_LEVEL:
return "parsing top level css";
case CSS_MODE_IN_RULE:
return "parsing css rule content (global)";
case CSS_MODE_IN_LOCAL_RULE:
return "parsing css rule content (local)";
case CSS_MODE_AT_IMPORT_EXPECT_URL:
return "parsing @import (expecting url)";
case CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS:
return "parsing @import (expecting optionally supports or media query)";
case CSS_MODE_AT_IMPORT_EXPECT_MEDIA:
return "parsing @import (expecting optionally media query)";
case CSS_MODE_AT_OTHER:
return "parsing at-rule";
default:
return mode;
}
};
class CssParser extends Parser {
constructor({
allowPseudoBlocks = true,
allowModeSwitch = true,
defaultMode = "global"
} = {}) {
super();
this.allowPseudoBlocks = allowPseudoBlocks;
this.allowModeSwitch = allowModeSwitch;
this.defaultMode = defaultMode;
}
/**
* @param {string | Buffer | PreparsedAst} source the source to parse
* @param {ParserState} state the parser state
* @returns {ParserState} the parser state
*/
parse(source, state) {
if (Buffer.isBuffer(source)) {
source = source.toString("utf-8");
} else if (typeof source === "object") {
throw new Error("webpackAst is unexpected for the CssParser");
}
if (source[0] === "\ufeff") {
source = source.slice(1);
}
const module = state.module;
const declaredCssVariables = new Set();
const locConverter = new LocConverter(source);
let mode = CSS_MODE_TOP_LEVEL;
let modePos = 0;
let modeNestingLevel = 0;
let modeData = undefined;
let singleClassSelector = undefined;
let lastIdentifier = undefined;
const modeStack = [];
const isTopLevelLocal = () =>
modeData === "local" ||
(this.defaultMode === "local" && modeData === undefined);
const eatWhiteLine = (input, pos) => {
for (;;) {
const cc = input.charCodeAt(pos);
if (cc === 32 || cc === 9) {
pos++;
continue;
}
if (cc === 10) pos++;
break;
}
return pos;
};
const eatUntil = chars => {
const charCodes = Array.from({ length: chars.length }, (_, i) =>
chars.charCodeAt(i)
);
const arr = Array.from(
{ length: charCodes.reduce((a, b) => Math.max(a, b), 0) + 1 },
() => false
);
charCodes.forEach(cc => (arr[cc] = true));
return (input, pos) => {
for (;;) {
const cc = input.charCodeAt(pos);
if (cc < arr.length && arr[cc]) {
return pos;
}
pos++;
if (pos === input.length) return pos;
}
};
};
const eatText = (input, pos, eater) => {
let text = "";
for (;;) {
if (input.charCodeAt(pos) === CC_SLASH) {
const newPos = walkCssTokens.eatComments(input, pos);
if (pos !== newPos) {
pos = newPos;
if (pos === input.length) break;
} else {
text += "/";
pos++;
if (pos === input.length) break;
}
}
const newPos = eater(input, pos);
if (pos !== newPos) {
text += input.slice(pos, newPos);
pos = newPos;
} else {
break;
}
if (pos === input.length) break;
}
return [pos, text.trimRight()];
};
const eatExportName = eatUntil(":};/");
const eatExportValue = eatUntil("};/");
const parseExports = (input, pos) => {
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
const cc = input.charCodeAt(pos);
if (cc !== CC_LEFT_CURLY)
throw new Error(
`Unexpected ${input[pos]} at ${pos} during parsing of ':export' (expected '{')`
);
pos++;
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
for (;;) {
if (input.charCodeAt(pos) === CC_RIGHT_CURLY) break;
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
if (pos === input.length) return pos;
let start = pos;
let name;
[pos, name] = eatText(input, pos, eatExportName);
if (pos === input.length) return pos;
if (input.charCodeAt(pos) !== CC_COLON) {
throw new Error(
`Unexpected ${input[pos]} at ${pos} during parsing of export name in ':export' (expected ':')`
);
}
pos++;
if (pos === input.length) return pos;
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
if (pos === input.length) return pos;
let value;
[pos, value] = eatText(input, pos, eatExportValue);
if (pos === input.length) return pos;
const cc = input.charCodeAt(pos);
if (cc === CC_SEMICOLON) {
pos++;
if (pos === input.length) return pos;
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
if (pos === input.length) return pos;
} else if (cc !== CC_RIGHT_CURLY) {
throw new Error(
`Unexpected ${input[pos]} at ${pos} during parsing of export value in ':export' (expected ';' or '}')`
);
}
const dep = new CssExportDependency(name, value);
const { line: sl, column: sc } = locConverter.get(start);
const { line: el, column: ec } = locConverter.get(pos);
dep.setLoc(sl, sc, el, ec);
module.addDependency(dep);
}
pos++;
if (pos === input.length) return pos;
pos = eatWhiteLine(input, pos);
return pos;
};
const eatPropertyName = eatUntil(":{};");
const processLocalDeclaration = (input, pos) => {
modeData = undefined;
const start = pos;
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
const propertyNameStart = pos;
const [propertyNameEnd, propertyName] = eatText(
input,
pos,
eatPropertyName
);
if (input.charCodeAt(propertyNameEnd) !== CC_COLON) return start;
pos = propertyNameEnd + 1;
if (propertyName.startsWith("--")) {
// CSS Variable
const { line: sl, column: sc } = locConverter.get(propertyNameStart);
const { line: el, column: ec } = locConverter.get(propertyNameEnd);
const name = propertyName.slice(2);
const dep = new CssLocalIdentifierDependency(
name,
[propertyNameStart, propertyNameEnd],
"--"
);
dep.setLoc(sl, sc, el, ec);
module.addDependency(dep);
declaredCssVariables.add(name);
} else if (
propertyName === "animation-name" ||
propertyName === "animation"
) {
modeData = "animation";
lastIdentifier = undefined;
}
return pos;
};
const processDeclarationValueDone = (input, pos) => {
if (modeData === "animation" && lastIdentifier) {
const { line: sl, column: sc } = locConverter.get(lastIdentifier[0]);
const { line: el, column: ec } = locConverter.get(lastIdentifier[1]);
const name = input.slice(lastIdentifier[0], lastIdentifier[1]);
const dep = new CssSelfLocalIdentifierDependency(name, lastIdentifier);
dep.setLoc(sl, sc, el, ec);
module.addDependency(dep);
}
};
const eatKeyframes = eatUntil("{};/");
const eatNameInVar = eatUntil(",)};/");
walkCssTokens(source, {
isSelector: () => {
return mode !== CSS_MODE_IN_RULE && mode !== CSS_MODE_IN_LOCAL_RULE;
},
url: (input, start, end, contentStart, contentEnd) => {
const value = cssUnescape(input.slice(contentStart, contentEnd));
switch (mode) {
case CSS_MODE_AT_IMPORT_EXPECT_URL: {
modeData.url = value;
mode = CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS;
break;
}
case CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS:
case CSS_MODE_AT_IMPORT_EXPECT_MEDIA:
throw new Error(
`Unexpected ${input.slice(
start,
end
)} at ${start} during ${explainMode(mode)}`
);
default: {
const dep = new CssUrlDependency(value, [start, end], "url");
const { line: sl, column: sc } = locConverter.get(start);
const { line: el, column: ec } = locConverter.get(end);
dep.setLoc(sl, sc, el, ec);
module.addDependency(dep);
module.addCodeGenerationDependency(dep);
break;
}
}
return end;
},
string: (input, start, end) => {
switch (mode) {
case CSS_MODE_AT_IMPORT_EXPECT_URL: {
modeData.url = cssUnescape(input.slice(start + 1, end - 1));
mode = CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS;
break;
}
}
return end;
},
atKeyword: (input, start, end) => {
const name = input.slice(start, end);
if (name === "@namespace") {
throw new Error("@namespace is not supported in bundled CSS");
}
if (name === "@import") {
if (mode !== CSS_MODE_TOP_LEVEL) {
throw new Error(
`Unexpected @import at ${start} during ${explainMode(mode)}`
);
}
mode = CSS_MODE_AT_IMPORT_EXPECT_URL;
modePos = end;
modeData = {
start: start,
url: undefined,
supports: undefined
};
}
if (name === "@keyframes") {
let pos = end;
pos = walkCssTokens.eatWhitespaceAndComments(input, pos);
if (pos === input.length) return pos;
const [newPos, name] = eatText(input, pos, eatKeyframes);
const { line: sl, column: sc } = locConverter.get(pos);
const { line: el, column: ec } = locConverter.get(newPos);
const dep = new CssLocalIdentifierDependency(name, [pos, newPos]);
dep.setLoc(sl, sc, el, ec);
module.addDependency(dep);
pos = newPos;
if (pos === input.length) return pos;
if (input.charCodeAt(pos) !== CC_LEFT_CURLY) {
throw new Error(
`Unexpected ${input[pos]} at ${pos} during parsing of @keyframes (expected '{')`
);
}
mode = CSS_MODE_IN_LOCAL_RULE;
modeNestingLevel = 1;
return pos + 1;
}
return end;
},
semicolon: (input, start, end) => {
switch (mode) {
case CSS_MODE_AT_IMPORT_EXPECT_URL:
throw new Error(`Expected URL for @import at ${start}`);
case CSS_MODE_AT_IMPORT_EXPECT_MEDIA:
case CSS_MODE_AT_IMPORT_EXPECT_SUPPORTS: {
const { line: sl, column: sc } = locConverter.get(modeData.start);
const { line: el, column: ec } = locConverter.get(end);
end = eatWhiteLine(input, end);
const media = input.slice(modePos, start).trim();
const dep = new CssImportDependency(
modeData.url,
[modeData.start, end],
modeData.supports,
media
);
dep.setLoc(sl, sc, el, ec);
module.addDependency(dep);
break;
}
case CSS_MODE_IN_LOCAL_RULE: {
processDeclarationValueDone(input, start);
return processLocalDeclaration(input, end);
}
case CSS_MODE_IN_RULE: {
return end;
}
}
mode = CSS_MODE_TOP_LEVEL;
modeData = undefined;
singleClassSelector = undefined;
return end;
},
leftCurlyBracket: (input, start, end) => {
switch (mode) {
case CSS_MODE_TOP_LEVEL:
mode = isTopLevelLocal()
? CSS_MODE_IN_LOCAL_RULE
: CSS_MODE_IN_RULE;
modeNestingLevel = 1;
if (mode === CSS_MODE_IN_LOCAL_RULE)
return processLocalDeclaration(input, end);
break;
case CSS_MODE_IN_RULE:
case CSS_MODE_IN_LOCAL_RULE:
modeNestingLevel++;
break;
}
return end;
},
rightCurlyBracket: (input, start, end) => {
switch (mode) {
case CSS_MODE_IN_LOCAL_RULE:
processDeclarationValueDone(input, start);
/* falls through */
case CSS_MODE_IN_RULE:
if (--modeNestingLevel === 0) {
mode = CSS_MODE_TOP_LEVEL;
modeData = undefined;
singleClassSelector = undefined;
}
break;
}
return end;
},
id: (input, start, end) => {
singleClassSelector = false;
switch (mode) {
case CSS_MODE_TOP_LEVEL:
if (isTopLevelLocal()) {
const name = input.slice(start + 1, end);
const dep = new CssLocalIdentifierDependency(name, [
start + 1,
end
]);
const { line: sl, column: sc } = locConverter.get(start);
const { line: el, column: ec } = locConverter.get(end);
dep.setLoc(sl, sc, el, ec);
module.addDependency(dep);
}
break;
}
return end;
},
identifier: (input, start, end) => {
singleClassSelector = false;
switch (mode) {
case CSS_MODE_IN_LOCAL_RULE:
if (modeData === "animation") {
lastIdentifier = [start, end];
}
break;
}
return end;
},
class: (input, start, end) => {
switch (mode) {
case CSS_MODE_TOP_LEVEL: {
if (isTopLevelLocal()) {
const name = input.slice(start + 1, end);
const dep = new CssLocalIdentifierDependency(name, [
start + 1,
end
]);
const { line: sl, column: sc } = locConverter.get(start);
const { line: el, column: ec } = locConverter.get(end);
dep.setLoc(sl, sc, el, ec);
module.addDependency(dep);
if (singleClassSelector === undefined) singleClassSelector = name;
} else {
singleClassSelector = false;
}
break;
}
}
return end;
},
leftParenthesis: (input, start, end) => {
switch (mode) {
case CSS_MODE_TOP_LEVEL: {
modeStack.push(false);
break;
}
}
return end;
},
rightParenthesis: (input, start, end) => {
switch (mode) {
case CSS_MODE_TOP_LEVEL: {
const newModeData = modeStack.pop();
if (newModeData !== false) {
modeData = newModeData;
const dep = new ConstDependency("", [start, end]);
module.addPresentationalDependency(dep);
}
break;
}
}
return end;
},
pseudoClass: (input, start, end) => {
singleClassSelector = false;
switch (mode) {
case CSS_MODE_TOP_LEVEL: {
const name = input.slice(start, end);
if (this.allowModeSwitch && name === ":global") {
modeData = "global";
const dep = new ConstDependency("", [start, end]);
module.addPresentationalDependency(dep);
} else if (this.allowModeSwitch && name === ":local") {
modeData = "local";
const dep = new ConstDependency("", [start, end]);
module.addPresentationalDependency(dep);
} else if (this.allowPseudoBlocks && name === ":export") {
const pos = parseExports(input, end);
const dep = new ConstDependency("", [start, pos]);
module.addPresentationalDependency(dep);
return pos;
}
break;
}
}
return end;
},
pseudoFunction: (input, start, end) => {
switch (mode) {
case CSS_MODE_TOP_LEVEL: {
const name = input.slice(start, end - 1);
if (this.allowModeSwitch && name === ":global") {
modeStack.push(modeData);
modeData = "global";
const dep = new ConstDependency("", [start, end]);
module.addPresentationalDependency(dep);
} else if (this.allowModeSwitch && name === ":local") {
modeStack.push(modeData);
modeData = "local";
const dep = new ConstDependency("", [start, end]);
module.addPresentationalDependency(dep);
} else {
modeStack.push(false);
}
break;
}
}
return end;
},
function: (input, start, end) => {
switch (mode) {
case CSS_MODE_IN_LOCAL_RULE: {
const name = input.slice(start, end - 1);
if (name === "var") {
let pos = walkCssTokens.eatWhitespaceAndComments(input, end);
if (pos === input.length) return pos;
const [newPos, name] = eatText(input, pos, eatNameInVar);
if (!name.startsWith("--")) return end;
const { line: sl, column: sc } = locConverter.get(pos);
const { line: el, column: ec } = locConverter.get(newPos);
const dep = new CssSelfLocalIdentifierDependency(
name.slice(2),
[pos, newPos],
"--",
declaredCssVariables
);
dep.setLoc(sl, sc, el, ec);
module.addDependency(dep);
return newPos;
}
break;
}
}
return end;
},
comma: (input, start, end) => {
switch (mode) {
case CSS_MODE_TOP_LEVEL:
modeData = undefined;
modeStack.length = 0;
break;
case CSS_MODE_IN_LOCAL_RULE:
processDeclarationValueDone(input, start);
break;
}
return end;
}
});
module.buildInfo.strict = true;
module.buildMeta.exportsType = "namespace";
module.addDependency(new StaticExportsDependency([], true));
return state;
}
}
module.exports = CssParser;

659
lib/css/walkCssTokens.js Normal file
View File

@ -0,0 +1,659 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/**
* @typedef {Object} CssTokenCallbacks
* @property {function(string, number): boolean} isSelector
* @property {function(string, number, number, number, number): number=} url
* @property {function(string, number, number): number=} string
* @property {function(string, number, number): number=} leftParenthesis
* @property {function(string, number, number): number=} rightParenthesis
* @property {function(string, number, number): number=} pseudoFunction
* @property {function(string, number, number): number=} function
* @property {function(string, number, number): number=} pseudoClass
* @property {function(string, number, number): number=} atKeyword
* @property {function(string, number, number): number=} class
* @property {function(string, number, number): number=} identifier
* @property {function(string, number, number): number=} id
* @property {function(string, number, number): number=} leftCurlyBracket
* @property {function(string, number, number): number=} rightCurlyBracket
* @property {function(string, number, number): number=} semicolon
* @property {function(string, number, number): number=} comma
*/
/** @typedef {function(string, number, CssTokenCallbacks): number} CharHandler */
// spec: https://drafts.csswg.org/css-syntax/
const CC_LINE_FEED = "\n".charCodeAt(0);
const CC_CARRIAGE_RETURN = "\r".charCodeAt(0);
const CC_FORM_FEED = "\f".charCodeAt(0);
const CC_TAB = "\t".charCodeAt(0);
const CC_SPACE = " ".charCodeAt(0);
const CC_SLASH = "/".charCodeAt(0);
const CC_BACK_SLASH = "\\".charCodeAt(0);
const CC_ASTERISK = "*".charCodeAt(0);
const CC_LEFT_PARENTHESIS = "(".charCodeAt(0);
const CC_RIGHT_PARENTHESIS = ")".charCodeAt(0);
const CC_LEFT_CURLY = "{".charCodeAt(0);
const CC_RIGHT_CURLY = "}".charCodeAt(0);
const CC_QUOTATION_MARK = '"'.charCodeAt(0);
const CC_APOSTROPHE = "'".charCodeAt(0);
const CC_FULL_STOP = ".".charCodeAt(0);
const CC_COLON = ":".charCodeAt(0);
const CC_SEMICOLON = ";".charCodeAt(0);
const CC_COMMA = ",".charCodeAt(0);
const CC_PERCENTAGE = "%".charCodeAt(0);
const CC_AT_SIGN = "@".charCodeAt(0);
const CC_LOW_LINE = "_".charCodeAt(0);
const CC_LOWER_A = "a".charCodeAt(0);
const CC_LOWER_U = "u".charCodeAt(0);
const CC_LOWER_E = "e".charCodeAt(0);
const CC_LOWER_Z = "z".charCodeAt(0);
const CC_UPPER_A = "A".charCodeAt(0);
const CC_UPPER_E = "E".charCodeAt(0);
const CC_UPPER_Z = "Z".charCodeAt(0);
const CC_0 = "0".charCodeAt(0);
const CC_9 = "9".charCodeAt(0);
const CC_NUMBER_SIGN = "#".charCodeAt(0);
const CC_PLUS_SIGN = "+".charCodeAt(0);
const CC_HYPHEN_MINUS = "-".charCodeAt(0);
const CC_LESS_THAN_SIGN = "<".charCodeAt(0);
const CC_GREATER_THAN_SIGN = ">".charCodeAt(0);
const _isNewLine = cc => {
return (
cc === CC_LINE_FEED || cc === CC_CARRIAGE_RETURN || cc === CC_FORM_FEED
);
};
/** @type {CharHandler} */
const consumeSpace = (input, pos, callbacks) => {
let cc;
do {
pos++;
cc = input.charCodeAt(pos);
} while (_isWhiteSpace(cc));
return pos;
};
const _isWhiteSpace = cc => {
return (
cc === CC_LINE_FEED ||
cc === CC_CARRIAGE_RETURN ||
cc === CC_FORM_FEED ||
cc === CC_TAB ||
cc === CC_SPACE
);
};
/** @type {CharHandler} */
const consumeSingleCharToken = (input, pos, callbacks) => {
return pos + 1;
};
/** @type {CharHandler} */
const consumePotentialComment = (input, pos, callbacks) => {
pos++;
if (pos === input.length) return pos;
let cc = input.charCodeAt(pos);
if (cc !== CC_ASTERISK) return pos;
for (;;) {
pos++;
if (pos === input.length) return pos;
cc = input.charCodeAt(pos);
while (cc === CC_ASTERISK) {
pos++;
if (pos === input.length) return pos;
cc = input.charCodeAt(pos);
if (cc === CC_SLASH) return pos + 1;
}
}
};
/** @type {function(number): CharHandler} */
const consumeString = end => (input, pos, callbacks) => {
const start = pos;
pos = _consumeString(input, pos, end);
if (callbacks.string !== undefined) {
pos = callbacks.string(input, start, pos);
}
return pos;
};
const _consumeString = (input, pos, end) => {
pos++;
for (;;) {
if (pos === input.length) return pos;
const cc = input.charCodeAt(pos);
if (cc === end) return pos + 1;
if (_isNewLine(cc)) {
// bad string
return pos;
}
if (cc === CC_BACK_SLASH) {
// we don't need to fully parse the escaped code point
// just skip over a potential new line
pos++;
if (pos === input.length) return pos;
pos++;
} else {
pos++;
}
}
};
const _isIdentifierStartCode = cc => {
return (
cc === CC_LOW_LINE ||
(cc >= CC_LOWER_A && cc <= CC_LOWER_Z) ||
(cc >= CC_UPPER_A && cc <= CC_UPPER_Z) ||
cc > 0x80
);
};
const _isDigit = cc => {
return cc >= CC_0 && cc <= CC_9;
};
const _startsIdentifier = (input, pos) => {
const cc = input.charCodeAt(pos);
if (cc === CC_HYPHEN_MINUS) {
if (pos === input.length) return false;
const cc = input.charCodeAt(pos + 1);
if (cc === CC_HYPHEN_MINUS) return true;
if (cc === CC_BACK_SLASH) {
const cc = input.charCodeAt(pos + 2);
return !_isNewLine(cc);
}
return _isIdentifierStartCode(cc);
}
if (cc === CC_BACK_SLASH) {
const cc = input.charCodeAt(pos + 1);
return !_isNewLine(cc);
}
return _isIdentifierStartCode(cc);
};
/** @type {CharHandler} */
const consumeNumberSign = (input, pos, callbacks) => {
const start = pos;
pos++;
if (pos === input.length) return pos;
if (callbacks.isSelector(input, pos) && _startsIdentifier(input, pos)) {
pos = _consumeIdentifier(input, pos);
if (callbacks.id !== undefined) {
return callbacks.id(input, start, pos);
}
}
return pos;
};
/** @type {CharHandler} */
const consumeMinus = (input, pos, callbacks) => {
const start = pos;
pos++;
if (pos === input.length) return pos;
const cc = input.charCodeAt(pos);
if (cc === CC_FULL_STOP || _isDigit(cc)) {
return consumeNumericToken(input, pos, callbacks);
} else if (cc === CC_HYPHEN_MINUS) {
pos++;
if (pos === input.length) return pos;
const cc = input.charCodeAt(pos);
if (cc === CC_GREATER_THAN_SIGN) {
return pos + 1;
} else {
pos = _consumeIdentifier(input, pos);
if (callbacks.identifier !== undefined) {
return callbacks.identifier(input, start, pos);
}
}
} else if (cc === CC_BACK_SLASH) {
if (pos + 1 === input.length) return pos;
const cc = input.charCodeAt(pos + 1);
if (_isNewLine(cc)) return pos;
pos = _consumeIdentifier(input, pos);
if (callbacks.identifier !== undefined) {
return callbacks.identifier(input, start, pos);
}
} else if (_isIdentifierStartCode(cc)) {
pos++;
pos = _consumeIdentifier(input, pos);
if (callbacks.identifier !== undefined) {
return callbacks.identifier(input, start, pos);
}
}
return pos;
};
/** @type {CharHandler} */
const consumeDot = (input, pos, callbacks) => {
const start = pos;
pos++;
if (pos === input.length) return pos;
const cc = input.charCodeAt(pos);
if (_isDigit(cc)) return consumeNumericToken(input, pos - 2, callbacks);
if (!callbacks.isSelector(input, pos) || !_startsIdentifier(input, pos))
return pos;
pos = _consumeIdentifier(input, pos);
if (callbacks.class !== undefined) return callbacks.class(input, start, pos);
return pos;
};
/** @type {CharHandler} */
const consumeNumericToken = (input, pos, callbacks) => {
pos = _consumeNumber(input, pos);
if (pos === input.length) return pos;
if (_startsIdentifier(input, pos)) return _consumeIdentifier(input, pos);
const cc = input.charCodeAt(pos);
if (cc === CC_PERCENTAGE) return pos + 1;
return pos;
};
/** @type {CharHandler} */
const consumeOtherIdentifier = (input, pos, callbacks) => {
const start = pos;
pos = _consumeIdentifier(input, pos);
if (
pos !== input.length &&
!callbacks.isSelector(input, pos) &&
input.charCodeAt(pos) === CC_LEFT_PARENTHESIS
) {
pos++;
if (callbacks.function !== undefined) {
return callbacks.function(input, start, pos);
}
} else {
if (callbacks.identifier !== undefined) {
return callbacks.identifier(input, start, pos);
}
}
return pos;
};
/** @type {CharHandler} */
const consumePotentialUrl = (input, pos, callbacks) => {
const start = pos;
pos = _consumeIdentifier(input, pos);
if (pos === start + 3 && input.slice(start, pos + 1) === "url(") {
pos++;
let cc = input.charCodeAt(pos);
while (_isWhiteSpace(cc)) {
pos++;
if (pos === input.length) return pos;
cc = input.charCodeAt(pos);
}
if (cc === CC_QUOTATION_MARK || cc === CC_APOSTROPHE) {
pos++;
const contentStart = pos;
pos = _consumeString(input, pos, cc);
const contentEnd = pos - 1;
cc = input.charCodeAt(pos);
while (_isWhiteSpace(cc)) {
pos++;
if (pos === input.length) return pos;
cc = input.charCodeAt(pos);
}
if (cc !== CC_RIGHT_PARENTHESIS) return pos;
pos++;
if (callbacks.url !== undefined)
return callbacks.url(input, start, pos, contentStart, contentEnd);
return pos;
} else {
const contentStart = pos;
let contentEnd;
for (;;) {
if (cc === CC_BACK_SLASH) {
pos++;
if (pos === input.length) return pos;
pos++;
} else if (_isWhiteSpace(cc)) {
contentEnd = pos;
do {
pos++;
if (pos === input.length) return pos;
cc = input.charCodeAt(pos);
} while (_isWhiteSpace(cc));
if (cc !== CC_RIGHT_PARENTHESIS) return pos;
pos++;
if (callbacks.url !== undefined) {
return callbacks.url(input, start, pos, contentStart, contentEnd);
}
return pos;
} else if (cc === CC_RIGHT_PARENTHESIS) {
contentEnd = pos;
pos++;
if (callbacks.url !== undefined) {
return callbacks.url(input, start, pos, contentStart, contentEnd);
}
return pos;
} else if (cc === CC_LEFT_PARENTHESIS) {
return pos;
} else {
pos++;
}
if (pos === input.length) return pos;
cc = input.charCodeAt(pos);
}
}
} else {
if (callbacks.identifier !== undefined) {
return callbacks.identifier(input, start, pos);
}
return pos;
}
};
/** @type {CharHandler} */
const consumePotentialPseudo = (input, pos, callbacks) => {
const start = pos;
pos++;
if (!callbacks.isSelector(input, pos) || !_startsIdentifier(input, pos))
return pos;
pos = _consumeIdentifier(input, pos);
let cc = input.charCodeAt(pos);
if (cc === CC_LEFT_PARENTHESIS) {
pos++;
if (callbacks.pseudoFunction !== undefined) {
return callbacks.pseudoFunction(input, start, pos);
}
return pos;
}
if (callbacks.pseudoClass !== undefined) {
return callbacks.pseudoClass(input, start, pos);
}
return pos;
};
/** @type {CharHandler} */
const consumeLeftParenthesis = (input, pos, callbacks) => {
pos++;
if (callbacks.leftParenthesis !== undefined) {
return callbacks.leftParenthesis(input, pos - 1, pos);
}
return pos;
};
/** @type {CharHandler} */
const consumeRightParenthesis = (input, pos, callbacks) => {
pos++;
if (callbacks.rightParenthesis !== undefined) {
return callbacks.rightParenthesis(input, pos - 1, pos);
}
return pos;
};
/** @type {CharHandler} */
const consumeLeftCurlyBracket = (input, pos, callbacks) => {
pos++;
if (callbacks.leftCurlyBracket !== undefined) {
return callbacks.leftCurlyBracket(input, pos - 1, pos);
}
return pos;
};
/** @type {CharHandler} */
const consumeRightCurlyBracket = (input, pos, callbacks) => {
pos++;
if (callbacks.rightCurlyBracket !== undefined) {
return callbacks.rightCurlyBracket(input, pos - 1, pos);
}
return pos;
};
/** @type {CharHandler} */
const consumeSemicolon = (input, pos, callbacks) => {
pos++;
if (callbacks.semicolon !== undefined) {
return callbacks.semicolon(input, pos - 1, pos);
}
return pos;
};
/** @type {CharHandler} */
const consumeComma = (input, pos, callbacks) => {
pos++;
if (callbacks.comma !== undefined) {
return callbacks.comma(input, pos - 1, pos);
}
return pos;
};
const _consumeIdentifier = (input, pos) => {
for (;;) {
const cc = input.charCodeAt(pos);
if (cc === CC_BACK_SLASH) {
pos++;
if (pos === input.length) return pos;
pos++;
} else if (
_isIdentifierStartCode(cc) ||
_isDigit(cc) ||
cc === CC_HYPHEN_MINUS
) {
pos++;
} else {
return pos;
}
}
};
const _consumeNumber = (input, pos) => {
pos++;
if (pos === input.length) return pos;
let cc = input.charCodeAt(pos);
while (_isDigit(cc)) {
pos++;
if (pos === input.length) return pos;
cc = input.charCodeAt(pos);
}
if (cc === CC_FULL_STOP && pos + 1 !== input.length) {
const next = input.charCodeAt(pos + 1);
if (_isDigit(next)) {
pos += 2;
cc = input.charCodeAt(pos);
while (_isDigit(cc)) {
pos++;
if (pos === input.length) return pos;
cc = input.charCodeAt(pos);
}
}
}
if (cc === CC_LOWER_E || cc === CC_UPPER_E) {
if (pos + 1 !== input.length) {
const next = input.charCodeAt(pos + 2);
if (_isDigit(next)) {
pos += 2;
} else if (
(next === CC_HYPHEN_MINUS || next === CC_PLUS_SIGN) &&
pos + 2 !== input.length
) {
const next = input.charCodeAt(pos + 2);
if (_isDigit(next)) {
pos += 3;
} else {
return pos;
}
} else {
return pos;
}
}
} else {
return pos;
}
cc = input.charCodeAt(pos);
while (_isDigit(cc)) {
pos++;
if (pos === input.length) return pos;
cc = input.charCodeAt(pos);
}
return pos;
};
/** @type {CharHandler} */
const consumeLessThan = (input, pos, callbacks) => {
if (input.slice(pos + 1, pos + 4) === "!--") return pos + 4;
return pos + 1;
};
/** @type {CharHandler} */
const consumeAt = (input, pos, callbacks) => {
const start = pos;
pos++;
if (pos === input.length) return pos;
if (_startsIdentifier(input, pos)) {
pos = _consumeIdentifier(input, pos);
if (callbacks.atKeyword !== undefined) {
pos = callbacks.atKeyword(input, start, pos);
}
}
return pos;
};
const CHAR_MAP = Array.from({ length: 0x80 }, (_, cc) => {
// https://drafts.csswg.org/css-syntax/#consume-token
switch (cc) {
case CC_LINE_FEED:
case CC_CARRIAGE_RETURN:
case CC_FORM_FEED:
case CC_TAB:
case CC_SPACE:
return consumeSpace;
case CC_QUOTATION_MARK:
case CC_APOSTROPHE:
return consumeString(cc);
case CC_NUMBER_SIGN:
return consumeNumberSign;
case CC_SLASH:
return consumePotentialComment;
// case CC_LEFT_SQUARE:
// case CC_RIGHT_SQUARE:
// case CC_COMMA:
// case CC_COLON:
// return consumeSingleCharToken;
case CC_COMMA:
return consumeComma;
case CC_SEMICOLON:
return consumeSemicolon;
case CC_LEFT_PARENTHESIS:
return consumeLeftParenthesis;
case CC_RIGHT_PARENTHESIS:
return consumeRightParenthesis;
case CC_LEFT_CURLY:
return consumeLeftCurlyBracket;
case CC_RIGHT_CURLY:
return consumeRightCurlyBracket;
case CC_COLON:
return consumePotentialPseudo;
case CC_PLUS_SIGN:
return consumeNumericToken;
case CC_FULL_STOP:
return consumeDot;
case CC_HYPHEN_MINUS:
return consumeMinus;
case CC_LESS_THAN_SIGN:
return consumeLessThan;
case CC_AT_SIGN:
return consumeAt;
case CC_LOWER_U:
return consumePotentialUrl;
case CC_LOW_LINE:
return consumeOtherIdentifier;
default:
if (_isDigit(cc)) return consumeNumericToken;
if (
(cc >= CC_LOWER_A && cc <= CC_LOWER_Z) ||
(cc >= CC_UPPER_A && cc <= CC_UPPER_Z)
) {
return consumeOtherIdentifier;
}
return consumeSingleCharToken;
}
});
/**
* @param {string} input input css
* @param {CssTokenCallbacks} callbacks callbacks
* @returns {void}
*/
module.exports = (input, callbacks) => {
let pos = 0;
while (pos < input.length) {
const cc = input.charCodeAt(pos);
if (cc < 0x80) {
pos = CHAR_MAP[cc](input, pos, callbacks);
} else {
pos++;
}
}
};
module.exports.eatComments = (input, pos) => {
loop: for (;;) {
const cc = input.charCodeAt(pos);
if (cc === CC_SLASH) {
if (pos === input.length) return pos;
let cc = input.charCodeAt(pos + 1);
if (cc !== CC_ASTERISK) return pos;
pos++;
for (;;) {
pos++;
if (pos === input.length) return pos;
cc = input.charCodeAt(pos);
while (cc === CC_ASTERISK) {
pos++;
if (pos === input.length) return pos;
cc = input.charCodeAt(pos);
if (cc === CC_SLASH) {
pos++;
continue loop;
}
}
}
}
return pos;
}
};
module.exports.eatWhitespaceAndComments = (input, pos) => {
loop: for (;;) {
const cc = input.charCodeAt(pos);
if (cc === CC_SLASH) {
if (pos === input.length) return pos;
let cc = input.charCodeAt(pos + 1);
if (cc !== CC_ASTERISK) return pos;
pos++;
for (;;) {
pos++;
if (pos === input.length) return pos;
cc = input.charCodeAt(pos);
while (cc === CC_ASTERISK) {
pos++;
if (pos === input.length) return pos;
cc = input.charCodeAt(pos);
if (cc === CC_SLASH) {
pos++;
continue loop;
}
}
}
} else if (_isWhiteSpace(cc)) {
pos++;
continue;
}
return pos;
}
};

View File

@ -123,9 +123,7 @@ class Profiler {
* @returns {Trace} The trace object
*/
const createTrace = (fs, outputPath) => {
const trace = new Tracer({
noStream: true
});
const trace = new Tracer();
const profiler = new Profiler(inspector);
if (/\/|\\/.test(outputPath)) {
const dirPath = dirname(fs, outputPath);
@ -173,6 +171,7 @@ const createTrace = (fs, outputPath) => {
counter,
profiler,
end: callback => {
trace.push("]");
// Wait until the write stream finishes.
fsStream.on("close", () => {
callback();
@ -242,10 +241,10 @@ class ProfilingPlugin {
stage: Infinity
},
(stats, callback) => {
if (compiler.watchMode) return callback();
tracer.profiler.stopProfiling().then(parsedResults => {
if (parsedResults === undefined) {
tracer.profiler.destroy();
tracer.trace.flush();
tracer.end(callback);
return;
}
@ -293,7 +292,6 @@ class ProfilingPlugin {
});
tracer.profiler.destroy();
tracer.trace.flush();
tracer.end(callback);
});
}
@ -346,11 +344,15 @@ const interceptAllJavascriptModulesPluginHooks = (compilation, tracer) => {
const makeInterceptorFor = (instance, tracer) => hookName => ({
register: ({ name, type, context, fn }) => {
const newFn = makeNewProfiledTapFn(hookName, tracer, {
name,
type,
fn
});
const newFn =
// Don't tap our own hooks to ensure stream can close cleanly
name === pluginName
? fn
: makeNewProfiledTapFn(hookName, tracer, {
name,
type,
fn
});
return {
name,
type,

View File

@ -25,6 +25,18 @@ class CreateScriptUrlDependency extends NullDependency {
get type() {
return "create script url";
}
serialize(context) {
const { write } = context;
write(this.range);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.range = read();
super.deserialize(context);
}
}
CreateScriptUrlDependency.Template = class CreateScriptUrlDependencyTemplate extends (

View File

@ -0,0 +1,85 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
const makeSerializable = require("../util/makeSerializable");
const NullDependency = require("./NullDependency");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
/** @typedef {import("../DependencyTemplate").CssDependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
class CssExportDependency extends NullDependency {
/**
* @param {string} name name
* @param {string} value value
*/
constructor(name, value) {
super();
this.name = name;
this.value = value;
}
get type() {
return "css :export";
}
/**
* Returns the exported names
* @param {ModuleGraph} moduleGraph module graph
* @returns {ExportsSpec | undefined} export names
*/
getExports(moduleGraph) {
const name = this.name;
return {
exports: [
{
name,
canMangle: true
}
],
dependencies: undefined
};
}
serialize(context) {
const { write } = context;
write(this.name);
write(this.value);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.name = read();
this.value = read();
super.deserialize(context);
}
}
CssExportDependency.Template = class CssExportDependencyTemplate extends (
NullDependency.Template
) {
/**
* @param {Dependency} dependency the dependency for which the template should be applied
* @param {ReplaceSource} source the current replace source which can be modified
* @param {DependencyTemplateContext} templateContext the context object
* @returns {void}
*/
apply(dependency, source, { cssExports }) {
const dep = /** @type {CssExportDependency} */ (dependency);
cssExports.set(dep.name, dep.value);
}
};
makeSerializable(
CssExportDependency,
"webpack/lib/dependencies/CssExportDependency"
);
module.exports = CssExportDependency;

View File

@ -0,0 +1,75 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
const makeSerializable = require("../util/makeSerializable");
const ModuleDependency = require("./ModuleDependency");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
/** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState */
/** @typedef {import("../util/Hash")} Hash */
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
class CssImportDependency extends ModuleDependency {
/**
* @param {string} request request
* @param {[number, number]} range range of the argument
* @param {string | undefined} supports list of supports conditions
* @param {string | undefined} media list of media conditions
*/
constructor(request, range, supports, media) {
super(request);
this.range = range;
this.supports = supports;
this.media = media;
}
get type() {
return "css @import";
}
get category() {
return "css-import";
}
/**
* @param {string} context context directory
* @returns {Module} a module
*/
createIgnoredModule(context) {
return null;
}
}
CssImportDependency.Template = class CssImportDependencyTemplate extends (
ModuleDependency.Template
) {
/**
* @param {Dependency} dependency the dependency for which the template should be applied
* @param {ReplaceSource} source the current replace source which can be modified
* @param {DependencyTemplateContext} templateContext the context object
* @returns {void}
*/
apply(dependency, source, templateContext) {
const dep = /** @type {CssImportDependency} */ (dependency);
source.replace(dep.range[0], dep.range[1] - 1, "");
}
};
makeSerializable(
CssImportDependency,
"webpack/lib/dependencies/CssImportDependency"
);
module.exports = CssImportDependency;

View File

@ -0,0 +1,119 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
const makeSerializable = require("../util/makeSerializable");
const NullDependency = require("./NullDependency");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
/** @typedef {import("../DependencyTemplate").CssDependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
class CssLocalIdentifierDependency extends NullDependency {
/**
* @param {string} name name
* @param {[number, number]} range range
* @param {string=} prefix prefix
*/
constructor(name, range, prefix = "") {
super();
this.name = name;
this.range = range;
this.prefix = prefix;
}
get type() {
return "css local identifier";
}
/**
* Returns the exported names
* @param {ModuleGraph} moduleGraph module graph
* @returns {ExportsSpec | undefined} export names
*/
getExports(moduleGraph) {
const name = this.name;
return {
exports: [
{
name,
canMangle: true
}
],
dependencies: undefined
};
}
serialize(context) {
const { write } = context;
write(this.name);
write(this.range);
write(this.prefix);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.name = read();
this.range = read();
this.prefix = read();
super.deserialize(context);
}
}
const escapeCssIdentifier = (str, omitUnderscore) => {
const escaped = `${str}`.replace(
// cspell:word uffff
/[^a-zA-Z0-9_\u0081-\uffff-]/g,
s => `\\${s}`
);
return !omitUnderscore && /^(?!--)[0-9-]/.test(escaped)
? `_${escaped}`
: escaped;
};
CssLocalIdentifierDependency.Template = class CssLocalIdentifierDependencyTemplate extends (
NullDependency.Template
) {
/**
* @param {Dependency} dependency the dependency for which the template should be applied
* @param {ReplaceSource} source the current replace source which can be modified
* @param {DependencyTemplateContext} templateContext the context object
* @returns {void}
*/
apply(
dependency,
source,
{ module, moduleGraph, chunkGraph, runtime, runtimeTemplate, cssExports }
) {
const dep = /** @type {CssLocalIdentifierDependency} */ (dependency);
const used = moduleGraph
.getExportInfo(module, dep.name)
.getUsedName(dep.name, runtime);
const moduleId = chunkGraph.getModuleId(module);
const identifier =
dep.prefix +
(runtimeTemplate.outputOptions.uniqueName
? runtimeTemplate.outputOptions.uniqueName + "-"
: "") +
(used ? moduleId + "-" + used : "-");
source.replace(
dep.range[0],
dep.range[1] - 1,
escapeCssIdentifier(identifier, dep.prefix)
);
if (used) cssExports.set(used, identifier);
}
};
makeSerializable(
CssLocalIdentifierDependency,
"webpack/lib/dependencies/CssLocalIdentifierDependency"
);
module.exports = CssLocalIdentifierDependency;

View File

@ -0,0 +1,101 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
const Dependency = require("../Dependency");
const makeSerializable = require("../util/makeSerializable");
const CssLocalIdentifierDependency = require("./CssLocalIdentifierDependency");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../Dependency").ExportsSpec} ExportsSpec */
/** @typedef {import("../Dependency").ReferencedExport} ReferencedExport */
/** @typedef {import("../DependencyTemplate").CssDependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
class CssSelfLocalIdentifierDependency extends CssLocalIdentifierDependency {
/**
* @param {string} name name
* @param {[number, number]} range range
* @param {string=} prefix prefix
* @param {Set<string>=} declaredSet set of declared names (will only be active when in declared set)
*/
constructor(name, range, prefix = "", declaredSet = undefined) {
super(name, range, prefix);
this.declaredSet = declaredSet;
}
get type() {
return "css self local identifier";
}
get category() {
return "self";
}
/**
* @returns {string | null} an identifier to merge equal requests
*/
getResourceIdentifier() {
return `self`;
}
/**
* Returns the exported names
* @param {ModuleGraph} moduleGraph module graph
* @returns {ExportsSpec | undefined} export names
*/
getExports(moduleGraph) {
if (this.declaredSet && !this.declaredSet.has(this.name)) return;
return super.getExports(moduleGraph);
}
/**
* Returns list of exports referenced by this dependency
* @param {ModuleGraph} moduleGraph module graph
* @param {RuntimeSpec} runtime the runtime for which the module is analysed
* @returns {(string[] | ReferencedExport)[]} referenced exports
*/
getReferencedExports(moduleGraph, runtime) {
if (this.declaredSet && !this.declaredSet.has(this.name))
return Dependency.NO_EXPORTS_REFERENCED;
return [[this.name]];
}
serialize(context) {
const { write } = context;
write(this.declaredSet);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.declaredSet = read();
super.deserialize(context);
}
}
CssSelfLocalIdentifierDependency.Template = class CssSelfLocalIdentifierDependencyTemplate extends (
CssLocalIdentifierDependency.Template
) {
/**
* @param {Dependency} dependency the dependency for which the template should be applied
* @param {ReplaceSource} source the current replace source which can be modified
* @param {DependencyTemplateContext} templateContext the context object
* @returns {void}
*/
apply(dependency, source, templateContext) {
const dep = /** @type {CssSelfLocalIdentifierDependency} */ (dependency);
if (dep.declaredSet && !dep.declaredSet.has(dep.name)) return;
super.apply(dependency, source, templateContext);
}
};
makeSerializable(
CssSelfLocalIdentifierDependency,
"webpack/lib/dependencies/CssSelfLocalIdentifierDependency"
);
module.exports = CssSelfLocalIdentifierDependency;

View File

@ -0,0 +1,132 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Ivan Kopeykin @vankop
*/
"use strict";
const makeSerializable = require("../util/makeSerializable");
const memoize = require("../util/memoize");
const ModuleDependency = require("./ModuleDependency");
/** @typedef {import("webpack-sources").ReplaceSource} ReplaceSource */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
/** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
/** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState */
/** @typedef {import("../util/Hash")} Hash */
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
const getRawDataUrlModule = memoize(() => require("../asset/RawDataUrlModule"));
class CssUrlDependency extends ModuleDependency {
/**
* @param {string} request request
* @param {[number, number]} range range of the argument
* @param {string} cssFunctionKind kind of css function, e. g. url(), image()
*/
constructor(request, range, cssFunctionKind) {
super(request);
this.range = range;
this.cssFunctionKind = cssFunctionKind;
}
get type() {
return "css url()";
}
get category() {
return "url";
}
/**
* @param {string} context context directory
* @returns {Module} a module
*/
createIgnoredModule(context) {
const RawDataUrlModule = getRawDataUrlModule();
return new RawDataUrlModule("data:,", `ignored-asset`, `(ignored asset)`);
}
serialize(context) {
const { write } = context;
write(this.cssFunctionKind);
super.serialize(context);
}
deserialize(context) {
const { read } = context;
this.cssFunctionKind = read();
super.deserialize(context);
}
}
const cssEscapeString = str => {
let countWhiteOrBracket = 0;
let countQuotation = 0;
let countApostrophe = 0;
for (let i = 0; i < str.length; i++) {
const cc = str.charCodeAt(i);
switch (cc) {
case 9: // tab
case 10: // nl
case 32: // space
case 40: // (
case 41: // )
countWhiteOrBracket++;
break;
case 34:
countQuotation++;
break;
case 39:
countApostrophe++;
break;
}
}
if (countWhiteOrBracket < 2) {
return str.replace(/[\n\t ()'"\\]/g, m => `\\${m}`);
} else if (countQuotation <= countApostrophe) {
return `"${str.replace(/[\n"\\]/g, m => `\\${m}`)}"`;
} else {
return `'${str.replace(/[\n'\\]/g, m => `\\${m}`)}'`;
}
};
CssUrlDependency.Template = class CssUrlDependencyTemplate extends (
ModuleDependency.Template
) {
/**
* @param {Dependency} dependency the dependency for which the template should be applied
* @param {ReplaceSource} source the current replace source which can be modified
* @param {DependencyTemplateContext} templateContext the context object
* @returns {void}
*/
apply(
dependency,
source,
{ runtime, moduleGraph, runtimeTemplate, codeGenerationResults }
) {
const dep = /** @type {CssUrlDependency} */ (dependency);
source.replace(
dep.range[0],
dep.range[1] - 1,
`${dep.cssFunctionKind}(${cssEscapeString(
runtimeTemplate.assetUrl({
publicPath: "",
runtime,
module: moduleGraph.getModule(dep),
codeGenerationResults
})
)})`
);
}
};
makeSerializable(CssUrlDependency, "webpack/lib/dependencies/CssUrlDependency");
module.exports = CssUrlDependency;

View File

@ -16,7 +16,7 @@ const LoaderImportDependency = require("./LoaderImportDependency");
/**
* @callback LoadModuleCallback
* @param {Error=} err error object
* @param {(Error | null)=} err error object
* @param {string | Buffer=} source source code
* @param {object=} map source map
* @param {Module=} module loaded module if successful
@ -24,7 +24,7 @@ const LoaderImportDependency = require("./LoaderImportDependency");
/**
* @callback ImportModuleCallback
* @param {Error=} err error object
* @param {(Error | null)=} err error object
* @param {any=} exports exports of the evaluated module
*/

View File

@ -25,7 +25,7 @@ const ModuleDependency = require("./ModuleDependency");
/** @typedef {import("../util/Hash")} Hash */
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
const getRawModule = memoize(() => require("../RawModule"));
const getRawDataUrlModule = memoize(() => require("../asset/RawDataUrlModule"));
class URLDependency extends ModuleDependency {
/**
@ -68,13 +68,8 @@ class URLDependency extends ModuleDependency {
* @returns {Module} a module
*/
createIgnoredModule(context) {
const RawModule = getRawModule();
return new RawModule(
'module.exports = "data:,";',
`ignored-asset`,
`(ignored asset)`,
new Set([RuntimeGlobals.module])
);
const RawDataUrlModule = getRawDataUrlModule();
return new RawDataUrlModule("data:,", `ignored-asset`, `(ignored asset)`);
}
serialize(context) {

View File

@ -81,7 +81,7 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
);
const conditionMap = chunkGraph.getChunkConditionMap(chunk, chunkHasJs);
const hasJsMatcher = compileBooleanMatcher(conditionMap);
const initialChunkIds = getInitialChunkIds(chunk, chunkGraph);
const initialChunkIds = getInitialChunkIds(chunk, chunkGraph, chunkHasJs);
const outputName = this.compilation.getPath(
getChunkFilenameTemplate(chunk, this.compilation.outputOptions),

View File

@ -146,7 +146,7 @@ class LazyCompilationProxyModule extends Module {
/**
* @param {NeedBuildContext} context context info
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {

View File

@ -13,7 +13,7 @@
/**
* @callback BackendHandler
* @param {Compiler} compiler compiler
* @param {function(Error?, any?): void} callback callback
* @param {function((Error | null)=, any=): void} callback callback
* @returns {void}
*/
@ -68,7 +68,9 @@ module.exports = options => (compiler, callback) => {
req.socket.setNoDelay(true);
res.writeHead(200, {
"content-type": "text/event-stream",
"Access-Control-Allow-Origin": "*"
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "*",
"Access-Control-Allow-Headers": "*"
});
res.write("\n");
let moduleActivated = false;

View File

@ -199,6 +199,7 @@ class JavascriptGenerator extends Generator {
runtime: generateContext.runtime,
runtimeRequirements: generateContext.runtimeRequirements,
concatenationScope: generateContext.concatenationScope,
codeGenerationResults: generateContext.codeGenerationResults,
initFragments
};

View File

@ -9,7 +9,6 @@ const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
const { isSubset } = require("../util/SetHelpers");
const { getAllChunks } = require("./ChunkHelpers");
const { chunkHasJs } = require("./JavascriptModulesPlugin");
/** @typedef {import("../util/Hash")} Hash */
/** @typedef {import("../Chunk")} Chunk */
@ -119,12 +118,13 @@ exports.updateHashForEntryStartup = (hash, chunkGraph, entries, chunk) => {
/**
* @param {Chunk} chunk the chunk
* @param {ChunkGraph} chunkGraph the chunk graph
* @param {function(Chunk, ChunkGraph): boolean} filterFn filter function
* @returns {Set<number | string>} initially fulfilled chunk ids
*/
exports.getInitialChunkIds = (chunk, chunkGraph) => {
exports.getInitialChunkIds = (chunk, chunkGraph, filterFn) => {
const initialChunkIds = new Set(chunk.ids);
for (const c of chunk.getAllInitialChunks()) {
if (c === chunk || chunkHasJs(c, chunkGraph)) continue;
if (c === chunk || filterFn(c, chunkGraph)) continue;
for (const id of c.ids) initialChunkIds.add(id);
}
return initialChunkIds;

View File

@ -92,7 +92,7 @@ const accessWithInit = (accessor, existingLength, initLast = false) => {
* @property {LibraryType} type
* @property {string[] | "global"} prefix name prefix
* @property {string | false} declare declare name as variable
* @property {"error"|"copy"|"assign"} unnamed behavior for unnamed library name
* @property {"error"|"static"|"copy"|"assign"} unnamed behavior for unnamed library name
* @property {"copy"|"assign"=} named behavior for named library name
*/
@ -261,19 +261,42 @@ class AssignLibraryPlugin extends AbstractLibraryPlugin {
* @param {LibraryContext<T>} libraryContext context
* @returns {Source} source with library export
*/
renderStartup(source, module, { chunk }, { options, compilation }) {
renderStartup(
source,
module,
{ moduleGraph, chunk },
{ options, compilation }
) {
const fullNameResolved = this._getResolvedFullName(
options,
chunk,
compilation
);
const staticExports = this.unnamed === "static";
const exportAccess = options.export
? propertyAccess(
Array.isArray(options.export) ? options.export : [options.export]
)
: "";
const result = new ConcatSource(source);
if (options.name ? this.named === "copy" : this.unnamed === "copy") {
if (staticExports) {
const exportsInfo = moduleGraph.getExportsInfo(module);
const exportTarget = accessWithInit(
fullNameResolved,
this._getPrefix(compilation).length,
true
);
for (const exportInfo of exportsInfo.orderedExports) {
if (!exportInfo.provided) continue;
const nameAccess = propertyAccess([exportInfo.name]);
result.add(
`${exportTarget}${nameAccess} = __webpack_exports__${exportAccess}${nameAccess};\n`
);
}
result.add(
`Object.defineProperty(${exportTarget}, "__esModule", { value: true });\n`
);
} else if (options.name ? this.named === "copy" : this.unnamed === "copy") {
result.add(
`var __webpack_export_target__ = ${accessWithInit(
fullNameResolved,

View File

@ -167,6 +167,17 @@ class EnableLibraryPlugin {
}).apply(compiler);
break;
}
case "commonjs-static": {
//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
const AssignLibraryPlugin = require("./AssignLibraryPlugin");
new AssignLibraryPlugin({
type,
prefix: ["exports"],
declare: false,
unnamed: "static"
}).apply(compiler);
break;
}
case "commonjs2":
case "commonjs-module": {
//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697

View File

@ -46,7 +46,7 @@ class ReadFileChunkLoadingRuntimeModule extends RuntimeModule {
);
const conditionMap = chunkGraph.getChunkConditionMap(chunk, chunkHasJs);
const hasJsMatcher = compileBooleanMatcher(conditionMap);
const initialChunkIds = getInitialChunkIds(chunk, chunkGraph);
const initialChunkIds = getInitialChunkIds(chunk, chunkGraph, chunkHasJs);
const outputName = this.compilation.getPath(
getChunkFilenameTemplate(chunk, this.compilation.outputOptions),

View File

@ -46,7 +46,7 @@ class RequireChunkLoadingRuntimeModule extends RuntimeModule {
);
const conditionMap = chunkGraph.getChunkConditionMap(chunk, chunkHasJs);
const hasJsMatcher = compileBooleanMatcher(conditionMap);
const initialChunkIds = getInitialChunkIds(chunk, chunkGraph);
const initialChunkIds = getInitialChunkIds(chunk, chunkGraph, chunkHasJs);
const outputName = this.compilation.getPath(
getChunkFilenameTemplate(chunk, this.compilation.outputOptions),

View File

@ -39,6 +39,7 @@ const {
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
@ -1077,7 +1078,8 @@ class ConcatenatedModule extends Module {
runtimeTemplate,
moduleGraph,
chunkGraph,
runtime: generationRuntime
runtime: generationRuntime,
codeGenerationResults
}) {
/** @type {Set<string>} */
const runtimeRequirements = new Set();
@ -1104,7 +1106,8 @@ class ConcatenatedModule extends Module {
runtimeTemplate,
moduleGraph,
chunkGraph,
runtime
runtime,
codeGenerationResults
);
}
@ -1634,6 +1637,7 @@ ${defineGetters}`
* @param {ModuleGraph} moduleGraph moduleGraph
* @param {ChunkGraph} chunkGraph chunkGraph
* @param {RuntimeSpec} runtime runtime
* @param {CodeGenerationResults} codeGenerationResults codeGenerationResults
*/
_analyseModule(
modulesMap,
@ -1642,7 +1646,8 @@ ${defineGetters}`
runtimeTemplate,
moduleGraph,
chunkGraph,
runtime
runtime,
codeGenerationResults
) {
if (info.type === "concatenated") {
const m = info.module;
@ -1657,7 +1662,8 @@ ${defineGetters}`
moduleGraph,
chunkGraph,
runtime,
concatenationScope
concatenationScope,
codeGenerationResults
});
const source = codeGenResult.sources.get("javascript");
const data = codeGenResult.data;

View File

@ -166,7 +166,7 @@ class Lockfile {
/**
* @template R
* @param {function(function(Error=, R=): void): void} fn function
* @returns {function(function(Error=, R=): void): void} cached function
* @returns {function(function((Error | null)=, R=): void): void} cached function
*/
const cachedWithoutKey = fn => {
let inFlight = false;
@ -201,10 +201,10 @@ const cachedWithoutKey = fn => {
* @template R
* @param {function(T, function(Error=, R=): void): void} fn function
* @param {function(T, function(Error=, R=): void): void=} forceFn function for the second try
* @returns {(function(T, function(Error=, R=): void): void) & { force: function(T, function(Error=, R=): void): void }} cached function
* @returns {(function(T, function((Error | null)=, R=): void): void) & { force: function(T, function((Error | null)=, R=): void): void }} cached function
*/
const cachedWithKey = (fn, forceFn = fn) => {
/** @typedef {{ result?: R, error?: Error, callbacks?: (function(Error=, R=): void)[], force?: true }} CacheEntry */
/** @typedef {{ result?: R, error?: Error, callbacks?: (function((Error | null)=, R=): void)[], force?: true }} CacheEntry */
/** @type {Map<T, CacheEntry>} */
const cache = new Map();
const resultFn = (arg, callback) => {
@ -358,7 +358,7 @@ class HttpUriPlugin {
const getLockfile = cachedWithoutKey(
/**
* @param {function(Error=, Lockfile=): void} callback callback
* @param {function((Error | null)=, Lockfile=): void} callback callback
* @returns {void}
*/
callback => {
@ -465,7 +465,7 @@ class HttpUriPlugin {
*
* @param {string} url URL
* @param {string} integrity integrity
* @param {function(Error=, { entry: LockfileEntry, content: Buffer, storeLock: boolean }=): void} callback callback
* @param {function((Error | null)=, { entry: LockfileEntry, content: Buffer, storeLock: boolean }=): void} callback callback
*/
const resolveContent = (url, integrity, callback) => {
const handleResult = (err, result) => {
@ -510,7 +510,7 @@ class HttpUriPlugin {
/**
* @param {string} url URL
* @param {FetchResult} cachedResult result from cache
* @param {function(Error=, FetchResult=): void} callback callback
* @param {function((Error | null)=, FetchResult=): void} callback callback
* @returns {void}
*/
const fetchContentRaw = (url, cachedResult, callback) => {
@ -662,7 +662,7 @@ class HttpUriPlugin {
const fetchContent = cachedWithKey(
/**
* @param {string} url URL
* @param {function(Error=, { validUntil: number, etag?: string, entry: LockfileEntry, content: Buffer, fresh: boolean } | { validUntil: number, etag?: string, location: string, fresh: boolean }=): void} callback callback
* @param {function((Error | null)=, { validUntil: number, etag?: string, entry: LockfileEntry, content: Buffer, fresh: boolean } | { validUntil: number, etag?: string, location: string, fresh: boolean }=): void} callback callback
* @returns {void}
*/ (url, callback) => {
cache.get(url, null, (err, cachedResult) => {
@ -693,7 +693,7 @@ class HttpUriPlugin {
const getInfo = cachedWithKey(
/**
* @param {string} url the url
* @param {function(Error=, { entry: LockfileEntry, content: Buffer }=): void} callback callback
* @param {function((Error | null)=, { entry: LockfileEntry, content: Buffer }=): void} callback callback
* @returns {void}
*/
(url, callback) => {

View File

@ -101,14 +101,16 @@ class ConsumeSharedModule extends Module {
*/
libIdent(options) {
const { shareKey, shareScope, import: request } = this.options;
return `webpack/sharing/consume/${shareScope}/${shareKey}${
return `${
this.layer ? `(${this.layer})/` : ""
}webpack/sharing/consume/${shareScope}/${shareKey}${
request ? `/${request}` : ""
}`;
}
/**
* @param {NeedBuildContext} context context info
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {

View File

@ -67,12 +67,14 @@ class ProvideSharedModule extends Module {
* @returns {string | null} an identifier for library inclusion
*/
libIdent(options) {
return `webpack/sharing/provide/${this._shareScope}/${this._name}`;
return `${this.layer ? `(${this.layer})/` : ""}webpack/sharing/provide/${
this._shareScope
}/${this._name}`;
}
/**
* @param {NeedBuildContext} context context info
* @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {

View File

@ -22,7 +22,7 @@ exports.isRequiredVersion = str => {
* @param {InputFileSystem} fs file system
* @param {string} directory directory to start looking into
* @param {string[]} descriptionFiles possible description filenames
* @param {function(Error=, {data: object, path: string}=): void} callback callback
* @param {function((Error | null)=, {data: object, path: string}=): void} callback callback
*/
const getDescriptionFile = (fs, directory, descriptionFiles, callback) => {
let i = 0;

View File

@ -1658,84 +1658,121 @@ const collapse = children => {
return newChildren;
};
const spaceLimited = (itemsAndGroups, max) => {
const spaceLimited = (
itemsAndGroups,
max,
filteredChildrenLineReserved = false
) => {
if (max < 1) {
return {
children: undefined,
filteredChildren: getTotalItems(itemsAndGroups)
};
}
/** @type {any[] | undefined} */
let children = undefined;
/** @type {number | undefined} */
let filteredChildren = undefined;
// This are the groups, which take 1+ lines each
const groups = itemsAndGroups.filter(c => c.children || c.filteredChildren);
const groups = [];
// The sizes of the groups are stored in groupSizes
const groupSizes = groups.map(g => getItemSize(g));
const groupSizes = [];
// This are the items, which take 1 line each
const items = itemsAndGroups.filter(c => !c.children && !c.filteredChildren);
const items = [];
// The total of group sizes
let groupsSize = groupSizes.reduce((a, b) => a + b, 0);
let groupsSize = 0;
for (const itemOrGroup of itemsAndGroups) {
// is item
if (!itemOrGroup.children && !itemOrGroup.filteredChildren) {
items.push(itemOrGroup);
} else {
groups.push(itemOrGroup);
const size = getItemSize(itemOrGroup);
groupSizes.push(size);
groupsSize += size;
}
}
if (groupsSize + items.length <= max) {
// The total size in the current state fits into the max
// keep all
children = groups.concat(items);
} else if (
groups.length > 0 &&
groups.length + Math.min(1, items.length) < max
) {
// If each group would take 1 line the total would be below the maximum
// collapse some groups, keep items
while (groupsSize + items.length + (filteredChildren ? 1 : 0) > max) {
children = groups.length > 0 ? groups.concat(items) : items;
} else if (groups.length === 0) {
// slice items to max
// inner space marks that lines for filteredChildren already reserved
const limit = max - (filteredChildrenLineReserved ? 0 : 1);
filteredChildren = items.length - limit;
items.length = limit;
children = items;
} else {
// limit is the size when all groups are collapsed
const limit =
groups.length +
(filteredChildrenLineReserved || items.length === 0 ? 0 : 1);
if (limit < max) {
// calculate how much we are over the size limit
// this allows to approach the limit faster
// it's always > 1
const oversize =
items.length + groupsSize + (filteredChildren ? 1 : 0) - max;
// Find the maximum group and process only this one
const maxGroupSize = Math.max(...groupSizes);
if (maxGroupSize < items.length) {
filteredChildren = items.length;
items.length = 0;
continue;
}
for (let i = 0; i < groups.length; i++) {
if (groupSizes[i] === maxGroupSize) {
const group = groups[i];
// run this algorithm recursively and limit the size of the children to
// current size - oversize / number of groups
// So it should always end up being smaller
const headerSize = !group.children
? 0
: group.filteredChildren
? 2
: 1;
const limited = spaceLimited(
group.children,
groupSizes[i] - headerSize - oversize / groups.length
);
groups[i] = {
...group,
children: limited.children,
filteredChildren:
(group.filteredChildren || 0) + limited.filteredChildren
};
const newSize = getItemSize(groups[i]);
groupsSize -= groupSizes[i] - newSize;
groupSizes[i] = newSize;
break;
let oversize;
// If each group would take 1 line the total would be below the maximum
// collapse some groups, keep items
while (
(oversize =
groupsSize +
items.length +
(filteredChildren && !filteredChildrenLineReserved ? 1 : 0) -
max) > 0
) {
// Find the maximum group and process only this one
const maxGroupSize = Math.max(...groupSizes);
if (maxGroupSize < items.length) {
filteredChildren = items.length;
items.length = 0;
continue;
}
for (let i = 0; i < groups.length; i++) {
if (groupSizes[i] === maxGroupSize) {
const group = groups[i];
// run this algorithm recursively and limit the size of the children to
// current size - oversize / number of groups
// So it should always end up being smaller
const headerSize = group.filteredChildren ? 2 : 1;
const limited = spaceLimited(
group.children,
maxGroupSize -
// we should use ceil to always feet in max
Math.ceil(oversize / groups.length) -
// we substitute size of group head
headerSize,
headerSize === 2
);
groups[i] = {
...group,
children: limited.children,
filteredChildren: limited.filteredChildren
? (group.filteredChildren || 0) + limited.filteredChildren
: group.filteredChildren
};
const newSize = getItemSize(groups[i]);
groupsSize -= maxGroupSize - newSize;
groupSizes[i] = newSize;
break;
}
}
}
children = groups.concat(items);
} else if (limit === max) {
// If we have only enough space to show one line per group and one line for the filtered items
// collapse all groups and items
children = collapse(groups);
filteredChildren = items.length;
} else {
// If we have no space
// collapse complete group
filteredChildren = getTotalItems(itemsAndGroups);
}
children = groups.concat(items);
} else if (
groups.length > 0 &&
groups.length + Math.min(1, items.length) <= max
) {
// If we have only enough space to show one line per group and one line for the filtered items
// collapse all groups and items
children = groups.length ? collapse(groups) : undefined;
filteredChildren = items.length;
} else {
// If we have no space
// collapse complete group
filteredChildren = getTotalItems(itemsAndGroups);
}
return {
children,
filteredChildren
@ -1777,6 +1814,9 @@ const reasonGroup = (children, reasons) => {
};
};
const GROUP_EXTENSION_REGEXP = /(\.[^.]+?)(?:\?|(?: \+ \d+ modules?)?$)/;
const GROUP_PATH_REGEXP = /(.+)[/\\][^/\\]+?(?:\?|(?: \+ \d+ modules?)?$)/;
/** @type {Record<string, (groupConfigs: GroupConfig[], context: StatsFactoryContext, options: NormalizedStatsOptions) => void>} */
const ASSETS_GROUPERS = {
_: (groupConfigs, context, options) => {
@ -1825,10 +1865,10 @@ const ASSETS_GROUPERS = {
groupConfigs.push({
getKeys: asset => {
const extensionMatch =
groupAssetsByExtension && /(\.[^.]+)(?:\?.*|$)/.exec(asset.name);
groupAssetsByExtension && GROUP_EXTENSION_REGEXP.exec(asset.name);
const extension = extensionMatch ? extensionMatch[1] : "";
const pathMatch =
groupAssetsByPath && /(.+)[/\\][^/\\]+(?:\?.*|$)/.exec(asset.name);
groupAssetsByPath && GROUP_PATH_REGEXP.exec(asset.name);
const path = pathMatch ? pathMatch[1].split(/[/\\]/) : [];
const keys = [];
if (groupAssetsByPath) {
@ -2022,11 +2062,13 @@ const MODULES_GROUPERS = type => ({
getKeys: module => {
if (!module.name) return;
const resource = parseResource(module.name.split("!").pop()).path;
const dataUrl = /^data:[^,;]+/.exec(resource);
if (dataUrl) return [dataUrl[0]];
const extensionMatch =
groupModulesByExtension && /(\.[^.]+)(?:\?.*|$)/.exec(resource);
groupModulesByExtension && GROUP_EXTENSION_REGEXP.exec(resource);
const extension = extensionMatch ? extensionMatch[1] : "";
const pathMatch =
groupModulesByPath && /(.+)[/\\][^/\\]+(?:\?.*|$)/.exec(resource);
groupModulesByPath && GROUP_PATH_REGEXP.exec(resource);
const path = pathMatch ? pathMatch[1].split(/[/\\]/) : [];
const keys = [];
if (groupModulesByPath) {
@ -2046,11 +2088,14 @@ const MODULES_GROUPERS = type => ({
return keys;
},
createGroup: (key, children, modules) => {
const isDataUrl = key.startsWith("data:");
return {
type: groupModulesByPath
type: isDataUrl
? "modules by mime type"
: groupModulesByPath
? "modules by path"
: "modules by extension",
name: key,
name: isDataUrl ? key.slice(/* 'data:'.length */ 5) : key,
children,
...moduleGroup(children, modules)
};

View File

@ -9,6 +9,8 @@
/** @typedef {import("./StatsPrinter")} StatsPrinter */
/** @typedef {import("./StatsPrinter").StatsPrinterContext} StatsPrinterContext */
const DATA_URI_CONTENT_LENGTH = 16;
const plural = (n, singular, plural) => (n === 1 ? singular : plural);
/**
@ -26,6 +28,23 @@ const printSizes = (sizes, { formatSize = n => `${n}` }) => {
}
};
const getResourceName = resource => {
const dataUrl = /^data:[^,]+,/.exec(resource);
if (!dataUrl) return resource;
const len = dataUrl[0].length + DATA_URI_CONTENT_LENGTH;
if (resource.length < len) return resource;
return `${resource.slice(
0,
Math.min(resource.length - /* '..'.length */ 2, len)
)}..`;
};
const getModuleName = name => {
const [, prefix, resource] = /^(.*!)?([^!]*)$/.exec(name);
return [prefix, getResourceName(resource)];
};
const mapLines = (str, fn) => str.split("\n").map(fn).join("\n");
/**
@ -38,6 +57,10 @@ const isValidId = id => {
return typeof id === "number" || id;
};
const moreCount = (list, count) => {
return list && list.length > 0 ? `+ ${count}` : `${count}`;
};
/** @type {Record<string, (thing: any, context: StatsPrinterContext, printer: StatsPrinter) => string | void>} */
const SIMPLE_PRINTERS = {
"compilation.summary!": (
@ -163,13 +186,24 @@ const SIMPLE_PRINTERS = {
},
"compilation.assetsByChunkName": () => "",
"compilation.filteredModules": filteredModules =>
"compilation.filteredModules": (
filteredModules,
{ compilation: { modules } }
) =>
filteredModules > 0
? `${filteredModules} ${plural(filteredModules, "module", "modules")}`
? `${moreCount(modules, filteredModules)} ${plural(
filteredModules,
"module",
"modules"
)}`
: undefined,
"compilation.filteredAssets": (filteredAssets, { compilation: { assets } }) =>
filteredAssets > 0
? `${filteredAssets} ${plural(filteredAssets, "asset", "assets")}`
? `${moreCount(assets, filteredAssets)} ${plural(
filteredAssets,
"asset",
"assets"
)}`
: undefined,
"compilation.logging": (logging, context, printer) =>
Array.isArray(logging)
@ -262,15 +296,19 @@ const SIMPLE_PRINTERS = {
"asset.separator!": () => "\n",
"asset.filteredRelated": (filteredRelated, { asset: { related } }) =>
filteredRelated > 0
? `${filteredRelated} related ${plural(
? `${moreCount(related, filteredRelated)} related ${plural(
filteredRelated,
"asset",
"assets"
)}`
: undefined,
"asset.filteredChildren": filteredChildren =>
"asset.filteredChildren": (filteredChildren, { asset: { children } }) =>
filteredChildren > 0
? `${filteredChildren} ${plural(filteredChildren, "asset", "assets")}`
? `${moreCount(children, filteredChildren)} ${plural(
filteredChildren,
"asset",
"assets"
)}`
: undefined,
assetChunk: (id, { formatChunkId }) => formatChunkId(id),
@ -282,8 +320,8 @@ const SIMPLE_PRINTERS = {
"module.id": (id, { formatModuleId }) =>
isValidId(id) ? formatModuleId(id) : undefined,
"module.name": (name, { bold }) => {
const [, prefix, resource] = /^(.*!)?([^!]*)$/.exec(name);
return (prefix || "") + bold(resource);
const [prefix, resource] = getModuleName(name);
return `${prefix || ""}${bold(resource || "")}`;
},
"module.identifier": identifier => undefined,
"module.layer": (layer, { formatLayer }) =>
@ -366,21 +404,29 @@ const SIMPLE_PRINTERS = {
"module.issuerPath": (issuerPath, { module }) =>
module.profile ? undefined : "",
"module.profile": profile => undefined,
"module.filteredModules": filteredModules =>
"module.filteredModules": (filteredModules, { module: { modules } }) =>
filteredModules > 0
? `${filteredModules} nested ${plural(
? `${moreCount(modules, filteredModules)} nested ${plural(
filteredModules,
"module",
"modules"
)}`
: undefined,
"module.filteredReasons": filteredReasons =>
"module.filteredReasons": (filteredReasons, { module: { reasons } }) =>
filteredReasons > 0
? `${filteredReasons} ${plural(filteredReasons, "reason", "reasons")}`
? `${moreCount(reasons, filteredReasons)} ${plural(
filteredReasons,
"reason",
"reasons"
)}`
: undefined,
"module.filteredChildren": filteredChildren =>
"module.filteredChildren": (filteredChildren, { module: { children } }) =>
filteredChildren > 0
? `${filteredChildren} ${plural(filteredChildren, "module", "modules")}`
? `${moreCount(children, filteredChildren)} ${plural(
filteredChildren,
"module",
"modules"
)}`
: undefined,
"module.separator!": () => "\n",
@ -388,7 +434,8 @@ const SIMPLE_PRINTERS = {
"moduleIssuer.profile.total": (value, { formatTime }) => formatTime(value),
"moduleReason.type": type => type,
"moduleReason.userRequest": (userRequest, { cyan }) => cyan(userRequest),
"moduleReason.userRequest": (userRequest, { cyan }) =>
cyan(getResourceName(userRequest)),
"moduleReason.moduleId": (moduleId, { formatModuleId }) =>
isValidId(moduleId) ? formatModuleId(moduleId) : undefined,
"moduleReason.module": (module, { magenta }) => magenta(module),
@ -397,9 +444,16 @@ const SIMPLE_PRINTERS = {
"moduleReason.active": (active, { formatFlag }) =>
active ? undefined : formatFlag("inactive"),
"moduleReason.resolvedModule": (module, { magenta }) => magenta(module),
"moduleReason.filteredChildren": filteredChildren =>
"moduleReason.filteredChildren": (
filteredChildren,
{ moduleReason: { children } }
) =>
filteredChildren > 0
? `${filteredChildren} ${plural(filteredChildren, "reason", "reasons")}`
? `${moreCount(children, filteredChildren)} ${plural(
filteredChildren,
"reason",
"reasons"
)}`
: undefined,
"module.profile.total": (value, { formatTime }) => formatTime(value),
@ -427,10 +481,21 @@ const SIMPLE_PRINTERS = {
size ? formatSize(size) : undefined,
"chunkGroup.auxiliaryAssetsSize": (size, { formatSize }) =>
size ? `(${formatSize(size)})` : undefined,
"chunkGroup.filteredAssets": n =>
n > 0 ? `${n} ${plural(n, "asset", "assets")}` : undefined,
"chunkGroup.filteredAuxiliaryAssets": n =>
n > 0 ? `${n} auxiliary ${plural(n, "asset", "assets")}` : undefined,
"chunkGroup.filteredAssets": (n, { chunkGroup: { assets } }) =>
n > 0
? `${moreCount(assets, n)} ${plural(n, "asset", "assets")}`
: undefined,
"chunkGroup.filteredAuxiliaryAssets": (
n,
{ chunkGroup: { auxiliaryAssets } }
) =>
n > 0
? `${moreCount(auxiliaryAssets, n)} auxiliary ${plural(
n,
"asset",
"assets"
)}`
: undefined,
"chunkGroup.is!": () => "=",
"chunkGroupAsset.name": (asset, { green }) => green(asset),
"chunkGroupAsset.size": (size, { formatSize, chunkGroup }) =>
@ -490,9 +555,9 @@ const SIMPLE_PRINTERS = {
"chunk.recorded": (recorded, { formatFlag, green }) =>
recorded ? green(formatFlag("recorded")) : undefined,
"chunk.reason": (reason, { yellow }) => (reason ? yellow(reason) : undefined),
"chunk.filteredModules": filteredModules =>
"chunk.filteredModules": (filteredModules, { chunk: { modules } }) =>
filteredModules > 0
? `${filteredModules} chunk ${plural(
? `${moreCount(modules, filteredModules)} chunk ${plural(
filteredModules,
"module",
"modules"

View File

@ -19,7 +19,7 @@ let inHandleResult = 0;
/**
* @template T
* @callback Callback
* @param {WebpackError=} err
* @param {(WebpackError | null)=} err
* @param {T=} result
*/

View File

@ -10,8 +10,8 @@ const create = require("./wasm-hash");
//#region wasm code: xxhash64 (../../../assembly/hash/xxhash64.asm.ts) --initialMemory 1
const xxhash64 = new WebAssembly.Module(
Buffer.from(
// 1173 bytes
"AGFzbQEAAAABCAJgAX8AYAAAAwQDAQAABQMBAAEGGgV+AUIAC34BQgALfgFCAAt+AUIAC34BQgALByIEBGluaXQAAAZ1cGRhdGUAAQVmaW5hbAACBm1lbW9yeQIACrUIAzAAQtbrgu7q/Yn14AAkAELP1tO+0ser2UIkAUIAJAJC+erQ0OfJoeThACQDQgAkBAvUAQIBfwR+IABFBEAPCyMEIACtfCQEIwAhAiMBIQMjAiEEIwMhBQNAIAIgASkDAELP1tO+0ser2UJ+fEIfiUKHla+vmLbem55/fiECIAMgASkDCELP1tO+0ser2UJ+fEIfiUKHla+vmLbem55/fiEDIAQgASkDEELP1tO+0ser2UJ+fEIfiUKHla+vmLbem55/fiEEIAUgASkDGELP1tO+0ser2UJ+fEIfiUKHla+vmLbem55/fiEFIAAgAUEgaiIBSw0ACyACJAAgAyQBIAQkAiAFJAMLqwYCAX8EfiMEQgBSBH4jACICQgGJIwEiA0IHiXwjAiIEQgyJfCMDIgVCEol8IAJCz9bTvtLHq9lCfkIfiUKHla+vmLbem55/foVCh5Wvr5i23puef35CnaO16oOxjYr6AH0gA0LP1tO+0ser2UJ+Qh+JQoeVr6+Ytt6bnn9+hUKHla+vmLbem55/fkKdo7Xqg7GNivoAfSAEQs/W077Sx6vZQn5CH4lCh5Wvr5i23puef36FQoeVr6+Ytt6bnn9+Qp2jteqDsY2K+gB9IAVCz9bTvtLHq9lCfkIfiUKHla+vmLbem55/foVCh5Wvr5i23puef35CnaO16oOxjYr6AH0FQsXP2bLx5brqJwsjBCAArXx8IQIDQCABQQhqIABNBEAgAiABKQMAQs/W077Sx6vZQn5CH4lCh5Wvr5i23puef36FQhuJQoeVr6+Ytt6bnn9+Qp2jteqDsY2K+gB9IQIgAUEIaiEBDAELCyABQQRqIABNBEACfyACIAE1AgBCh5Wvr5i23puef36FQheJQs/W077Sx6vZQn5C+fPd8Zn2masWfCECIAFBBGoLIQELA0AgACABRwRAIAIgATEAAELFz9my8eW66id+hUILiUKHla+vmLbem55/fiECIAFBAWohAQwBCwtBACACIAJCIYiFQs/W077Sx6vZQn4iAkIdiCAChUL5893xmfaZqxZ+IgJCIIggAoUiAkIgiCIDQv//A4NCIIYgA0KAgPz/D4NCEIiEIgNC/4GAgPAfg0IQhiADQoD+g4CA4D+DQgiIhCIDQo+AvIDwgcAHg0IIhiADQvCBwIeAnoD4AINCBIiEIgNChoyYsODAgYMGfEIEiEKBgoSIkKDAgAGDQid+IANCsODAgYOGjJgwhHw3AwBBCCACQv////8PgyICQv//A4NCIIYgAkKAgPz/D4NCEIiEIgJC/4GAgPAfg0IQhiACQoD+g4CA4D+DQgiIhCICQo+AvIDwgcAHg0IIhiACQvCBwIeAnoD4AINCBIiEIgJChoyYsODAgYMGfEIEiEKBgoSIkKDAgAGDQid+IAJCsODAgYOGjJgwhHw3AwAL",
// 1170 bytes
"AGFzbQEAAAABCAJgAX8AYAAAAwQDAQAABQMBAAEGGgV+AUIAC34BQgALfgFCAAt+AUIAC34BQgALByIEBGluaXQAAAZ1cGRhdGUAAQVmaW5hbAACBm1lbW9yeQIACrIIAzAAQtbrgu7q/Yn14AAkAELP1tO+0ser2UIkAUIAJAJC+erQ0OfJoeThACQDQgAkBAvUAQIBfwR+IABFBEAPCyMEIACtfCQEIwAhAiMBIQMjAiEEIwMhBQNAIAIgASkDAELP1tO+0ser2UJ+fEIfiUKHla+vmLbem55/fiECIAMgASkDCELP1tO+0ser2UJ+fEIfiUKHla+vmLbem55/fiEDIAQgASkDEELP1tO+0ser2UJ+fEIfiUKHla+vmLbem55/fiEEIAUgASkDGELP1tO+0ser2UJ+fEIfiUKHla+vmLbem55/fiEFIAAgAUEgaiIBSw0ACyACJAAgAyQBIAQkAiAFJAMLqAYCAX8EfiMEQgBSBH4jACICQgGJIwEiA0IHiXwjAiIEQgyJfCMDIgVCEol8IAJCz9bTvtLHq9lCfkIfiUKHla+vmLbem55/foVCh5Wvr5i23puef35CnaO16oOxjYr6AH0gA0LP1tO+0ser2UJ+Qh+JQoeVr6+Ytt6bnn9+hUKHla+vmLbem55/fkKdo7Xqg7GNivoAfSAEQs/W077Sx6vZQn5CH4lCh5Wvr5i23puef36FQoeVr6+Ytt6bnn9+Qp2jteqDsY2K+gB9IAVCz9bTvtLHq9lCfkIfiUKHla+vmLbem55/foVCh5Wvr5i23puef35CnaO16oOxjYr6AH0FQsXP2bLx5brqJwsjBCAArXx8IQIDQCABQQhqIABNBEAgAiABKQMAQs/W077Sx6vZQn5CH4lCh5Wvr5i23puef36FQhuJQoeVr6+Ytt6bnn9+Qp2jteqDsY2K+gB9IQIgAUEIaiEBDAELCyABQQRqIABNBEAgAiABNQIAQoeVr6+Ytt6bnn9+hUIXiULP1tO+0ser2UJ+Qvnz3fGZ9pmrFnwhAiABQQRqIQELA0AgACABRwRAIAIgATEAAELFz9my8eW66id+hUILiUKHla+vmLbem55/fiECIAFBAWohAQwBCwtBACACIAJCIYiFQs/W077Sx6vZQn4iAkIdiCAChUL5893xmfaZqxZ+IgJCIIggAoUiAkIgiCIDQv//A4NCIIYgA0KAgPz/D4NCEIiEIgNC/4GAgPAfg0IQhiADQoD+g4CA4D+DQgiIhCIDQo+AvIDwgcAHg0IIhiADQvCBwIeAnoD4AINCBIiEIgNChoyYsODAgYMGfEIEiEKBgoSIkKDAgAGDQid+IANCsODAgYOGjJgwhHw3AwBBCCACQv////8PgyICQv//A4NCIIYgAkKAgPz/D4NCEIiEIgJC/4GAgPAfg0IQhiACQoD+g4CA4D+DQgiIhCICQo+AvIDwgcAHg0IIhiACQvCBwIeAnoD4AINCBIiEIgJChoyYsODAgYMGfEIEiEKBgoSIkKDAgAGDQid+IAJCsODAgYOGjJgwhHw3AwAL",
"base64"
)
);

View File

@ -67,6 +67,16 @@ module.exports = {
require("../dependencies/ContextElementDependency"),
"dependencies/CriticalDependencyWarning": () =>
require("../dependencies/CriticalDependencyWarning"),
"dependencies/CssImportDependency": () =>
require("../dependencies/CssImportDependency"),
"dependencies/CssLocalIdentifierDependency": () =>
require("../dependencies/CssLocalIdentifierDependency"),
"dependencies/CssSelfLocalIdentifierDependency": () =>
require("../dependencies/CssSelfLocalIdentifierDependency"),
"dependencies/CssExportDependency": () =>
require("../dependencies/CssExportDependency"),
"dependencies/CssUrlDependency": () =>
require("../dependencies/CssUrlDependency"),
"dependencies/DelegatedSourceDependency": () =>
require("../dependencies/DelegatedSourceDependency"),
"dependencies/DllEntryDependency": () =>
@ -175,6 +185,7 @@ module.exports = {
ModuleParseError: () => require("../ModuleParseError"),
ModuleWarning: () => require("../ModuleWarning"),
NormalModule: () => require("../NormalModule"),
RawDataUrlModule: () => require("../asset/RawDataUrlModule"),
RawModule: () => require("../RawModule"),
"sharing/ConsumeSharedModule": () =>
require("../sharing/ConsumeSharedModule"),

View File

@ -96,7 +96,7 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
)}]`;
const conditionMap = chunkGraph.getChunkConditionMap(chunk, chunkHasJs);
const hasJsMatcher = compileBooleanMatcher(conditionMap);
const initialChunkIds = getInitialChunkIds(chunk, chunkGraph);
const initialChunkIds = getInitialChunkIds(chunk, chunkGraph, chunkHasJs);
const stateExpression = withHmr
? `${RuntimeGlobals.hmrRuntimeStatePrefix}_jsonp`
@ -419,7 +419,7 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
`if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) && installedChunks[chunkId]) {`,
Template.indent("installedChunks[chunkId][0]();"),
"}",
"installedChunks[chunkIds[i]] = 0;"
"installedChunks[chunkId] = 0;"
]),
"}",
withOnChunkLoad

View File

@ -53,7 +53,7 @@ class ImportScriptsChunkLoadingRuntimeModule extends RuntimeModule {
const hasJsMatcher = compileBooleanMatcher(
chunkGraph.getChunkConditionMap(chunk, chunkHasJs)
);
const initialChunkIds = getInitialChunkIds(chunk, chunkGraph);
const initialChunkIds = getInitialChunkIds(chunk, chunkGraph, chunkHasJs);
const outputName = this.compilation.getPath(
getChunkFilenameTemplate(chunk, this.compilation.outputOptions),

View File

@ -1,6 +1,6 @@
{
"name": "webpack",
"version": "5.65.0",
"version": "5.66.0",
"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.",
"license": "MIT",
@ -19,7 +19,7 @@
"eslint-scope": "5.1.1",
"events": "^3.2.0",
"glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.2.4",
"graceful-fs": "^4.2.9",
"json-parse-better-errors": "^1.0.2",
"loader-runner": "^4.2.0",
"mime-types": "^2.1.27",
@ -143,13 +143,6 @@
"test:integration": "node --expose-gc --max-old-space-size=4096 --experimental-vm-modules --trace-deprecation node_modules/jest-cli/bin/jest --logHeapUsage --testMatch \"<rootDir>/test/*.{basictest,longtest,test}.js\"",
"test:basic": "node --expose-gc --max-old-space-size=4096 --experimental-vm-modules --trace-deprecation node_modules/jest-cli/bin/jest --logHeapUsage --testMatch \"<rootDir>/test/*.basictest.js\"",
"test:unit": "node --max-old-space-size=4096 --experimental-vm-modules --trace-deprecation node_modules/jest-cli/bin/jest --testMatch \"<rootDir>/test/*.unittest.js\"",
"travis:integration": "yarn cover:integration --ci $JEST",
"travis:basic": "yarn cover:basic --ci $JEST",
"travis:lintunit": "yarn lint && yarn cover:unit --ci $JEST",
"travis:benchmark": "yarn benchmark --ci",
"appveyor:integration": "yarn cover:integration --ci %JEST%",
"appveyor:unit": "yarn cover:unit --ci %JEST%",
"appveyor:benchmark": "yarn benchmark --ci",
"build:examples": "cd examples && node buildAll.js",
"type-report": "rimraf coverage && yarn cover:types && yarn cover:report && open-cli coverage/lcov-report/index.html",
"pretest": "yarn lint",

File diff suppressed because one or more lines are too long

View File

@ -335,6 +335,34 @@
"description": "This option enables cross-origin loading of chunks.",
"enum": [false, "anonymous", "use-credentials"]
},
"CssChunkFilename": {
"description": "Specifies the filename template of non-initial output css files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.",
"oneOf": [
{
"$ref": "#/definitions/FilenameTemplate"
}
]
},
"CssFilename": {
"description": "Specifies the filename template of output css files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.",
"oneOf": [
{
"$ref": "#/definitions/FilenameTemplate"
}
]
},
"CssGeneratorOptions": {
"description": "Generator options for css modules.",
"type": "object",
"additionalProperties": false,
"properties": {}
},
"CssParserOptions": {
"description": "Parser options for css modules.",
"type": "object",
"additionalProperties": false,
"properties": {}
},
"Dependencies": {
"description": "References to other configurations to depend on.",
"type": "array",
@ -720,6 +748,10 @@
"description": "Enable additional in memory caching of modules that are unchanged and reference only unchanged modules.",
"type": "boolean"
},
"css": {
"description": "Enable css support.",
"type": "boolean"
},
"futureDefaults": {
"description": "Apply defaults of next major version.",
"type": "boolean"
@ -770,6 +802,10 @@
"description": "Enable additional in memory caching of modules that are unchanged and reference only unchanged modules.",
"type": "boolean"
},
"css": {
"description": "Enable css support.",
"type": "boolean"
},
"futureDefaults": {
"description": "Apply defaults of next major version.",
"type": "boolean"
@ -818,6 +854,10 @@
"description": "Enable additional in memory caching of modules that are unchanged and reference only unchanged modules.",
"type": "boolean"
},
"css": {
"description": "Enable css support.",
"type": "boolean"
},
"futureDefaults": {
"description": "Apply defaults of next major version.",
"type": "boolean"
@ -1010,6 +1050,7 @@
"commonjs",
"commonjs2",
"commonjs-module",
"commonjs-static",
"amd",
"amd-require",
"umd",
@ -1879,7 +1920,7 @@
"required": ["type"]
},
"LibraryType": {
"description": "Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).",
"description": "Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).",
"anyOf": [
{
"enum": [
@ -1894,6 +1935,7 @@
"commonjs",
"commonjs2",
"commonjs-module",
"commonjs-static",
"amd",
"amd-require",
"umd",
@ -2948,6 +2990,12 @@
"crossOriginLoading": {
"$ref": "#/definitions/CrossOriginLoading"
},
"cssChunkFilename": {
"$ref": "#/definitions/CssChunkFilename"
},
"cssFilename": {
"$ref": "#/definitions/CssFilename"
},
"devtoolFallbackModuleFilenameTemplate": {
"$ref": "#/definitions/DevtoolFallbackModuleFilenameTemplate"
},
@ -3141,6 +3189,12 @@
"crossOriginLoading": {
"$ref": "#/definitions/CrossOriginLoading"
},
"cssChunkFilename": {
"$ref": "#/definitions/CssChunkFilename"
},
"cssFilename": {
"$ref": "#/definitions/CssFilename"
},
"devtoolFallbackModuleFilenameTemplate": {
"$ref": "#/definitions/DevtoolFallbackModuleFilenameTemplate"
},

File diff suppressed because one or more lines are too long

View File

@ -218,7 +218,7 @@
"required": ["type"]
},
"LibraryType": {
"description": "Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).",
"description": "Type of library (types included by default are 'var', 'module', 'assign', 'assign-properties', 'this', 'window', 'self', 'global', 'commonjs', 'commonjs2', 'commonjs-module', 'commonjs-static', 'amd', 'amd-require', 'umd', 'umd2', 'jsonp', 'system', but others might be added by plugins).",
"anyOf": [
{
"enum": [
@ -233,6 +233,7 @@
"commonjs",
"commonjs2",
"commonjs-module",
"commonjs-static",
"amd",
"amd-require",
"umd",

File diff suppressed because one or more lines are too long

View File

@ -13,6 +13,7 @@
"commonjs",
"commonjs2",
"commonjs-module",
"commonjs-static",
"amd",
"amd-require",
"umd",

View File

@ -3,4 +3,4 @@
* DO NOT MODIFY BY HAND.
* Run `yarn special-lint-fix` to update
*/
"use strict";function o(r,{instancePath:e="",parentData:s,parentDataProperty:m,rootData:t=r}={}){return"var"!==r&&"module"!==r&&"assign"!==r&&"this"!==r&&"window"!==r&&"self"!==r&&"global"!==r&&"commonjs"!==r&&"commonjs2"!==r&&"commonjs-module"!==r&&"amd"!==r&&"amd-require"!==r&&"umd"!==r&&"umd2"!==r&&"jsonp"!==r&&"system"!==r&&"promise"!==r&&"import"!==r&&"script"!==r&&"node-commonjs"!==r?(o.errors=[{params:{}}],!1):(o.errors=null,!0)}module.exports=o,module.exports.default=o;
"use strict";function o(r,{instancePath:s="",parentData:m,parentDataProperty:t,rootData:e=r}={}){return"var"!==r&&"module"!==r&&"assign"!==r&&"this"!==r&&"window"!==r&&"self"!==r&&"global"!==r&&"commonjs"!==r&&"commonjs2"!==r&&"commonjs-module"!==r&&"commonjs-static"!==r&&"amd"!==r&&"amd-require"!==r&&"umd"!==r&&"umd2"!==r&&"jsonp"!==r&&"system"!==r&&"promise"!==r&&"import"!==r&&"script"!==r&&"node-commonjs"!==r?(o.errors=[{params:{}}],!1):(o.errors=null,!0)}module.exports=o,module.exports.default=o;

File diff suppressed because one or more lines are too long

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